diff options
32 files changed, 364 insertions, 175 deletions
diff --git a/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt b/Documentation/devicetree/bindings/display/panel/innolux,p120zdg-bf1.txt index a9b35265fa13..513f03466aba 100644 --- a/Documentation/devicetree/bindings/display/panel/innolux,tv123wam.txt +++ b/Documentation/devicetree/bindings/display/panel/innolux,p120zdg-bf1.txt | |||
| @@ -1,20 +1,22 @@ | |||
| 1 | Innolux TV123WAM 12.3 inch eDP 2K display panel | 1 | Innolux P120ZDG-BF1 12.02 inch eDP 2K display panel |
| 2 | 2 | ||
| 3 | This binding is compatible with the simple-panel binding, which is specified | 3 | This binding is compatible with the simple-panel binding, which is specified |
| 4 | in simple-panel.txt in this directory. | 4 | in simple-panel.txt in this directory. |
| 5 | 5 | ||
| 6 | Required properties: | 6 | Required properties: |
| 7 | - compatible: should be "innolux,tv123wam" | 7 | - compatible: should be "innolux,p120zdg-bf1" |
| 8 | - power-supply: regulator to provide the supply voltage | 8 | - power-supply: regulator to provide the supply voltage |
| 9 | 9 | ||
| 10 | Optional properties: | 10 | Optional properties: |
| 11 | - enable-gpios: GPIO pin to enable or disable the panel | 11 | - enable-gpios: GPIO pin to enable or disable the panel |
| 12 | - backlight: phandle of the backlight device attached to the panel | 12 | - backlight: phandle of the backlight device attached to the panel |
| 13 | - no-hpd: If HPD isn't hooked up; add this property. | ||
| 13 | 14 | ||
| 14 | Example: | 15 | Example: |
| 15 | panel_edp: panel-edp { | 16 | panel_edp: panel-edp { |
| 16 | compatible = "innolux,tv123wam"; | 17 | compatible = "innolux,p120zdg-bf1"; |
| 17 | enable-gpios = <&msmgpio 31 GPIO_ACTIVE_LOW>; | 18 | enable-gpios = <&msmgpio 31 GPIO_ACTIVE_LOW>; |
| 18 | power-supply = <&pm8916_l2>; | 19 | power-supply = <&pm8916_l2>; |
| 19 | backlight = <&backlight>; | 20 | backlight = <&backlight>; |
| 21 | no-hpd; | ||
| 20 | }; | 22 | }; |
diff --git a/Documentation/devicetree/bindings/display/panel/simple-panel.txt b/Documentation/devicetree/bindings/display/panel/simple-panel.txt index 45a457ad38f0..b2b872c710f2 100644 --- a/Documentation/devicetree/bindings/display/panel/simple-panel.txt +++ b/Documentation/devicetree/bindings/display/panel/simple-panel.txt | |||
| @@ -11,6 +11,9 @@ Optional properties: | |||
| 11 | - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing | 11 | - ddc-i2c-bus: phandle of an I2C controller used for DDC EDID probing |
| 12 | - enable-gpios: GPIO pin to enable or disable the panel | 12 | - enable-gpios: GPIO pin to enable or disable the panel |
| 13 | - backlight: phandle of the backlight device attached to the panel | 13 | - backlight: phandle of the backlight device attached to the panel |
| 14 | - no-hpd: This panel is supposed to communicate that it's ready via HPD | ||
| 15 | (hot plug detect) signal, but the signal isn't hooked up so we should | ||
| 16 | hardcode the max delay from the panel spec when powering up the panel. | ||
| 14 | 17 | ||
| 15 | Example: | 18 | Example: |
| 16 | 19 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index 297a5490ad8c..0a4fba196b84 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c | |||
| @@ -135,7 +135,8 @@ static int acp_poweroff(struct generic_pm_domain *genpd) | |||
| 135 | * 2. power off the acp tiles | 135 | * 2. power off the acp tiles |
| 136 | * 3. check and enter ulv state | 136 | * 3. check and enter ulv state |
| 137 | */ | 137 | */ |
| 138 | if (adev->powerplay.pp_funcs->set_powergating_by_smu) | 138 | if (adev->powerplay.pp_funcs && |
| 139 | adev->powerplay.pp_funcs->set_powergating_by_smu) | ||
| 139 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); | 140 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, true); |
| 140 | } | 141 | } |
| 141 | return 0; | 142 | return 0; |
| @@ -517,7 +518,8 @@ static int acp_set_powergating_state(void *handle, | |||
| 517 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 518 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 518 | bool enable = state == AMD_PG_STATE_GATE ? true : false; | 519 | bool enable = state == AMD_PG_STATE_GATE ? true : false; |
| 519 | 520 | ||
| 520 | if (adev->powerplay.pp_funcs->set_powergating_by_smu) | 521 | if (adev->powerplay.pp_funcs && |
| 522 | adev->powerplay.pp_funcs->set_powergating_by_smu) | ||
| 521 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); | 523 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_ACP, enable); |
| 522 | 524 | ||
| 523 | return 0; | 525 | return 0; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 1e4dd09a5072..30bc345d6fdf 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | |||
| @@ -1493,8 +1493,6 @@ static int amdgpu_device_ip_early_init(struct amdgpu_device *adev) | |||
| 1493 | } | 1493 | } |
| 1494 | 1494 | ||
| 1495 | adev->powerplay.pp_feature = amdgpu_pp_feature_mask; | 1495 | adev->powerplay.pp_feature = amdgpu_pp_feature_mask; |
| 1496 | if (amdgpu_sriov_vf(adev)) | ||
| 1497 | adev->powerplay.pp_feature &= ~PP_GFXOFF_MASK; | ||
| 1498 | 1496 | ||
| 1499 | for (i = 0; i < adev->num_ip_blocks; i++) { | 1497 | for (i = 0; i < adev->num_ip_blocks; i++) { |
| 1500 | if ((amdgpu_ip_block_mask & (1 << i)) == 0) { | 1498 | if ((amdgpu_ip_block_mask & (1 << i)) == 0) { |
| @@ -1600,7 +1598,7 @@ static int amdgpu_device_fw_loading(struct amdgpu_device *adev) | |||
| 1600 | } | 1598 | } |
| 1601 | } | 1599 | } |
| 1602 | 1600 | ||
| 1603 | if (adev->powerplay.pp_funcs->load_firmware) { | 1601 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->load_firmware) { |
| 1604 | r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); | 1602 | r = adev->powerplay.pp_funcs->load_firmware(adev->powerplay.pp_handle); |
| 1605 | if (r) { | 1603 | if (r) { |
| 1606 | pr_err("firmware loading failed\n"); | 1604 | pr_err("firmware loading failed\n"); |
| @@ -3341,7 +3339,7 @@ int amdgpu_device_gpu_recover(struct amdgpu_device *adev, | |||
| 3341 | 3339 | ||
| 3342 | kthread_park(ring->sched.thread); | 3340 | kthread_park(ring->sched.thread); |
| 3343 | 3341 | ||
| 3344 | if (job && job->base.sched == &ring->sched) | 3342 | if (job && job->base.sched != &ring->sched) |
| 3345 | continue; | 3343 | continue; |
| 3346 | 3344 | ||
| 3347 | drm_sched_hw_job_reset(&ring->sched, job ? &job->base : NULL); | 3345 | drm_sched_hw_job_reset(&ring->sched, job ? &job->base : NULL); |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 28781414d71c..943dbf3c5da1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | |||
| @@ -114,8 +114,8 @@ uint amdgpu_pg_mask = 0xffffffff; | |||
| 114 | uint amdgpu_sdma_phase_quantum = 32; | 114 | uint amdgpu_sdma_phase_quantum = 32; |
| 115 | char *amdgpu_disable_cu = NULL; | 115 | char *amdgpu_disable_cu = NULL; |
| 116 | char *amdgpu_virtual_display = NULL; | 116 | char *amdgpu_virtual_display = NULL; |
| 117 | /* OverDrive(bit 14) disabled by default*/ | 117 | /* OverDrive(bit 14),gfxoff(bit 15),stutter mode(bit 17) disabled by default*/ |
| 118 | uint amdgpu_pp_feature_mask = 0xffffbfff; | 118 | uint amdgpu_pp_feature_mask = 0xfffd3fff; |
| 119 | int amdgpu_ngg = 0; | 119 | int amdgpu_ngg = 0; |
| 120 | int amdgpu_prim_buf_per_se = 0; | 120 | int amdgpu_prim_buf_per_se = 0; |
| 121 | int amdgpu_pos_buf_per_se = 0; | 121 | int amdgpu_pos_buf_per_se = 0; |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 790fd5408ddf..1a656b8657f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | |||
| @@ -392,7 +392,7 @@ void amdgpu_gfx_off_ctrl(struct amdgpu_device *adev, bool enable) | |||
| 392 | if (!(adev->powerplay.pp_feature & PP_GFXOFF_MASK)) | 392 | if (!(adev->powerplay.pp_feature & PP_GFXOFF_MASK)) |
| 393 | return; | 393 | return; |
| 394 | 394 | ||
| 395 | if (!adev->powerplay.pp_funcs->set_powergating_by_smu) | 395 | if (!adev->powerplay.pp_funcs || !adev->powerplay.pp_funcs->set_powergating_by_smu) |
| 396 | return; | 396 | return; |
| 397 | 397 | ||
| 398 | 398 | ||
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 94055a485e01..59cc678de8c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c | |||
| @@ -704,7 +704,10 @@ static ssize_t amdgpu_set_pp_dpm_sclk(struct device *dev, | |||
| 704 | return ret; | 704 | return ret; |
| 705 | 705 | ||
| 706 | if (adev->powerplay.pp_funcs->force_clock_level) | 706 | if (adev->powerplay.pp_funcs->force_clock_level) |
| 707 | amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); | 707 | ret = amdgpu_dpm_force_clock_level(adev, PP_SCLK, mask); |
| 708 | |||
| 709 | if (ret) | ||
| 710 | return -EINVAL; | ||
| 708 | 711 | ||
| 709 | return count; | 712 | return count; |
| 710 | } | 713 | } |
| @@ -737,7 +740,10 @@ static ssize_t amdgpu_set_pp_dpm_mclk(struct device *dev, | |||
| 737 | return ret; | 740 | return ret; |
| 738 | 741 | ||
| 739 | if (adev->powerplay.pp_funcs->force_clock_level) | 742 | if (adev->powerplay.pp_funcs->force_clock_level) |
| 740 | amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); | 743 | ret = amdgpu_dpm_force_clock_level(adev, PP_MCLK, mask); |
| 744 | |||
| 745 | if (ret) | ||
| 746 | return -EINVAL; | ||
| 741 | 747 | ||
| 742 | return count; | 748 | return count; |
| 743 | } | 749 | } |
| @@ -770,7 +776,10 @@ static ssize_t amdgpu_set_pp_dpm_pcie(struct device *dev, | |||
| 770 | return ret; | 776 | return ret; |
| 771 | 777 | ||
| 772 | if (adev->powerplay.pp_funcs->force_clock_level) | 778 | if (adev->powerplay.pp_funcs->force_clock_level) |
| 773 | amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); | 779 | ret = amdgpu_dpm_force_clock_level(adev, PP_PCIE, mask); |
| 780 | |||
| 781 | if (ret) | ||
| 782 | return -EINVAL; | ||
| 774 | 783 | ||
| 775 | return count; | 784 | return count; |
| 776 | } | 785 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 6904d794d60a..352b30409060 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | |||
| @@ -542,7 +542,8 @@ static void amdgpu_vm_pt_next_leaf(struct amdgpu_device *adev, | |||
| 542 | struct amdgpu_vm_pt_cursor *cursor) | 542 | struct amdgpu_vm_pt_cursor *cursor) |
| 543 | { | 543 | { |
| 544 | amdgpu_vm_pt_next(adev, cursor); | 544 | amdgpu_vm_pt_next(adev, cursor); |
| 545 | while (amdgpu_vm_pt_descendant(adev, cursor)); | 545 | if (cursor->pfn != ~0ll) |
| 546 | while (amdgpu_vm_pt_descendant(adev, cursor)); | ||
| 546 | } | 547 | } |
| 547 | 548 | ||
| 548 | /** | 549 | /** |
| @@ -3234,8 +3235,10 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) | |||
| 3234 | } | 3235 | } |
| 3235 | rbtree_postorder_for_each_entry_safe(mapping, tmp, | 3236 | rbtree_postorder_for_each_entry_safe(mapping, tmp, |
| 3236 | &vm->va.rb_root, rb) { | 3237 | &vm->va.rb_root, rb) { |
| 3238 | /* Don't remove the mapping here, we don't want to trigger a | ||
| 3239 | * rebalance and the tree is about to be destroyed anyway. | ||
| 3240 | */ | ||
| 3237 | list_del(&mapping->list); | 3241 | list_del(&mapping->list); |
| 3238 | amdgpu_vm_it_remove(mapping, &vm->va); | ||
| 3239 | kfree(mapping); | 3242 | kfree(mapping); |
| 3240 | } | 3243 | } |
| 3241 | list_for_each_entry_safe(mapping, tmp, &vm->freed, list) { | 3244 | list_for_each_entry_safe(mapping, tmp, &vm->freed, list) { |
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index 3d0f277a6523..617b0c8908a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c | |||
| @@ -4815,8 +4815,10 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev) | |||
| 4815 | if (r) | 4815 | if (r) |
| 4816 | goto done; | 4816 | goto done; |
| 4817 | 4817 | ||
| 4818 | /* Test KCQs */ | 4818 | /* Test KCQs - reversing the order of rings seems to fix ring test failure |
| 4819 | for (i = 0; i < adev->gfx.num_compute_rings; i++) { | 4819 | * after GPU reset |
| 4820 | */ | ||
| 4821 | for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) { | ||
| 4820 | ring = &adev->gfx.compute_ring[i]; | 4822 | ring = &adev->gfx.compute_ring[i]; |
| 4821 | ring->ready = true; | 4823 | ring->ready = true; |
| 4822 | r = amdgpu_ring_test_ring(ring); | 4824 | r = amdgpu_ring_test_ring(ring); |
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index 14649f8475f3..fd23ba1226a5 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c | |||
| @@ -280,7 +280,7 @@ void mmhub_v1_0_update_power_gating(struct amdgpu_device *adev, | |||
| 280 | return; | 280 | return; |
| 281 | 281 | ||
| 282 | if (enable && adev->pg_flags & AMD_PG_SUPPORT_MMHUB) { | 282 | if (enable && adev->pg_flags & AMD_PG_SUPPORT_MMHUB) { |
| 283 | if (adev->powerplay.pp_funcs->set_powergating_by_smu) | 283 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->set_powergating_by_smu) |
| 284 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GMC, true); | 284 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_GMC, true); |
| 285 | 285 | ||
| 286 | } | 286 | } |
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index 04fa3d972636..7a8c9172d30a 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c | |||
| @@ -1366,7 +1366,8 @@ static int sdma_v4_0_hw_init(void *handle) | |||
| 1366 | int r; | 1366 | int r; |
| 1367 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; | 1367 | struct amdgpu_device *adev = (struct amdgpu_device *)handle; |
| 1368 | 1368 | ||
| 1369 | if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs->set_powergating_by_smu) | 1369 | if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs && |
| 1370 | adev->powerplay.pp_funcs->set_powergating_by_smu) | ||
| 1370 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, false); | 1371 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, false); |
| 1371 | 1372 | ||
| 1372 | sdma_v4_0_init_golden_registers(adev); | 1373 | sdma_v4_0_init_golden_registers(adev); |
| @@ -1386,7 +1387,8 @@ static int sdma_v4_0_hw_fini(void *handle) | |||
| 1386 | sdma_v4_0_ctx_switch_enable(adev, false); | 1387 | sdma_v4_0_ctx_switch_enable(adev, false); |
| 1387 | sdma_v4_0_enable(adev, false); | 1388 | sdma_v4_0_enable(adev, false); |
| 1388 | 1389 | ||
| 1389 | if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs->set_powergating_by_smu) | 1390 | if (adev->asic_type == CHIP_RAVEN && adev->powerplay.pp_funcs |
| 1391 | && adev->powerplay.pp_funcs->set_powergating_by_smu) | ||
| 1390 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, true); | 1392 | amdgpu_dpm_set_powergating_by_smu(adev, AMD_IP_BLOCK_TYPE_SDMA, true); |
| 1391 | 1393 | ||
| 1392 | return 0; | 1394 | return 0; |
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 e224f23e2215..b0df6dc9a775 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | |||
| @@ -1524,6 +1524,13 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd) | |||
| 1524 | { | 1524 | { |
| 1525 | struct amdgpu_display_manager *dm = bl_get_data(bd); | 1525 | struct amdgpu_display_manager *dm = bl_get_data(bd); |
| 1526 | 1526 | ||
| 1527 | /* | ||
| 1528 | * PWM interperts 0 as 100% rather than 0% because of HW | ||
| 1529 | * limitation for level 0.So limiting minimum brightness level | ||
| 1530 | * to 1. | ||
| 1531 | */ | ||
| 1532 | if (bd->props.brightness < 1) | ||
| 1533 | return 1; | ||
| 1527 | if (dc_link_set_backlight_level(dm->backlight_link, | 1534 | if (dc_link_set_backlight_level(dm->backlight_link, |
| 1528 | bd->props.brightness, 0, 0)) | 1535 | bd->props.brightness, 0, 0)) |
| 1529 | return 0; | 1536 | return 0; |
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c index 0fab64a2a915..12001a006b2d 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_pp_smu.c | |||
| @@ -101,7 +101,7 @@ bool dm_pp_apply_display_requirements( | |||
| 101 | adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1; | 101 | adev->pm.pm_display_cfg.displays[i].controller_id = dc_cfg->pipe_idx + 1; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | if (adev->powerplay.pp_funcs->display_configuration_change) | 104 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_configuration_change) |
| 105 | adev->powerplay.pp_funcs->display_configuration_change( | 105 | adev->powerplay.pp_funcs->display_configuration_change( |
| 106 | adev->powerplay.pp_handle, | 106 | adev->powerplay.pp_handle, |
| 107 | &adev->pm.pm_display_cfg); | 107 | &adev->pm.pm_display_cfg); |
| @@ -304,7 +304,7 @@ bool dm_pp_get_clock_levels_by_type( | |||
| 304 | struct amd_pp_simple_clock_info validation_clks = { 0 }; | 304 | struct amd_pp_simple_clock_info validation_clks = { 0 }; |
| 305 | uint32_t i; | 305 | uint32_t i; |
| 306 | 306 | ||
| 307 | if (adev->powerplay.pp_funcs->get_clock_by_type) { | 307 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_clock_by_type) { |
| 308 | if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle, | 308 | if (adev->powerplay.pp_funcs->get_clock_by_type(pp_handle, |
| 309 | dc_to_pp_clock_type(clk_type), &pp_clks)) { | 309 | dc_to_pp_clock_type(clk_type), &pp_clks)) { |
| 310 | /* Error in pplib. Provide default values. */ | 310 | /* Error in pplib. Provide default values. */ |
| @@ -315,7 +315,7 @@ bool dm_pp_get_clock_levels_by_type( | |||
| 315 | 315 | ||
| 316 | pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type); | 316 | pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type); |
| 317 | 317 | ||
| 318 | if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks) { | 318 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_display_mode_validation_clocks) { |
| 319 | if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks( | 319 | if (adev->powerplay.pp_funcs->get_display_mode_validation_clocks( |
| 320 | pp_handle, &validation_clks)) { | 320 | pp_handle, &validation_clks)) { |
| 321 | /* Error in pplib. Provide default values. */ | 321 | /* Error in pplib. Provide default values. */ |
| @@ -398,6 +398,9 @@ bool dm_pp_get_clock_levels_by_type_with_voltage( | |||
| 398 | struct pp_clock_levels_with_voltage pp_clk_info = {0}; | 398 | struct pp_clock_levels_with_voltage pp_clk_info = {0}; |
| 399 | const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; | 399 | const struct amd_pm_funcs *pp_funcs = adev->powerplay.pp_funcs; |
| 400 | 400 | ||
| 401 | if (!pp_funcs || !pp_funcs->get_clock_by_type_with_voltage) | ||
| 402 | return false; | ||
| 403 | |||
| 401 | if (pp_funcs->get_clock_by_type_with_voltage(pp_handle, | 404 | if (pp_funcs->get_clock_by_type_with_voltage(pp_handle, |
| 402 | dc_to_pp_clock_type(clk_type), | 405 | dc_to_pp_clock_type(clk_type), |
| 403 | &pp_clk_info)) | 406 | &pp_clk_info)) |
| @@ -438,7 +441,7 @@ bool dm_pp_apply_clock_for_voltage_request( | |||
| 438 | if (!pp_clock_request.clock_type) | 441 | if (!pp_clock_request.clock_type) |
| 439 | return false; | 442 | return false; |
| 440 | 443 | ||
| 441 | if (adev->powerplay.pp_funcs->display_clock_voltage_request) | 444 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->display_clock_voltage_request) |
| 442 | ret = adev->powerplay.pp_funcs->display_clock_voltage_request( | 445 | ret = adev->powerplay.pp_funcs->display_clock_voltage_request( |
| 443 | adev->powerplay.pp_handle, | 446 | adev->powerplay.pp_handle, |
| 444 | &pp_clock_request); | 447 | &pp_clock_request); |
| @@ -455,7 +458,7 @@ bool dm_pp_get_static_clocks( | |||
| 455 | struct amd_pp_clock_info pp_clk_info = {0}; | 458 | struct amd_pp_clock_info pp_clk_info = {0}; |
| 456 | int ret = 0; | 459 | int ret = 0; |
| 457 | 460 | ||
| 458 | if (adev->powerplay.pp_funcs->get_current_clocks) | 461 | if (adev->powerplay.pp_funcs && adev->powerplay.pp_funcs->get_current_clocks) |
| 459 | ret = adev->powerplay.pp_funcs->get_current_clocks( | 462 | ret = adev->powerplay.pp_funcs->get_current_clocks( |
| 460 | adev->powerplay.pp_handle, | 463 | adev->powerplay.pp_handle, |
| 461 | &pp_clk_info); | 464 | &pp_clk_info); |
| @@ -505,6 +508,9 @@ void pp_rv_set_wm_ranges(struct pp_smu *pp, | |||
| 505 | wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets; | 508 | wm_with_clock_ranges.num_wm_dmif_sets = ranges->num_reader_wm_sets; |
| 506 | wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets; | 509 | wm_with_clock_ranges.num_wm_mcif_sets = ranges->num_writer_wm_sets; |
| 507 | 510 | ||
| 511 | if (!pp_funcs || !pp_funcs->set_watermarks_for_clocks_ranges) | ||
| 512 | return; | ||
| 513 | |||
| 508 | for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) { | 514 | for (i = 0; i < wm_with_clock_ranges.num_wm_dmif_sets; i++) { |
| 509 | if (ranges->reader_wm_sets[i].wm_inst > 3) | 515 | if (ranges->reader_wm_sets[i].wm_inst > 3) |
| 510 | wm_dce_clocks[i].wm_set_id = WM_SET_A; | 516 | wm_dce_clocks[i].wm_set_id = WM_SET_A; |
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 de190935f0a4..e3624ca24574 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c | |||
| @@ -568,7 +568,7 @@ static struct input_pixel_processor *dce110_ipp_create( | |||
| 568 | 568 | ||
| 569 | static const struct encoder_feature_support link_enc_feature = { | 569 | static const struct encoder_feature_support link_enc_feature = { |
| 570 | .max_hdmi_deep_color = COLOR_DEPTH_121212, | 570 | .max_hdmi_deep_color = COLOR_DEPTH_121212, |
| 571 | .max_hdmi_pixel_clock = 594000, | 571 | .max_hdmi_pixel_clock = 300000, |
| 572 | .flags.bits.IS_HBR2_CAPABLE = true, | 572 | .flags.bits.IS_HBR2_CAPABLE = true, |
| 573 | .flags.bits.IS_TPS3_CAPABLE = true | 573 | .flags.bits.IS_TPS3_CAPABLE = true |
| 574 | }; | 574 | }; |
diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index e8964cae6b93..d6aa1d414320 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c | |||
| @@ -723,11 +723,14 @@ static int pp_dpm_force_clock_level(void *handle, | |||
| 723 | pr_info("%s was not implemented.\n", __func__); | 723 | pr_info("%s was not implemented.\n", __func__); |
| 724 | return 0; | 724 | return 0; |
| 725 | } | 725 | } |
| 726 | |||
| 727 | if (hwmgr->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL) { | ||
| 728 | pr_info("force clock level is for dpm manual mode only.\n"); | ||
| 729 | return -EINVAL; | ||
| 730 | } | ||
| 731 | |||
| 726 | mutex_lock(&hwmgr->smu_lock); | 732 | mutex_lock(&hwmgr->smu_lock); |
| 727 | if (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_MANUAL) | 733 | ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); |
| 728 | ret = hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); | ||
| 729 | else | ||
| 730 | ret = -EINVAL; | ||
| 731 | mutex_unlock(&hwmgr->smu_lock); | 734 | mutex_unlock(&hwmgr->smu_lock); |
| 732 | return ret; | 735 | return ret; |
| 733 | } | 736 | } |
| @@ -963,6 +966,7 @@ static int pp_dpm_switch_power_profile(void *handle, | |||
| 963 | static int pp_set_power_limit(void *handle, uint32_t limit) | 966 | static int pp_set_power_limit(void *handle, uint32_t limit) |
| 964 | { | 967 | { |
| 965 | struct pp_hwmgr *hwmgr = handle; | 968 | struct pp_hwmgr *hwmgr = handle; |
| 969 | uint32_t max_power_limit; | ||
| 966 | 970 | ||
| 967 | if (!hwmgr || !hwmgr->pm_en) | 971 | if (!hwmgr || !hwmgr->pm_en) |
| 968 | return -EINVAL; | 972 | return -EINVAL; |
| @@ -975,7 +979,13 @@ static int pp_set_power_limit(void *handle, uint32_t limit) | |||
| 975 | if (limit == 0) | 979 | if (limit == 0) |
| 976 | limit = hwmgr->default_power_limit; | 980 | limit = hwmgr->default_power_limit; |
| 977 | 981 | ||
| 978 | if (limit > hwmgr->default_power_limit) | 982 | max_power_limit = hwmgr->default_power_limit; |
| 983 | if (hwmgr->od_enabled) { | ||
| 984 | max_power_limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); | ||
| 985 | max_power_limit /= 100; | ||
| 986 | } | ||
| 987 | |||
| 988 | if (limit > max_power_limit) | ||
| 979 | return -EINVAL; | 989 | return -EINVAL; |
| 980 | 990 | ||
| 981 | mutex_lock(&hwmgr->smu_lock); | 991 | mutex_lock(&hwmgr->smu_lock); |
| @@ -994,8 +1004,13 @@ static int pp_get_power_limit(void *handle, uint32_t *limit, bool default_limit) | |||
| 994 | 1004 | ||
| 995 | mutex_lock(&hwmgr->smu_lock); | 1005 | mutex_lock(&hwmgr->smu_lock); |
| 996 | 1006 | ||
| 997 | if (default_limit) | 1007 | if (default_limit) { |
| 998 | *limit = hwmgr->default_power_limit; | 1008 | *limit = hwmgr->default_power_limit; |
| 1009 | if (hwmgr->od_enabled) { | ||
| 1010 | *limit *= (100 + hwmgr->platform_descriptor.TDPODLimit); | ||
| 1011 | *limit /= 100; | ||
| 1012 | } | ||
| 1013 | } | ||
| 999 | else | 1014 | else |
| 1000 | *limit = hwmgr->power_limit; | 1015 | *limit = hwmgr->power_limit; |
| 1001 | 1016 | ||
| @@ -1303,12 +1318,12 @@ static int pp_enable_mgpu_fan_boost(void *handle) | |||
| 1303 | { | 1318 | { |
| 1304 | struct pp_hwmgr *hwmgr = handle; | 1319 | struct pp_hwmgr *hwmgr = handle; |
| 1305 | 1320 | ||
| 1306 | if (!hwmgr || !hwmgr->pm_en) | 1321 | if (!hwmgr) |
| 1307 | return -EINVAL; | 1322 | return -EINVAL; |
| 1308 | 1323 | ||
| 1309 | if (hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) { | 1324 | if (!hwmgr->pm_en || |
| 1325 | hwmgr->hwmgr_func->enable_mgpu_fan_boost == NULL) | ||
| 1310 | return 0; | 1326 | return 0; |
| 1311 | } | ||
| 1312 | 1327 | ||
| 1313 | mutex_lock(&hwmgr->smu_lock); | 1328 | mutex_lock(&hwmgr->smu_lock); |
| 1314 | hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr); | 1329 | hwmgr->hwmgr_func->enable_mgpu_fan_boost(hwmgr); |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 6c99cbf51c08..ed35ec0341e6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c | |||
| @@ -3588,9 +3588,10 @@ static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, cons | |||
| 3588 | break; | 3588 | break; |
| 3589 | } | 3589 | } |
| 3590 | 3590 | ||
| 3591 | if (i >= sclk_table->count) | 3591 | if (i >= sclk_table->count) { |
| 3592 | data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; | 3592 | data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; |
| 3593 | else { | 3593 | sclk_table->dpm_levels[i-1].value = sclk; |
| 3594 | } else { | ||
| 3594 | /* TODO: Check SCLK in DAL's minimum clocks | 3595 | /* TODO: Check SCLK in DAL's minimum clocks |
| 3595 | * in case DeepSleep divider update is required. | 3596 | * in case DeepSleep divider update is required. |
| 3596 | */ | 3597 | */ |
| @@ -3605,9 +3606,10 @@ static int smu7_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, cons | |||
| 3605 | break; | 3606 | break; |
| 3606 | } | 3607 | } |
| 3607 | 3608 | ||
| 3608 | if (i >= mclk_table->count) | 3609 | if (i >= mclk_table->count) { |
| 3609 | data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; | 3610 | data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; |
| 3610 | 3611 | mclk_table->dpm_levels[i-1].value = mclk; | |
| 3612 | } | ||
| 3611 | 3613 | ||
| 3612 | if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) | 3614 | if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) |
| 3613 | data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; | 3615 | data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c index 4714b5b59825..99a33c33a32c 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c | |||
| @@ -718,7 +718,7 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table, | |||
| 718 | table->WatermarkRow[1][i].MaxClock = | 718 | table->WatermarkRow[1][i].MaxClock = |
| 719 | cpu_to_le16((uint16_t) | 719 | cpu_to_le16((uint16_t) |
| 720 | (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz) / | 720 | (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz) / |
| 721 | 100); | 721 | 1000); |
| 722 | table->WatermarkRow[1][i].MinUclk = | 722 | table->WatermarkRow[1][i].MinUclk = |
| 723 | cpu_to_le16((uint16_t) | 723 | cpu_to_le16((uint16_t) |
| 724 | (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz) / | 724 | (wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz) / |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 419a1d77d661..8c4db86bb4b7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c | |||
| @@ -1333,7 +1333,6 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) | |||
| 1333 | if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) | 1333 | if (hwmgr->platform_descriptor.overdriveLimit.memoryClock == 0) |
| 1334 | hwmgr->platform_descriptor.overdriveLimit.memoryClock = | 1334 | hwmgr->platform_descriptor.overdriveLimit.memoryClock = |
| 1335 | dpm_table->dpm_levels[dpm_table->count-1].value; | 1335 | dpm_table->dpm_levels[dpm_table->count-1].value; |
| 1336 | |||
| 1337 | vega10_init_dpm_state(&(dpm_table->dpm_state)); | 1336 | vega10_init_dpm_state(&(dpm_table->dpm_state)); |
| 1338 | 1337 | ||
| 1339 | data->dpm_table.eclk_table.count = 0; | 1338 | data->dpm_table.eclk_table.count = 0; |
| @@ -3249,6 +3248,37 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, | |||
| 3249 | static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) | 3248 | static int vega10_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) |
| 3250 | { | 3249 | { |
| 3251 | struct vega10_hwmgr *data = hwmgr->backend; | 3250 | struct vega10_hwmgr *data = hwmgr->backend; |
| 3251 | const struct phm_set_power_state_input *states = | ||
| 3252 | (const struct phm_set_power_state_input *)input; | ||
| 3253 | const struct vega10_power_state *vega10_ps = | ||
| 3254 | cast_const_phw_vega10_power_state(states->pnew_state); | ||
| 3255 | struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); | ||
| 3256 | uint32_t sclk = vega10_ps->performance_levels | ||
| 3257 | [vega10_ps->performance_level_count - 1].gfx_clock; | ||
| 3258 | struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); | ||
| 3259 | uint32_t mclk = vega10_ps->performance_levels | ||
| 3260 | [vega10_ps->performance_level_count - 1].mem_clock; | ||
| 3261 | uint32_t i; | ||
| 3262 | |||
| 3263 | for (i = 0; i < sclk_table->count; i++) { | ||
| 3264 | if (sclk == sclk_table->dpm_levels[i].value) | ||
| 3265 | break; | ||
| 3266 | } | ||
| 3267 | |||
| 3268 | if (i >= sclk_table->count) { | ||
| 3269 | data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; | ||
| 3270 | sclk_table->dpm_levels[i-1].value = sclk; | ||
| 3271 | } | ||
| 3272 | |||
| 3273 | for (i = 0; i < mclk_table->count; i++) { | ||
| 3274 | if (mclk == mclk_table->dpm_levels[i].value) | ||
| 3275 | break; | ||
| 3276 | } | ||
| 3277 | |||
| 3278 | if (i >= mclk_table->count) { | ||
| 3279 | data->need_update_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; | ||
| 3280 | mclk_table->dpm_levels[i-1].value = mclk; | ||
| 3281 | } | ||
| 3252 | 3282 | ||
| 3253 | if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) | 3283 | if (data->display_timing.num_existing_displays != hwmgr->display_config->num_display) |
| 3254 | data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK; | 3284 | data->need_update_dpm_table |= DPMTABLE_UPDATE_MCLK; |
| @@ -4529,11 +4559,13 @@ static int vega10_set_sclk_od(struct pp_hwmgr *hwmgr, uint32_t value) | |||
| 4529 | 4559 | ||
| 4530 | if (vega10_ps->performance_levels | 4560 | if (vega10_ps->performance_levels |
| 4531 | [vega10_ps->performance_level_count - 1].gfx_clock > | 4561 | [vega10_ps->performance_level_count - 1].gfx_clock > |
| 4532 | hwmgr->platform_descriptor.overdriveLimit.engineClock) | 4562 | hwmgr->platform_descriptor.overdriveLimit.engineClock) { |
| 4533 | vega10_ps->performance_levels | 4563 | vega10_ps->performance_levels |
| 4534 | [vega10_ps->performance_level_count - 1].gfx_clock = | 4564 | [vega10_ps->performance_level_count - 1].gfx_clock = |
| 4535 | hwmgr->platform_descriptor.overdriveLimit.engineClock; | 4565 | hwmgr->platform_descriptor.overdriveLimit.engineClock; |
| 4536 | 4566 | pr_warn("max sclk supported by vbios is %d\n", | |
| 4567 | hwmgr->platform_descriptor.overdriveLimit.engineClock); | ||
| 4568 | } | ||
| 4537 | return 0; | 4569 | return 0; |
| 4538 | } | 4570 | } |
| 4539 | 4571 | ||
| @@ -4581,10 +4613,13 @@ static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) | |||
| 4581 | 4613 | ||
| 4582 | if (vega10_ps->performance_levels | 4614 | if (vega10_ps->performance_levels |
| 4583 | [vega10_ps->performance_level_count - 1].mem_clock > | 4615 | [vega10_ps->performance_level_count - 1].mem_clock > |
| 4584 | hwmgr->platform_descriptor.overdriveLimit.memoryClock) | 4616 | hwmgr->platform_descriptor.overdriveLimit.memoryClock) { |
| 4585 | vega10_ps->performance_levels | 4617 | vega10_ps->performance_levels |
| 4586 | [vega10_ps->performance_level_count - 1].mem_clock = | 4618 | [vega10_ps->performance_level_count - 1].mem_clock = |
| 4587 | hwmgr->platform_descriptor.overdriveLimit.memoryClock; | 4619 | hwmgr->platform_descriptor.overdriveLimit.memoryClock; |
| 4620 | pr_warn("max mclk supported by vbios is %d\n", | ||
| 4621 | hwmgr->platform_descriptor.overdriveLimit.memoryClock); | ||
| 4622 | } | ||
| 4588 | 4623 | ||
| 4589 | return 0; | 4624 | return 0; |
| 4590 | } | 4625 | } |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index 9600e2f226e9..74bc37308dc0 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c | |||
| @@ -2356,6 +2356,13 @@ static int vega12_gfx_off_control(struct pp_hwmgr *hwmgr, bool enable) | |||
| 2356 | return vega12_disable_gfx_off(hwmgr); | 2356 | return vega12_disable_gfx_off(hwmgr); |
| 2357 | } | 2357 | } |
| 2358 | 2358 | ||
| 2359 | static int vega12_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, | ||
| 2360 | PHM_PerformanceLevelDesignation designation, uint32_t index, | ||
| 2361 | PHM_PerformanceLevel *level) | ||
| 2362 | { | ||
| 2363 | return 0; | ||
| 2364 | } | ||
| 2365 | |||
| 2359 | static const struct pp_hwmgr_func vega12_hwmgr_funcs = { | 2366 | static const struct pp_hwmgr_func vega12_hwmgr_funcs = { |
| 2360 | .backend_init = vega12_hwmgr_backend_init, | 2367 | .backend_init = vega12_hwmgr_backend_init, |
| 2361 | .backend_fini = vega12_hwmgr_backend_fini, | 2368 | .backend_fini = vega12_hwmgr_backend_fini, |
| @@ -2406,6 +2413,7 @@ static const struct pp_hwmgr_func vega12_hwmgr_funcs = { | |||
| 2406 | .register_irq_handlers = smu9_register_irq_handlers, | 2413 | .register_irq_handlers = smu9_register_irq_handlers, |
| 2407 | .start_thermal_controller = vega12_start_thermal_controller, | 2414 | .start_thermal_controller = vega12_start_thermal_controller, |
| 2408 | .powergate_gfx = vega12_gfx_off_control, | 2415 | .powergate_gfx = vega12_gfx_off_control, |
| 2416 | .get_performance_level = vega12_get_performance_level, | ||
| 2409 | }; | 2417 | }; |
| 2410 | 2418 | ||
| 2411 | int vega12_hwmgr_init(struct pp_hwmgr *hwmgr) | 2419 | int vega12_hwmgr_init(struct pp_hwmgr *hwmgr) |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index b4dbbb7c334c..57143d51e3ee 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c | |||
| @@ -1875,38 +1875,20 @@ static int vega20_get_gpu_power(struct pp_hwmgr *hwmgr, | |||
| 1875 | return ret; | 1875 | return ret; |
| 1876 | } | 1876 | } |
| 1877 | 1877 | ||
| 1878 | static int vega20_get_current_gfx_clk_freq(struct pp_hwmgr *hwmgr, uint32_t *gfx_freq) | 1878 | static int vega20_get_current_clk_freq(struct pp_hwmgr *hwmgr, |
| 1879 | PPCLK_e clk_id, uint32_t *clk_freq) | ||
| 1879 | { | 1880 | { |
| 1880 | uint32_t gfx_clk = 0; | ||
| 1881 | int ret = 0; | 1881 | int ret = 0; |
| 1882 | 1882 | ||
| 1883 | *gfx_freq = 0; | 1883 | *clk_freq = 0; |
| 1884 | 1884 | ||
| 1885 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, | 1885 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, |
| 1886 | PPSMC_MSG_GetDpmClockFreq, (PPCLK_GFXCLK << 16))) == 0, | 1886 | PPSMC_MSG_GetDpmClockFreq, (clk_id << 16))) == 0, |
| 1887 | "[GetCurrentGfxClkFreq] Attempt to get Current GFXCLK Frequency Failed!", | 1887 | "[GetCurrentClkFreq] Attempt to get Current Frequency Failed!", |
| 1888 | return ret); | 1888 | return ret); |
| 1889 | gfx_clk = smum_get_argument(hwmgr); | 1889 | *clk_freq = smum_get_argument(hwmgr); |
| 1890 | 1890 | ||
| 1891 | *gfx_freq = gfx_clk * 100; | 1891 | *clk_freq = *clk_freq * 100; |
| 1892 | |||
| 1893 | return 0; | ||
| 1894 | } | ||
| 1895 | |||
| 1896 | static int vega20_get_current_mclk_freq(struct pp_hwmgr *hwmgr, uint32_t *mclk_freq) | ||
| 1897 | { | ||
| 1898 | uint32_t mem_clk = 0; | ||
| 1899 | int ret = 0; | ||
| 1900 | |||
| 1901 | *mclk_freq = 0; | ||
| 1902 | |||
| 1903 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter(hwmgr, | ||
| 1904 | PPSMC_MSG_GetDpmClockFreq, (PPCLK_UCLK << 16))) == 0, | ||
| 1905 | "[GetCurrentMClkFreq] Attempt to get Current MCLK Frequency Failed!", | ||
| 1906 | return ret); | ||
| 1907 | mem_clk = smum_get_argument(hwmgr); | ||
| 1908 | |||
| 1909 | *mclk_freq = mem_clk * 100; | ||
| 1910 | 1892 | ||
| 1911 | return 0; | 1893 | return 0; |
| 1912 | } | 1894 | } |
| @@ -1937,12 +1919,16 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx, | |||
| 1937 | 1919 | ||
| 1938 | switch (idx) { | 1920 | switch (idx) { |
| 1939 | case AMDGPU_PP_SENSOR_GFX_SCLK: | 1921 | case AMDGPU_PP_SENSOR_GFX_SCLK: |
| 1940 | ret = vega20_get_current_gfx_clk_freq(hwmgr, (uint32_t *)value); | 1922 | ret = vega20_get_current_clk_freq(hwmgr, |
| 1923 | PPCLK_GFXCLK, | ||
| 1924 | (uint32_t *)value); | ||
| 1941 | if (!ret) | 1925 | if (!ret) |
| 1942 | *size = 4; | 1926 | *size = 4; |
| 1943 | break; | 1927 | break; |
| 1944 | case AMDGPU_PP_SENSOR_GFX_MCLK: | 1928 | case AMDGPU_PP_SENSOR_GFX_MCLK: |
| 1945 | ret = vega20_get_current_mclk_freq(hwmgr, (uint32_t *)value); | 1929 | ret = vega20_get_current_clk_freq(hwmgr, |
| 1930 | PPCLK_UCLK, | ||
| 1931 | (uint32_t *)value); | ||
| 1946 | if (!ret) | 1932 | if (!ret) |
| 1947 | *size = 4; | 1933 | *size = 4; |
| 1948 | break; | 1934 | break; |
| @@ -2012,7 +1998,6 @@ int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr, | |||
| 2012 | if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { | 1998 | if (data->smu_features[GNLD_DPM_DCEFCLK].enabled) { |
| 2013 | switch (clk_type) { | 1999 | switch (clk_type) { |
| 2014 | case amd_pp_dcef_clock: | 2000 | case amd_pp_dcef_clock: |
| 2015 | clk_freq = clock_req->clock_freq_in_khz / 100; | ||
| 2016 | clk_select = PPCLK_DCEFCLK; | 2001 | clk_select = PPCLK_DCEFCLK; |
| 2017 | break; | 2002 | break; |
| 2018 | case amd_pp_disp_clock: | 2003 | case amd_pp_disp_clock: |
| @@ -2041,11 +2026,20 @@ int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr, | |||
| 2041 | return result; | 2026 | return result; |
| 2042 | } | 2027 | } |
| 2043 | 2028 | ||
| 2029 | static int vega20_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, | ||
| 2030 | PHM_PerformanceLevelDesignation designation, uint32_t index, | ||
| 2031 | PHM_PerformanceLevel *level) | ||
| 2032 | { | ||
| 2033 | return 0; | ||
| 2034 | } | ||
| 2035 | |||
| 2044 | static int vega20_notify_smc_display_config_after_ps_adjustment( | 2036 | static int vega20_notify_smc_display_config_after_ps_adjustment( |
| 2045 | struct pp_hwmgr *hwmgr) | 2037 | struct pp_hwmgr *hwmgr) |
| 2046 | { | 2038 | { |
| 2047 | struct vega20_hwmgr *data = | 2039 | struct vega20_hwmgr *data = |
| 2048 | (struct vega20_hwmgr *)(hwmgr->backend); | 2040 | (struct vega20_hwmgr *)(hwmgr->backend); |
| 2041 | struct vega20_single_dpm_table *dpm_table = | ||
| 2042 | &data->dpm_table.mem_table; | ||
| 2049 | struct PP_Clocks min_clocks = {0}; | 2043 | struct PP_Clocks min_clocks = {0}; |
| 2050 | struct pp_display_clock_request clock_req; | 2044 | struct pp_display_clock_request clock_req; |
| 2051 | int ret = 0; | 2045 | int ret = 0; |
| @@ -2063,7 +2057,7 @@ static int vega20_notify_smc_display_config_after_ps_adjustment( | |||
| 2063 | 2057 | ||
| 2064 | if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { | 2058 | if (data->smu_features[GNLD_DPM_DCEFCLK].supported) { |
| 2065 | clock_req.clock_type = amd_pp_dcef_clock; | 2059 | clock_req.clock_type = amd_pp_dcef_clock; |
| 2066 | clock_req.clock_freq_in_khz = min_clocks.dcefClock; | 2060 | clock_req.clock_freq_in_khz = min_clocks.dcefClock * 10; |
| 2067 | if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) { | 2061 | if (!vega20_display_clock_voltage_request(hwmgr, &clock_req)) { |
| 2068 | if (data->smu_features[GNLD_DS_DCEFCLK].supported) | 2062 | if (data->smu_features[GNLD_DS_DCEFCLK].supported) |
| 2069 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter( | 2063 | PP_ASSERT_WITH_CODE((ret = smum_send_msg_to_smc_with_parameter( |
| @@ -2076,6 +2070,15 @@ static int vega20_notify_smc_display_config_after_ps_adjustment( | |||
| 2076 | } | 2070 | } |
| 2077 | } | 2071 | } |
| 2078 | 2072 | ||
| 2073 | if (data->smu_features[GNLD_DPM_UCLK].enabled) { | ||
| 2074 | dpm_table->dpm_state.hard_min_level = min_clocks.memoryClock / 100; | ||
| 2075 | PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(hwmgr, | ||
| 2076 | PPSMC_MSG_SetHardMinByFreq, | ||
| 2077 | (PPCLK_UCLK << 16 ) | dpm_table->dpm_state.hard_min_level)), | ||
| 2078 | "[SetHardMinFreq] Set hard min uclk failed!", | ||
| 2079 | return ret); | ||
| 2080 | } | ||
| 2081 | |||
| 2079 | return 0; | 2082 | return 0; |
| 2080 | } | 2083 | } |
| 2081 | 2084 | ||
| @@ -2353,7 +2356,7 @@ static int vega20_get_sclks(struct pp_hwmgr *hwmgr, | |||
| 2353 | 2356 | ||
| 2354 | for (i = 0; i < count; i++) { | 2357 | for (i = 0; i < count; i++) { |
| 2355 | clocks->data[i].clocks_in_khz = | 2358 | clocks->data[i].clocks_in_khz = |
| 2356 | dpm_table->dpm_levels[i].value * 100; | 2359 | dpm_table->dpm_levels[i].value * 1000; |
| 2357 | clocks->data[i].latency_in_us = 0; | 2360 | clocks->data[i].latency_in_us = 0; |
| 2358 | } | 2361 | } |
| 2359 | 2362 | ||
| @@ -2383,7 +2386,7 @@ static int vega20_get_memclocks(struct pp_hwmgr *hwmgr, | |||
| 2383 | for (i = 0; i < count; i++) { | 2386 | for (i = 0; i < count; i++) { |
| 2384 | clocks->data[i].clocks_in_khz = | 2387 | clocks->data[i].clocks_in_khz = |
| 2385 | data->mclk_latency_table.entries[i].frequency = | 2388 | data->mclk_latency_table.entries[i].frequency = |
| 2386 | dpm_table->dpm_levels[i].value * 100; | 2389 | dpm_table->dpm_levels[i].value * 1000; |
| 2387 | clocks->data[i].latency_in_us = | 2390 | clocks->data[i].latency_in_us = |
| 2388 | data->mclk_latency_table.entries[i].latency = | 2391 | data->mclk_latency_table.entries[i].latency = |
| 2389 | vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); | 2392 | vega20_get_mem_latency(hwmgr, dpm_table->dpm_levels[i].value); |
| @@ -2408,7 +2411,7 @@ static int vega20_get_dcefclocks(struct pp_hwmgr *hwmgr, | |||
| 2408 | 2411 | ||
| 2409 | for (i = 0; i < count; i++) { | 2412 | for (i = 0; i < count; i++) { |
| 2410 | clocks->data[i].clocks_in_khz = | 2413 | clocks->data[i].clocks_in_khz = |
| 2411 | dpm_table->dpm_levels[i].value * 100; | 2414 | dpm_table->dpm_levels[i].value * 1000; |
| 2412 | clocks->data[i].latency_in_us = 0; | 2415 | clocks->data[i].latency_in_us = 0; |
| 2413 | } | 2416 | } |
| 2414 | 2417 | ||
| @@ -2431,7 +2434,7 @@ static int vega20_get_socclocks(struct pp_hwmgr *hwmgr, | |||
| 2431 | 2434 | ||
| 2432 | for (i = 0; i < count; i++) { | 2435 | for (i = 0; i < count; i++) { |
| 2433 | clocks->data[i].clocks_in_khz = | 2436 | clocks->data[i].clocks_in_khz = |
| 2434 | dpm_table->dpm_levels[i].value * 100; | 2437 | dpm_table->dpm_levels[i].value * 1000; |
| 2435 | clocks->data[i].latency_in_us = 0; | 2438 | clocks->data[i].latency_in_us = 0; |
| 2436 | } | 2439 | } |
| 2437 | 2440 | ||
| @@ -2582,11 +2585,11 @@ static int vega20_odn_edit_dpm_table(struct pp_hwmgr *hwmgr, | |||
| 2582 | return -EINVAL; | 2585 | return -EINVAL; |
| 2583 | } | 2586 | } |
| 2584 | 2587 | ||
| 2585 | if (input_clk < clocks.data[0].clocks_in_khz / 100 || | 2588 | if (input_clk < clocks.data[0].clocks_in_khz / 1000 || |
| 2586 | input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) { | 2589 | input_clk > od8_settings[OD8_SETTING_UCLK_FMAX].max_value) { |
| 2587 | pr_info("clock freq %d is not within allowed range [%d - %d]\n", | 2590 | pr_info("clock freq %d is not within allowed range [%d - %d]\n", |
| 2588 | input_clk, | 2591 | input_clk, |
| 2589 | clocks.data[0].clocks_in_khz / 100, | 2592 | clocks.data[0].clocks_in_khz / 1000, |
| 2590 | od8_settings[OD8_SETTING_UCLK_FMAX].max_value); | 2593 | od8_settings[OD8_SETTING_UCLK_FMAX].max_value); |
| 2591 | return -EINVAL; | 2594 | return -EINVAL; |
| 2592 | } | 2595 | } |
| @@ -2726,7 +2729,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, | |||
| 2726 | 2729 | ||
| 2727 | switch (type) { | 2730 | switch (type) { |
| 2728 | case PP_SCLK: | 2731 | case PP_SCLK: |
| 2729 | ret = vega20_get_current_gfx_clk_freq(hwmgr, &now); | 2732 | ret = vega20_get_current_clk_freq(hwmgr, PPCLK_GFXCLK, &now); |
| 2730 | PP_ASSERT_WITH_CODE(!ret, | 2733 | PP_ASSERT_WITH_CODE(!ret, |
| 2731 | "Attempt to get current gfx clk Failed!", | 2734 | "Attempt to get current gfx clk Failed!", |
| 2732 | return ret); | 2735 | return ret); |
| @@ -2738,12 +2741,12 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, | |||
| 2738 | 2741 | ||
| 2739 | for (i = 0; i < clocks.num_levels; i++) | 2742 | for (i = 0; i < clocks.num_levels; i++) |
| 2740 | size += sprintf(buf + size, "%d: %uMhz %s\n", | 2743 | size += sprintf(buf + size, "%d: %uMhz %s\n", |
| 2741 | i, clocks.data[i].clocks_in_khz / 100, | 2744 | i, clocks.data[i].clocks_in_khz / 1000, |
| 2742 | (clocks.data[i].clocks_in_khz == now) ? "*" : ""); | 2745 | (clocks.data[i].clocks_in_khz == now) ? "*" : ""); |
| 2743 | break; | 2746 | break; |
| 2744 | 2747 | ||
| 2745 | case PP_MCLK: | 2748 | case PP_MCLK: |
| 2746 | ret = vega20_get_current_mclk_freq(hwmgr, &now); | 2749 | ret = vega20_get_current_clk_freq(hwmgr, PPCLK_UCLK, &now); |
| 2747 | PP_ASSERT_WITH_CODE(!ret, | 2750 | PP_ASSERT_WITH_CODE(!ret, |
| 2748 | "Attempt to get current mclk freq Failed!", | 2751 | "Attempt to get current mclk freq Failed!", |
| 2749 | return ret); | 2752 | return ret); |
| @@ -2755,7 +2758,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, | |||
| 2755 | 2758 | ||
| 2756 | for (i = 0; i < clocks.num_levels; i++) | 2759 | for (i = 0; i < clocks.num_levels; i++) |
| 2757 | size += sprintf(buf + size, "%d: %uMhz %s\n", | 2760 | size += sprintf(buf + size, "%d: %uMhz %s\n", |
| 2758 | i, clocks.data[i].clocks_in_khz / 100, | 2761 | i, clocks.data[i].clocks_in_khz / 1000, |
| 2759 | (clocks.data[i].clocks_in_khz == now) ? "*" : ""); | 2762 | (clocks.data[i].clocks_in_khz == now) ? "*" : ""); |
| 2760 | break; | 2763 | break; |
| 2761 | 2764 | ||
| @@ -2820,7 +2823,7 @@ static int vega20_print_clock_levels(struct pp_hwmgr *hwmgr, | |||
| 2820 | return ret); | 2823 | return ret); |
| 2821 | 2824 | ||
| 2822 | size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", | 2825 | size += sprintf(buf + size, "MCLK: %7uMhz %10uMhz\n", |
| 2823 | clocks.data[0].clocks_in_khz / 100, | 2826 | clocks.data[0].clocks_in_khz / 1000, |
| 2824 | od8_settings[OD8_SETTING_UCLK_FMAX].max_value); | 2827 | od8_settings[OD8_SETTING_UCLK_FMAX].max_value); |
| 2825 | } | 2828 | } |
| 2826 | 2829 | ||
| @@ -3476,6 +3479,8 @@ static const struct pp_hwmgr_func vega20_hwmgr_funcs = { | |||
| 3476 | vega20_set_watermarks_for_clocks_ranges, | 3479 | vega20_set_watermarks_for_clocks_ranges, |
| 3477 | .display_clock_voltage_request = | 3480 | .display_clock_voltage_request = |
| 3478 | vega20_display_clock_voltage_request, | 3481 | vega20_display_clock_voltage_request, |
| 3482 | .get_performance_level = | ||
| 3483 | vega20_get_performance_level, | ||
| 3479 | /* UMD pstate, profile related */ | 3484 | /* UMD pstate, profile related */ |
| 3480 | .force_dpm_level = | 3485 | .force_dpm_level = |
| 3481 | vega20_dpm_force_dpm_level, | 3486 | vega20_dpm_force_dpm_level, |
diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c index e5f7f8230065..97f8a1a970c3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_processpptables.c | |||
| @@ -642,8 +642,14 @@ static int check_powerplay_tables( | |||
| 642 | "Unsupported PPTable format!", return -1); | 642 | "Unsupported PPTable format!", return -1); |
| 643 | PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, | 643 | PP_ASSERT_WITH_CODE(powerplay_table->sHeader.structuresize > 0, |
| 644 | "Invalid PowerPlay Table!", return -1); | 644 | "Invalid PowerPlay Table!", return -1); |
| 645 | PP_ASSERT_WITH_CODE(powerplay_table->smcPPTable.Version == PPTABLE_V20_SMU_VERSION, | 645 | |
| 646 | "Unmatch PPTable version, vbios update may be needed!", return -1); | 646 | if (powerplay_table->smcPPTable.Version != PPTABLE_V20_SMU_VERSION) { |
| 647 | pr_info("Unmatch PPTable version: " | ||
| 648 | "pptable from VBIOS is V%d while driver supported is V%d!", | ||
| 649 | powerplay_table->smcPPTable.Version, | ||
| 650 | PPTABLE_V20_SMU_VERSION); | ||
| 651 | return -EINVAL; | ||
| 652 | } | ||
| 647 | 653 | ||
| 648 | //dump_pptable(&powerplay_table->smcPPTable); | 654 | //dump_pptable(&powerplay_table->smcPPTable); |
| 649 | 655 | ||
| @@ -716,10 +722,6 @@ static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable | |||
| 716 | "[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!", | 722 | "[appendVbiosPPTable] Failed to retrieve Smc Dpm Table from VBIOS!", |
| 717 | return -1); | 723 | return -1); |
| 718 | 724 | ||
| 719 | memset(ppsmc_pptable->Padding32, | ||
| 720 | 0, | ||
| 721 | sizeof(struct atom_smc_dpm_info_v4_4) - | ||
| 722 | sizeof(struct atom_common_table_header)); | ||
| 723 | ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx; | 725 | ppsmc_pptable->MaxVoltageStepGfx = smc_dpm_table->maxvoltagestepgfx; |
| 724 | ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc; | 726 | ppsmc_pptable->MaxVoltageStepSoc = smc_dpm_table->maxvoltagestepsoc; |
| 725 | 727 | ||
| @@ -778,22 +780,19 @@ static int append_vbios_pptable(struct pp_hwmgr *hwmgr, PPTable_t *ppsmc_pptable | |||
| 778 | ppsmc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent; | 780 | ppsmc_pptable->FllGfxclkSpreadPercent = smc_dpm_table->fllgfxclkspreadpercent; |
| 779 | ppsmc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq; | 781 | ppsmc_pptable->FllGfxclkSpreadFreq = smc_dpm_table->fllgfxclkspreadfreq; |
| 780 | 782 | ||
| 781 | if ((smc_dpm_table->table_header.format_revision == 4) && | 783 | for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { |
| 782 | (smc_dpm_table->table_header.content_revision == 4)) { | 784 | ppsmc_pptable->I2cControllers[i].Enabled = |
| 783 | for (i = 0; i < I2C_CONTROLLER_NAME_COUNT; i++) { | 785 | smc_dpm_table->i2ccontrollers[i].enabled; |
| 784 | ppsmc_pptable->I2cControllers[i].Enabled = | 786 | ppsmc_pptable->I2cControllers[i].SlaveAddress = |
| 785 | smc_dpm_table->i2ccontrollers[i].enabled; | 787 | smc_dpm_table->i2ccontrollers[i].slaveaddress; |
| 786 | ppsmc_pptable->I2cControllers[i].SlaveAddress = | 788 | ppsmc_pptable->I2cControllers[i].ControllerPort = |
| 787 | smc_dpm_table->i2ccontrollers[i].slaveaddress; | 789 | smc_dpm_table->i2ccontrollers[i].controllerport; |
| 788 | ppsmc_pptable->I2cControllers[i].ControllerPort = | 790 | ppsmc_pptable->I2cControllers[i].ThermalThrottler = |
| 789 | smc_dpm_table->i2ccontrollers[i].controllerport; | 791 | smc_dpm_table->i2ccontrollers[i].thermalthrottler; |
| 790 | ppsmc_pptable->I2cControllers[i].ThermalThrottler = | 792 | ppsmc_pptable->I2cControllers[i].I2cProtocol = |
| 791 | smc_dpm_table->i2ccontrollers[i].thermalthrottler; | 793 | smc_dpm_table->i2ccontrollers[i].i2cprotocol; |
| 792 | ppsmc_pptable->I2cControllers[i].I2cProtocol = | 794 | ppsmc_pptable->I2cControllers[i].I2cSpeed = |
| 793 | smc_dpm_table->i2ccontrollers[i].i2cprotocol; | 795 | smc_dpm_table->i2ccontrollers[i].i2cspeed; |
| 794 | ppsmc_pptable->I2cControllers[i].I2cSpeed = | ||
| 795 | smc_dpm_table->i2ccontrollers[i].i2cspeed; | ||
| 796 | } | ||
| 797 | } | 796 | } |
| 798 | 797 | ||
| 799 | return 0; | 798 | return 0; |
| @@ -882,15 +881,10 @@ static int init_powerplay_table_information( | |||
| 882 | if (pptable_information->smc_pptable == NULL) | 881 | if (pptable_information->smc_pptable == NULL) |
| 883 | return -ENOMEM; | 882 | return -ENOMEM; |
| 884 | 883 | ||
| 885 | if (powerplay_table->smcPPTable.Version <= 2) | 884 | memcpy(pptable_information->smc_pptable, |
| 886 | memcpy(pptable_information->smc_pptable, | 885 | &(powerplay_table->smcPPTable), |
| 887 | &(powerplay_table->smcPPTable), | 886 | sizeof(PPTable_t)); |
| 888 | sizeof(PPTable_t) - | 887 | |
| 889 | sizeof(I2cControllerConfig_t) * I2C_CONTROLLER_NAME_COUNT); | ||
| 890 | else | ||
| 891 | memcpy(pptable_information->smc_pptable, | ||
| 892 | &(powerplay_table->smcPPTable), | ||
| 893 | sizeof(PPTable_t)); | ||
| 894 | 888 | ||
| 895 | result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); | 889 | result = append_vbios_pptable(hwmgr, (pptable_information->smc_pptable)); |
| 896 | 890 | ||
diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h index 2998a49960ed..63d5cf691549 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu11_driver_if.h | |||
| @@ -29,7 +29,7 @@ | |||
| 29 | // any structure is changed in this file | 29 | // any structure is changed in this file |
| 30 | #define SMU11_DRIVER_IF_VERSION 0x12 | 30 | #define SMU11_DRIVER_IF_VERSION 0x12 |
| 31 | 31 | ||
| 32 | #define PPTABLE_V20_SMU_VERSION 2 | 32 | #define PPTABLE_V20_SMU_VERSION 3 |
| 33 | 33 | ||
| 34 | #define NUM_GFXCLK_DPM_LEVELS 16 | 34 | #define NUM_GFXCLK_DPM_LEVELS 16 |
| 35 | #define NUM_VCLK_DPM_LEVELS 8 | 35 | #define NUM_VCLK_DPM_LEVELS 8 |
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c index f836d30fdd44..09b844ec3eab 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu8_smumgr.c | |||
| @@ -71,7 +71,11 @@ static int smu8_send_msg_to_smc_async(struct pp_hwmgr *hwmgr, uint16_t msg) | |||
| 71 | result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, | 71 | result = PHM_WAIT_FIELD_UNEQUAL(hwmgr, |
| 72 | SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); | 72 | SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); |
| 73 | if (result != 0) { | 73 | if (result != 0) { |
| 74 | /* Read the last message to SMU, to report actual cause */ | ||
| 75 | uint32_t val = cgs_read_register(hwmgr->device, | ||
| 76 | mmSMU_MP1_SRBM2P_MSG_0); | ||
| 74 | pr_err("smu8_send_msg_to_smc_async (0x%04x) failed\n", msg); | 77 | pr_err("smu8_send_msg_to_smc_async (0x%04x) failed\n", msg); |
| 78 | pr_err("SMU still servicing msg (0x%04x)\n", val); | ||
| 75 | return result; | 79 | return result; |
| 76 | } | 80 | } |
| 77 | 81 | ||
diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index f8a931cf3665..680566d97adc 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c | |||
| @@ -458,18 +458,6 @@ static void ti_sn_bridge_enable(struct drm_bridge *bridge) | |||
| 458 | unsigned int val; | 458 | unsigned int val; |
| 459 | int ret; | 459 | int ret; |
| 460 | 460 | ||
| 461 | /* | ||
| 462 | * FIXME: | ||
| 463 | * This 70ms was found necessary by experimentation. If it's not | ||
| 464 | * present, link training fails. It seems like it can go anywhere from | ||
| 465 | * pre_enable() up to semi-auto link training initiation below. | ||
| 466 | * | ||
| 467 | * Neither the datasheet for the bridge nor the panel tested mention a | ||
| 468 | * delay of this magnitude in the timing requirements. So for now, add | ||
| 469 | * the mystery delay until someone figures out a better fix. | ||
| 470 | */ | ||
| 471 | msleep(70); | ||
| 472 | |||
| 473 | /* DSI_A lane config */ | 461 | /* DSI_A lane config */ |
| 474 | val = CHA_DSI_LANES(4 - pdata->dsi->lanes); | 462 | val = CHA_DSI_LANES(4 - pdata->dsi->lanes); |
| 475 | regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG, | 463 | regmap_update_bits(pdata->regmap, SN_DSI_LANES_REG, |
| @@ -536,7 +524,22 @@ static void ti_sn_bridge_pre_enable(struct drm_bridge *bridge) | |||
| 536 | /* configure bridge ref_clk */ | 524 | /* configure bridge ref_clk */ |
| 537 | ti_sn_bridge_set_refclk_freq(pdata); | 525 | ti_sn_bridge_set_refclk_freq(pdata); |
| 538 | 526 | ||
| 539 | /* in case drm_panel is connected then HPD is not supported */ | 527 | /* |
| 528 | * HPD on this bridge chip is a bit useless. This is an eDP bridge | ||
| 529 | * so the HPD is an internal signal that's only there to signal that | ||
| 530 | * the panel is done powering up. ...but the bridge chip debounces | ||
| 531 | * this signal by between 100 ms and 400 ms (depending on process, | ||
| 532 | * voltage, and temperate--I measured it at about 200 ms). One | ||
| 533 | * particular panel asserted HPD 84 ms after it was powered on meaning | ||
| 534 | * that we saw HPD 284 ms after power on. ...but the same panel said | ||
| 535 | * that instead of looking at HPD you could just hardcode a delay of | ||
| 536 | * 200 ms. We'll assume that the panel driver will have the hardcoded | ||
| 537 | * delay in its prepare and always disable HPD. | ||
| 538 | * | ||
| 539 | * If HPD somehow makes sense on some future panel we'll have to | ||
| 540 | * change this to be conditional on someone specifying that HPD should | ||
| 541 | * be used. | ||
| 542 | */ | ||
| 540 | regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE, | 543 | regmap_update_bits(pdata->regmap, SN_HPD_DISABLE_REG, HPD_DISABLE, |
| 541 | HPD_DISABLE); | 544 | HPD_DISABLE); |
| 542 | 545 | ||
diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 701cb334e1ea..d8b526b7932c 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c | |||
| @@ -308,6 +308,26 @@ update_connector_routing(struct drm_atomic_state *state, | |||
| 308 | return 0; | 308 | return 0; |
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | crtc_state = drm_atomic_get_new_crtc_state(state, | ||
| 312 | new_connector_state->crtc); | ||
| 313 | /* | ||
| 314 | * For compatibility with legacy users, we want to make sure that | ||
| 315 | * we allow DPMS On->Off modesets on unregistered connectors. Modesets | ||
| 316 | * which would result in anything else must be considered invalid, to | ||
| 317 | * avoid turning on new displays on dead connectors. | ||
| 318 | * | ||
| 319 | * Since the connector can be unregistered at any point during an | ||
| 320 | * atomic check or commit, this is racy. But that's OK: all we care | ||
| 321 | * about is ensuring that userspace can't do anything but shut off the | ||
| 322 | * display on a connector that was destroyed after its been notified, | ||
| 323 | * not before. | ||
| 324 | */ | ||
| 325 | if (drm_connector_is_unregistered(connector) && crtc_state->active) { | ||
| 326 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] is not registered\n", | ||
| 327 | connector->base.id, connector->name); | ||
| 328 | return -EINVAL; | ||
| 329 | } | ||
| 330 | |||
| 311 | funcs = connector->helper_private; | 331 | funcs = connector->helper_private; |
| 312 | 332 | ||
| 313 | if (funcs->atomic_best_encoder) | 333 | if (funcs->atomic_best_encoder) |
| @@ -352,7 +372,6 @@ update_connector_routing(struct drm_atomic_state *state, | |||
| 352 | 372 | ||
| 353 | set_best_encoder(state, new_connector_state, new_encoder); | 373 | set_best_encoder(state, new_connector_state, new_encoder); |
| 354 | 374 | ||
| 355 | crtc_state = drm_atomic_get_new_crtc_state(state, new_connector_state->crtc); | ||
| 356 | crtc_state->connectors_changed = true; | 375 | crtc_state->connectors_changed = true; |
| 357 | 376 | ||
| 358 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", | 377 | DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n", |
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index 1e40e5decbe9..4943cef178be 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c | |||
| @@ -379,7 +379,8 @@ void drm_connector_cleanup(struct drm_connector *connector) | |||
| 379 | /* The connector should have been removed from userspace long before | 379 | /* The connector should have been removed from userspace long before |
| 380 | * it is finally destroyed. | 380 | * it is finally destroyed. |
| 381 | */ | 381 | */ |
| 382 | if (WARN_ON(connector->registered)) | 382 | if (WARN_ON(connector->registration_state == |
| 383 | DRM_CONNECTOR_REGISTERED)) | ||
| 383 | drm_connector_unregister(connector); | 384 | drm_connector_unregister(connector); |
| 384 | 385 | ||
| 385 | if (connector->tile_group) { | 386 | if (connector->tile_group) { |
| @@ -436,7 +437,7 @@ int drm_connector_register(struct drm_connector *connector) | |||
| 436 | return 0; | 437 | return 0; |
| 437 | 438 | ||
| 438 | mutex_lock(&connector->mutex); | 439 | mutex_lock(&connector->mutex); |
| 439 | if (connector->registered) | 440 | if (connector->registration_state != DRM_CONNECTOR_INITIALIZING) |
| 440 | goto unlock; | 441 | goto unlock; |
| 441 | 442 | ||
| 442 | ret = drm_sysfs_connector_add(connector); | 443 | ret = drm_sysfs_connector_add(connector); |
| @@ -456,7 +457,7 @@ int drm_connector_register(struct drm_connector *connector) | |||
| 456 | 457 | ||
| 457 | drm_mode_object_register(connector->dev, &connector->base); | 458 | drm_mode_object_register(connector->dev, &connector->base); |
| 458 | 459 | ||
| 459 | connector->registered = true; | 460 | connector->registration_state = DRM_CONNECTOR_REGISTERED; |
| 460 | goto unlock; | 461 | goto unlock; |
| 461 | 462 | ||
| 462 | err_debugfs: | 463 | err_debugfs: |
| @@ -478,7 +479,7 @@ EXPORT_SYMBOL(drm_connector_register); | |||
| 478 | void drm_connector_unregister(struct drm_connector *connector) | 479 | void drm_connector_unregister(struct drm_connector *connector) |
| 479 | { | 480 | { |
| 480 | mutex_lock(&connector->mutex); | 481 | mutex_lock(&connector->mutex); |
| 481 | if (!connector->registered) { | 482 | if (connector->registration_state != DRM_CONNECTOR_REGISTERED) { |
| 482 | mutex_unlock(&connector->mutex); | 483 | mutex_unlock(&connector->mutex); |
| 483 | return; | 484 | return; |
| 484 | } | 485 | } |
| @@ -489,7 +490,7 @@ void drm_connector_unregister(struct drm_connector *connector) | |||
| 489 | drm_sysfs_connector_remove(connector); | 490 | drm_sysfs_connector_remove(connector); |
| 490 | drm_debugfs_connector_remove(connector); | 491 | drm_debugfs_connector_remove(connector); |
| 491 | 492 | ||
| 492 | connector->registered = false; | 493 | connector->registration_state = DRM_CONNECTOR_UNREGISTERED; |
| 493 | mutex_unlock(&connector->mutex); | 494 | mutex_unlock(&connector->mutex); |
| 494 | } | 495 | } |
| 495 | EXPORT_SYMBOL(drm_connector_unregister); | 496 | EXPORT_SYMBOL(drm_connector_unregister); |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ff0bfc65a8c1..b506e3622b08 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -122,6 +122,9 @@ static const struct edid_quirk { | |||
| 122 | /* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */ | 122 | /* SDC panel of Lenovo B50-80 reports 8 bpc, but is a 6 bpc panel */ |
| 123 | { "SDC", 0x3652, EDID_QUIRK_FORCE_6BPC }, | 123 | { "SDC", 0x3652, EDID_QUIRK_FORCE_6BPC }, |
| 124 | 124 | ||
| 125 | /* BOE model 0x0771 reports 8 bpc, but is a 6 bpc panel */ | ||
| 126 | { "BOE", 0x0771, EDID_QUIRK_FORCE_6BPC }, | ||
| 127 | |||
| 125 | /* Belinea 10 15 55 */ | 128 | /* Belinea 10 15 55 */ |
| 126 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, | 129 | { "MAX", 1516, EDID_QUIRK_PREFER_LARGE_60 }, |
| 127 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, | 130 | { "MAX", 0x77e, EDID_QUIRK_PREFER_LARGE_60 }, |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 3fae4dab295f..13f9b56a9ce7 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
| @@ -5102,19 +5102,13 @@ intel_dp_long_pulse(struct intel_connector *connector, | |||
| 5102 | */ | 5102 | */ |
| 5103 | status = connector_status_disconnected; | 5103 | status = connector_status_disconnected; |
| 5104 | goto out; | 5104 | goto out; |
| 5105 | } else { | 5105 | } |
| 5106 | /* | 5106 | |
| 5107 | * If display is now connected check links status, | 5107 | /* |
| 5108 | * there has been known issues of link loss triggering | 5108 | * Some external monitors do not signal loss of link synchronization |
| 5109 | * long pulse. | 5109 | * with an IRQ_HPD, so force a link status check. |
| 5110 | * | 5110 | */ |
| 5111 | * Some sinks (eg. ASUS PB287Q) seem to perform some | 5111 | if (!intel_dp_is_edp(intel_dp)) { |
| 5112 | * weird HPD ping pong during modesets. So we can apparently | ||
| 5113 | * end up with HPD going low during a modeset, and then | ||
| 5114 | * going back up soon after. And once that happens we must | ||
| 5115 | * retrain the link to get a picture. That's in case no | ||
| 5116 | * userspace component reacted to intermittent HPD dip. | ||
| 5117 | */ | ||
| 5118 | struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; | 5112 | struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; |
| 5119 | 5113 | ||
| 5120 | intel_dp_retrain_link(encoder, ctx); | 5114 | intel_dp_retrain_link(encoder, ctx); |
diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 7f155b4f1a7d..1b00f8ea145b 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c | |||
| @@ -77,7 +77,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder, | |||
| 77 | pipe_config->pbn = mst_pbn; | 77 | pipe_config->pbn = mst_pbn; |
| 78 | 78 | ||
| 79 | /* Zombie connectors can't have VCPI slots */ | 79 | /* Zombie connectors can't have VCPI slots */ |
| 80 | if (READ_ONCE(connector->registered)) { | 80 | if (!drm_connector_is_unregistered(connector)) { |
| 81 | slots = drm_dp_atomic_find_vcpi_slots(state, | 81 | slots = drm_dp_atomic_find_vcpi_slots(state, |
| 82 | &intel_dp->mst_mgr, | 82 | &intel_dp->mst_mgr, |
| 83 | port, | 83 | port, |
| @@ -313,7 +313,7 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector) | |||
| 313 | struct edid *edid; | 313 | struct edid *edid; |
| 314 | int ret; | 314 | int ret; |
| 315 | 315 | ||
| 316 | if (!READ_ONCE(connector->registered)) | 316 | if (drm_connector_is_unregistered(connector)) |
| 317 | return intel_connector_update_modes(connector, NULL); | 317 | return intel_connector_update_modes(connector, NULL); |
| 318 | 318 | ||
| 319 | edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); | 319 | edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port); |
| @@ -329,7 +329,7 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force) | |||
| 329 | struct intel_connector *intel_connector = to_intel_connector(connector); | 329 | struct intel_connector *intel_connector = to_intel_connector(connector); |
| 330 | struct intel_dp *intel_dp = intel_connector->mst_port; | 330 | struct intel_dp *intel_dp = intel_connector->mst_port; |
| 331 | 331 | ||
| 332 | if (!READ_ONCE(connector->registered)) | 332 | if (drm_connector_is_unregistered(connector)) |
| 333 | return connector_status_disconnected; | 333 | return connector_status_disconnected; |
| 334 | return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, | 334 | return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr, |
| 335 | intel_connector->port); | 335 | intel_connector->port); |
| @@ -372,7 +372,7 @@ intel_dp_mst_mode_valid(struct drm_connector *connector, | |||
| 372 | int bpp = 24; /* MST uses fixed bpp */ | 372 | int bpp = 24; /* MST uses fixed bpp */ |
| 373 | int max_rate, mode_rate, max_lanes, max_link_clock; | 373 | int max_rate, mode_rate, max_lanes, max_link_clock; |
| 374 | 374 | ||
| 375 | if (!READ_ONCE(connector->registered)) | 375 | if (drm_connector_is_unregistered(connector)) |
| 376 | return MODE_ERROR; | 376 | return MODE_ERROR; |
| 377 | 377 | ||
| 378 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | 378 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) |
diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index 6bb78076b5b5..6cbbae3f438b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c | |||
| @@ -881,22 +881,16 @@ nv50_mstc_atomic_best_encoder(struct drm_connector *connector, | |||
| 881 | { | 881 | { |
| 882 | struct nv50_head *head = nv50_head(connector_state->crtc); | 882 | struct nv50_head *head = nv50_head(connector_state->crtc); |
| 883 | struct nv50_mstc *mstc = nv50_mstc(connector); | 883 | struct nv50_mstc *mstc = nv50_mstc(connector); |
| 884 | if (mstc->port) { | 884 | |
| 885 | struct nv50_mstm *mstm = mstc->mstm; | 885 | return &mstc->mstm->msto[head->base.index]->encoder; |
| 886 | return &mstm->msto[head->base.index]->encoder; | ||
| 887 | } | ||
| 888 | return NULL; | ||
| 889 | } | 886 | } |
| 890 | 887 | ||
| 891 | static struct drm_encoder * | 888 | static struct drm_encoder * |
| 892 | nv50_mstc_best_encoder(struct drm_connector *connector) | 889 | nv50_mstc_best_encoder(struct drm_connector *connector) |
| 893 | { | 890 | { |
| 894 | struct nv50_mstc *mstc = nv50_mstc(connector); | 891 | struct nv50_mstc *mstc = nv50_mstc(connector); |
| 895 | if (mstc->port) { | 892 | |
| 896 | struct nv50_mstm *mstm = mstc->mstm; | 893 | return &mstc->mstm->msto[0]->encoder; |
| 897 | return &mstm->msto[0]->encoder; | ||
| 898 | } | ||
| 899 | return NULL; | ||
| 900 | } | 894 | } |
| 901 | 895 | ||
| 902 | static enum drm_mode_status | 896 | static enum drm_mode_status |
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 97964f7f2ace..a04ffb3b2174 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c | |||
| @@ -56,6 +56,8 @@ struct panel_desc { | |||
| 56 | /** | 56 | /** |
| 57 | * @prepare: the time (in milliseconds) that it takes for the panel to | 57 | * @prepare: the time (in milliseconds) that it takes for the panel to |
| 58 | * become ready and start receiving video data | 58 | * become ready and start receiving video data |
| 59 | * @hpd_absent_delay: Add this to the prepare delay if we know Hot | ||
| 60 | * Plug Detect isn't used. | ||
| 59 | * @enable: the time (in milliseconds) that it takes for the panel to | 61 | * @enable: the time (in milliseconds) that it takes for the panel to |
| 60 | * display the first valid frame after starting to receive | 62 | * display the first valid frame after starting to receive |
| 61 | * video data | 63 | * video data |
| @@ -66,6 +68,7 @@ struct panel_desc { | |||
| 66 | */ | 68 | */ |
| 67 | struct { | 69 | struct { |
| 68 | unsigned int prepare; | 70 | unsigned int prepare; |
| 71 | unsigned int hpd_absent_delay; | ||
| 69 | unsigned int enable; | 72 | unsigned int enable; |
| 70 | unsigned int disable; | 73 | unsigned int disable; |
| 71 | unsigned int unprepare; | 74 | unsigned int unprepare; |
| @@ -79,6 +82,7 @@ struct panel_simple { | |||
| 79 | struct drm_panel base; | 82 | struct drm_panel base; |
| 80 | bool prepared; | 83 | bool prepared; |
| 81 | bool enabled; | 84 | bool enabled; |
| 85 | bool no_hpd; | ||
| 82 | 86 | ||
| 83 | const struct panel_desc *desc; | 87 | const struct panel_desc *desc; |
| 84 | 88 | ||
| @@ -202,6 +206,7 @@ static int panel_simple_unprepare(struct drm_panel *panel) | |||
| 202 | static int panel_simple_prepare(struct drm_panel *panel) | 206 | static int panel_simple_prepare(struct drm_panel *panel) |
| 203 | { | 207 | { |
| 204 | struct panel_simple *p = to_panel_simple(panel); | 208 | struct panel_simple *p = to_panel_simple(panel); |
| 209 | unsigned int delay; | ||
| 205 | int err; | 210 | int err; |
| 206 | 211 | ||
| 207 | if (p->prepared) | 212 | if (p->prepared) |
| @@ -215,8 +220,11 @@ static int panel_simple_prepare(struct drm_panel *panel) | |||
| 215 | 220 | ||
| 216 | gpiod_set_value_cansleep(p->enable_gpio, 1); | 221 | gpiod_set_value_cansleep(p->enable_gpio, 1); |
| 217 | 222 | ||
| 218 | if (p->desc->delay.prepare) | 223 | delay = p->desc->delay.prepare; |
| 219 | msleep(p->desc->delay.prepare); | 224 | if (p->no_hpd) |
| 225 | delay += p->desc->delay.hpd_absent_delay; | ||
| 226 | if (delay) | ||
| 227 | msleep(delay); | ||
| 220 | 228 | ||
| 221 | p->prepared = true; | 229 | p->prepared = true; |
| 222 | 230 | ||
| @@ -305,6 +313,8 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) | |||
| 305 | panel->prepared = false; | 313 | panel->prepared = false; |
| 306 | panel->desc = desc; | 314 | panel->desc = desc; |
| 307 | 315 | ||
| 316 | panel->no_hpd = of_property_read_bool(dev->of_node, "no-hpd"); | ||
| 317 | |||
| 308 | panel->supply = devm_regulator_get(dev, "power"); | 318 | panel->supply = devm_regulator_get(dev, "power"); |
| 309 | if (IS_ERR(panel->supply)) | 319 | if (IS_ERR(panel->supply)) |
| 310 | return PTR_ERR(panel->supply); | 320 | return PTR_ERR(panel->supply); |
| @@ -1363,7 +1373,7 @@ static const struct panel_desc innolux_n156bge_l21 = { | |||
| 1363 | }, | 1373 | }, |
| 1364 | }; | 1374 | }; |
| 1365 | 1375 | ||
| 1366 | static const struct drm_display_mode innolux_tv123wam_mode = { | 1376 | static const struct drm_display_mode innolux_p120zdg_bf1_mode = { |
| 1367 | .clock = 206016, | 1377 | .clock = 206016, |
| 1368 | .hdisplay = 2160, | 1378 | .hdisplay = 2160, |
| 1369 | .hsync_start = 2160 + 48, | 1379 | .hsync_start = 2160 + 48, |
| @@ -1377,15 +1387,16 @@ static const struct drm_display_mode innolux_tv123wam_mode = { | |||
| 1377 | .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, | 1387 | .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, |
| 1378 | }; | 1388 | }; |
| 1379 | 1389 | ||
| 1380 | static const struct panel_desc innolux_tv123wam = { | 1390 | static const struct panel_desc innolux_p120zdg_bf1 = { |
| 1381 | .modes = &innolux_tv123wam_mode, | 1391 | .modes = &innolux_p120zdg_bf1_mode, |
| 1382 | .num_modes = 1, | 1392 | .num_modes = 1, |
| 1383 | .bpc = 8, | 1393 | .bpc = 8, |
| 1384 | .size = { | 1394 | .size = { |
| 1385 | .width = 259, | 1395 | .width = 254, |
| 1386 | .height = 173, | 1396 | .height = 169, |
| 1387 | }, | 1397 | }, |
| 1388 | .delay = { | 1398 | .delay = { |
| 1399 | .hpd_absent_delay = 200, | ||
| 1389 | .unprepare = 500, | 1400 | .unprepare = 500, |
| 1390 | }, | 1401 | }, |
| 1391 | }; | 1402 | }; |
| @@ -2445,8 +2456,8 @@ static const struct of_device_id platform_of_match[] = { | |||
| 2445 | .compatible = "innolux,n156bge-l21", | 2456 | .compatible = "innolux,n156bge-l21", |
| 2446 | .data = &innolux_n156bge_l21, | 2457 | .data = &innolux_n156bge_l21, |
| 2447 | }, { | 2458 | }, { |
| 2448 | .compatible = "innolux,tv123wam", | 2459 | .compatible = "innolux,p120zdg-bf1", |
| 2449 | .data = &innolux_tv123wam, | 2460 | .data = &innolux_p120zdg_bf1, |
| 2450 | }, { | 2461 | }, { |
| 2451 | .compatible = "innolux,zj070na-01p", | 2462 | .compatible = "innolux,zj070na-01p", |
| 2452 | .data = &innolux_zj070na_01p, | 2463 | .data = &innolux_zj070na_01p, |
diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index 91a877fa00cb..9ccad6b062f2 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h | |||
| @@ -82,6 +82,53 @@ enum drm_connector_status { | |||
| 82 | connector_status_unknown = 3, | 82 | connector_status_unknown = 3, |
| 83 | }; | 83 | }; |
| 84 | 84 | ||
| 85 | /** | ||
| 86 | * enum drm_connector_registration_status - userspace registration status for | ||
| 87 | * a &drm_connector | ||
| 88 | * | ||
| 89 | * This enum is used to track the status of initializing a connector and | ||
| 90 | * registering it with userspace, so that DRM can prevent bogus modesets on | ||
| 91 | * connectors that no longer exist. | ||
| 92 | */ | ||
| 93 | enum drm_connector_registration_state { | ||
| 94 | /** | ||
| 95 | * @DRM_CONNECTOR_INITIALIZING: The connector has just been created, | ||
| 96 | * but has yet to be exposed to userspace. There should be no | ||
| 97 | * additional restrictions to how the state of this connector may be | ||
| 98 | * modified. | ||
| 99 | */ | ||
| 100 | DRM_CONNECTOR_INITIALIZING = 0, | ||
| 101 | |||
| 102 | /** | ||
| 103 | * @DRM_CONNECTOR_REGISTERED: The connector has been fully initialized | ||
| 104 | * and registered with sysfs, as such it has been exposed to | ||
| 105 | * userspace. There should be no additional restrictions to how the | ||
| 106 | * state of this connector may be modified. | ||
| 107 | */ | ||
| 108 | DRM_CONNECTOR_REGISTERED = 1, | ||
| 109 | |||
| 110 | /** | ||
| 111 | * @DRM_CONNECTOR_UNREGISTERED: The connector has either been exposed | ||
| 112 | * to userspace and has since been unregistered and removed from | ||
| 113 | * userspace, or the connector was unregistered before it had a chance | ||
| 114 | * to be exposed to userspace (e.g. still in the | ||
| 115 | * @DRM_CONNECTOR_INITIALIZING state). When a connector is | ||
| 116 | * unregistered, there are additional restrictions to how its state | ||
| 117 | * may be modified: | ||
| 118 | * | ||
| 119 | * - An unregistered connector may only have its DPMS changed from | ||
| 120 | * On->Off. Once DPMS is changed to Off, it may not be switched back | ||
| 121 | * to On. | ||
| 122 | * - Modesets are not allowed on unregistered connectors, unless they | ||
| 123 | * would result in disabling its assigned CRTCs. This means | ||
| 124 | * disabling a CRTC on an unregistered connector is OK, but enabling | ||
| 125 | * one is not. | ||
| 126 | * - Removing a CRTC from an unregistered connector is OK, but new | ||
| 127 | * CRTCs may never be assigned to an unregistered connector. | ||
| 128 | */ | ||
| 129 | DRM_CONNECTOR_UNREGISTERED = 2, | ||
| 130 | }; | ||
| 131 | |||
| 85 | enum subpixel_order { | 132 | enum subpixel_order { |
| 86 | SubPixelUnknown = 0, | 133 | SubPixelUnknown = 0, |
| 87 | SubPixelHorizontalRGB, | 134 | SubPixelHorizontalRGB, |
| @@ -853,10 +900,12 @@ struct drm_connector { | |||
| 853 | bool ycbcr_420_allowed; | 900 | bool ycbcr_420_allowed; |
| 854 | 901 | ||
| 855 | /** | 902 | /** |
| 856 | * @registered: Is this connector exposed (registered) with userspace? | 903 | * @registration_state: Is this connector initializing, exposed |
| 904 | * (registered) with userspace, or unregistered? | ||
| 905 | * | ||
| 857 | * Protected by @mutex. | 906 | * Protected by @mutex. |
| 858 | */ | 907 | */ |
| 859 | bool registered; | 908 | enum drm_connector_registration_state registration_state; |
| 860 | 909 | ||
| 861 | /** | 910 | /** |
| 862 | * @modes: | 911 | * @modes: |
| @@ -1166,6 +1215,24 @@ static inline void drm_connector_unreference(struct drm_connector *connector) | |||
| 1166 | drm_connector_put(connector); | 1215 | drm_connector_put(connector); |
| 1167 | } | 1216 | } |
| 1168 | 1217 | ||
| 1218 | /** | ||
| 1219 | * drm_connector_is_unregistered - has the connector been unregistered from | ||
| 1220 | * userspace? | ||
| 1221 | * @connector: DRM connector | ||
| 1222 | * | ||
| 1223 | * Checks whether or not @connector has been unregistered from userspace. | ||
| 1224 | * | ||
| 1225 | * Returns: | ||
| 1226 | * True if the connector was unregistered, false if the connector is | ||
| 1227 | * registered or has not yet been registered with userspace. | ||
| 1228 | */ | ||
| 1229 | static inline bool | ||
| 1230 | drm_connector_is_unregistered(struct drm_connector *connector) | ||
| 1231 | { | ||
| 1232 | return READ_ONCE(connector->registration_state) == | ||
| 1233 | DRM_CONNECTOR_UNREGISTERED; | ||
| 1234 | } | ||
| 1235 | |||
| 1169 | const char *drm_get_connector_status_name(enum drm_connector_status status); | 1236 | const char *drm_get_connector_status_name(enum drm_connector_status status); |
| 1170 | const char *drm_get_subpixel_order_name(enum subpixel_order order); | 1237 | const char *drm_get_subpixel_order_name(enum subpixel_order order); |
| 1171 | const char *drm_get_dpms_name(int val); | 1238 | const char *drm_get_dpms_name(int val); |
