提交 51a831a7 编写于 作者: D Daniel Vetter

Merge remote-tracking branch 'airlied/drm-next' into drm-intel-next-queued

Chris Wilson needs the new drm_driver->release callback to make sure
the shiny new dma-buf testcases don't oops the driver on unload.
Signed-off-by: NDaniel Vetter <daniel.vetter@intel.com>
...@@ -56,6 +56,18 @@ Required properties for V3D: ...@@ -56,6 +56,18 @@ Required properties for V3D:
- interrupts: The interrupt number - interrupts: The interrupt number
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
Required properties for DSI:
- compatible: Should be "brcm,bcm2835-dsi0" or "brcm,bcm2835-dsi1"
- reg: Physical base address and length of the DSI block's registers
- interrupts: The interrupt number
See bindings/interrupt-controller/brcm,bcm2835-armctrl-ic.txt
- clocks: a) phy: The DSI PLL clock feeding the DSI analog PHY
b) escape: The DSI ESC clock from CPRMAN
c) pixel: The DSI pixel clock from CPRMAN
- clock-output-names:
The 3 clocks output from the DSI analog PHY: dsi[01]_byte,
dsi[01]_ddr2, and dsi[01]_ddr
[1] Documentation/devicetree/bindings/media/video-interfaces.txt [1] Documentation/devicetree/bindings/media/video-interfaces.txt
Example: Example:
...@@ -99,6 +111,29 @@ dpi: dpi@7e208000 { ...@@ -99,6 +111,29 @@ dpi: dpi@7e208000 {
}; };
}; };
dsi1: dsi@7e700000 {
compatible = "brcm,bcm2835-dsi1";
reg = <0x7e700000 0x8c>;
interrupts = <2 12>;
#address-cells = <1>;
#size-cells = <0>;
#clock-cells = <1>;
clocks = <&clocks BCM2835_PLLD_DSI1>,
<&clocks BCM2835_CLOCK_DSI1E>,
<&clocks BCM2835_CLOCK_DSI1P>;
clock-names = "phy", "escape", "pixel";
clock-output-names = "dsi1_byte", "dsi1_ddr2", "dsi1_ddr";
pitouchscreen: panel@0 {
compatible = "raspberrypi,touchscreen";
reg = <0>;
<...>
};
};
vec: vec@7e806000 { vec: vec@7e806000 {
compatible = "brcm,bcm2835-vec"; compatible = "brcm,bcm2835-vec";
reg = <0x7e806000 0x1000>; reg = <0x7e806000 0x1000>;
......
Qualcomm adreno/snapdragon GPU Qualcomm adreno/snapdragon GPU
Required properties: Required properties:
- compatible: "qcom,adreno-3xx" - compatible: "qcom,adreno-XYZ.W", "qcom,adreno"
for example: "qcom,adreno-306.0", "qcom,adreno"
Note that you need to list the less specific "qcom,adreno" (since this
is what the device is matched on), in addition to the more specific
with the chip-id.
- reg: Physical base address and length of the controller's registers. - reg: Physical base address and length of the controller's registers.
- interrupts: The interrupt signal from the gpu. - interrupts: The interrupt signal from the gpu.
- clocks: device clocks - clocks: device clocks
See ../clocks/clock-bindings.txt for details. See ../clocks/clock-bindings.txt for details.
- clock-names: the following clocks are required: - clock-names: the following clocks are required:
* "core_clk" * "core"
* "iface_clk" * "iface"
* "mem_iface_clk" * "mem_iface"
- qcom,chipid: gpu chip-id. Note this may become optional for future
devices if we can reliably read the chipid from hw
- qcom,gpu-pwrlevels: list of operating points
- compatible: "qcom,gpu-pwrlevels"
- for each qcom,gpu-pwrlevel:
- qcom,gpu-freq: requested gpu clock speed
- NOTE: downstream android driver defines additional parameters to
configure memory bandwidth scaling per OPP.
Example: Example:
...@@ -25,28 +21,18 @@ Example: ...@@ -25,28 +21,18 @@ Example:
... ...
gpu: qcom,kgsl-3d0@4300000 { gpu: qcom,kgsl-3d0@4300000 {
compatible = "qcom,adreno-3xx"; compatible = "qcom,adreno-320.2", "qcom,adreno";
reg = <0x04300000 0x20000>; reg = <0x04300000 0x20000>;
reg-names = "kgsl_3d0_reg_memory"; reg-names = "kgsl_3d0_reg_memory";
interrupts = <GIC_SPI 80 0>; interrupts = <GIC_SPI 80 0>;
interrupt-names = "kgsl_3d0_irq"; interrupt-names = "kgsl_3d0_irq";
clock-names = clock-names =
"core_clk", "core",
"iface_clk", "iface",
"mem_iface_clk"; "mem_iface";
clocks = clocks =
<&mmcc GFX3D_CLK>, <&mmcc GFX3D_CLK>,
<&mmcc GFX3D_AHB_CLK>, <&mmcc GFX3D_AHB_CLK>,
<&mmcc MMSS_IMEM_AHB_CLK>; <&mmcc MMSS_IMEM_AHB_CLK>;
qcom,chipid = <0x03020100>;
qcom,gpu-pwrlevels {
compatible = "qcom,gpu-pwrlevels";
qcom,gpu-pwrlevel@0 {
qcom,gpu-freq = <450000000>;
};
qcom,gpu-pwrlevel@1 {
qcom,gpu-freq = <27000000>;
};
};
}; };
}; };
...@@ -291,10 +291,17 @@ To use :c:func:`drm_gem_mmap()`, drivers must fill the struct ...@@ -291,10 +291,17 @@ To use :c:func:`drm_gem_mmap()`, drivers must fill the struct
:c:type:`struct drm_driver <drm_driver>` gem_vm_ops field :c:type:`struct drm_driver <drm_driver>` gem_vm_ops field
with a pointer to VM operations. with a pointer to VM operations.
struct vm_operations_struct \*gem_vm_ops struct The VM operations is a :c:type:`struct vm_operations_struct <vm_operations_struct>`
vm_operations_struct { void (\*open)(struct vm_area_struct \* area); made up of several fields, the more interesting ones being:
void (\*close)(struct vm_area_struct \* area); int (\*fault)(struct
vm_area_struct \*vma, struct vm_fault \*vmf); }; .. code-block:: c
struct vm_operations_struct {
void (*open)(struct vm_area_struct * area);
void (*close)(struct vm_area_struct * area);
int (*fault)(struct vm_fault *vmf);
};
The open and close operations must update the GEM object reference The open and close operations must update the GEM object reference
count. Drivers can use the :c:func:`drm_gem_vm_open()` and count. Drivers can use the :c:func:`drm_gem_vm_open()` and
......
...@@ -3970,6 +3970,7 @@ S: Maintained ...@@ -3970,6 +3970,7 @@ S: Maintained
L: linux-media@vger.kernel.org L: linux-media@vger.kernel.org
L: dri-devel@lists.freedesktop.org L: dri-devel@lists.freedesktop.org
F: drivers/dma-buf/sync_* F: drivers/dma-buf/sync_*
F: drivers/dma-buf/dma-fence*
F: drivers/dma-buf/sw_sync.c F: drivers/dma-buf/sw_sync.c
F: include/linux/sync_file.h F: include/linux/sync_file.h
F: include/uapi/linux/sync_file.h F: include/uapi/linux/sync_file.h
......
...@@ -1709,6 +1709,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data); ...@@ -1709,6 +1709,7 @@ int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data);
int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type, int amdgpu_cs_get_ring(struct amdgpu_device *adev, u32 ip_type,
u32 ip_instance, u32 ring, u32 ip_instance, u32 ring,
struct amdgpu_ring **out_ring); struct amdgpu_ring **out_ring);
void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes);
void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain); void amdgpu_ttm_placement_from_domain(struct amdgpu_bo *abo, u32 domain);
bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo); bool amdgpu_ttm_bo_is_amdgpu_bo(struct ttm_buffer_object *bo);
int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages); int amdgpu_ttm_tt_get_user_pages(struct ttm_tt *ttm, struct page **pages);
......
...@@ -850,16 +850,37 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device, ...@@ -850,16 +850,37 @@ static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
strcpy(fw_name, "amdgpu/fiji_smc.bin"); strcpy(fw_name, "amdgpu/fiji_smc.bin");
break; break;
case CHIP_POLARIS11: case CHIP_POLARIS11:
if (type == CGS_UCODE_ID_SMU) if (type == CGS_UCODE_ID_SMU) {
strcpy(fw_name, "amdgpu/polaris11_smc.bin"); if (((adev->pdev->device == 0x67ef) &&
else if (type == CGS_UCODE_ID_SMU_SK) ((adev->pdev->revision == 0xe0) ||
(adev->pdev->revision == 0xe2) ||
(adev->pdev->revision == 0xe5))) ||
((adev->pdev->device == 0x67ff) &&
((adev->pdev->revision == 0xcf) ||
(adev->pdev->revision == 0xef) ||
(adev->pdev->revision == 0xff))))
strcpy(fw_name, "amdgpu/polaris11_k_smc.bin");
else
strcpy(fw_name, "amdgpu/polaris11_smc.bin");
} else if (type == CGS_UCODE_ID_SMU_SK) {
strcpy(fw_name, "amdgpu/polaris11_smc_sk.bin"); strcpy(fw_name, "amdgpu/polaris11_smc_sk.bin");
}
break; break;
case CHIP_POLARIS10: case CHIP_POLARIS10:
if (type == CGS_UCODE_ID_SMU) if (type == CGS_UCODE_ID_SMU) {
strcpy(fw_name, "amdgpu/polaris10_smc.bin"); if ((adev->pdev->device == 0x67df) &&
else if (type == CGS_UCODE_ID_SMU_SK) ((adev->pdev->revision == 0xe0) ||
(adev->pdev->revision == 0xe3) ||
(adev->pdev->revision == 0xe4) ||
(adev->pdev->revision == 0xe5) ||
(adev->pdev->revision == 0xe7) ||
(adev->pdev->revision == 0xef)))
strcpy(fw_name, "amdgpu/polaris10_k_smc.bin");
else
strcpy(fw_name, "amdgpu/polaris10_smc.bin");
} else if (type == CGS_UCODE_ID_SMU_SK) {
strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin"); strcpy(fw_name, "amdgpu/polaris10_smc_sk.bin");
}
break; break;
case CHIP_POLARIS12: case CHIP_POLARIS12:
strcpy(fw_name, "amdgpu/polaris12_smc.bin"); strcpy(fw_name, "amdgpu/polaris12_smc.bin");
......
...@@ -344,8 +344,7 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev) ...@@ -344,8 +344,7 @@ static u64 amdgpu_cs_get_threshold_for_moves(struct amdgpu_device *adev)
* submission. This can result in a debt that can stop buffer migrations * submission. This can result in a debt that can stop buffer migrations
* temporarily. * temporarily.
*/ */
static void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, void amdgpu_cs_report_moved_bytes(struct amdgpu_device *adev, u64 num_bytes)
u64 num_bytes)
{ {
spin_lock(&adev->mm_stats.lock); spin_lock(&adev->mm_stats.lock);
adev->mm_stats.accum_us -= bytes_to_us(adev, num_bytes); adev->mm_stats.accum_us -= bytes_to_us(adev, num_bytes);
......
...@@ -374,7 +374,6 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev) ...@@ -374,7 +374,6 @@ int amdgpu_fbdev_init(struct amdgpu_device *adev)
&amdgpu_fb_helper_funcs); &amdgpu_fb_helper_funcs);
ret = drm_fb_helper_init(adev->ddev, &rfbdev->helper, ret = drm_fb_helper_init(adev->ddev, &rfbdev->helper,
adev->mode_info.num_crtc,
AMDGPUFB_CONN_LIMIT); AMDGPUFB_CONN_LIMIT);
if (ret) { if (ret) {
kfree(rfbdev); kfree(rfbdev);
......
...@@ -487,67 +487,50 @@ static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo) ...@@ -487,67 +487,50 @@ static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
* *
* @adev: amdgpu_device pointer * @adev: amdgpu_device pointer
* @bo_va: bo_va to update * @bo_va: bo_va to update
* @list: validation list
* @operation: map or unmap
* *
* Update the bo_va directly after setting it's address. Errors are not * Update the bo_va directly after setting its address. Errors are not
* vital here, so they are not reported back to userspace. * vital here, so they are not reported back to userspace.
*/ */
static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
struct amdgpu_bo_va *bo_va, struct amdgpu_bo_va *bo_va,
struct list_head *list,
uint32_t operation) uint32_t operation)
{ {
struct ttm_validate_buffer tv, *entry; struct ttm_validate_buffer *entry;
struct amdgpu_bo_list_entry vm_pd; int r = -ERESTARTSYS;
struct ww_acquire_ctx ticket;
struct list_head list, duplicates;
int r;
INIT_LIST_HEAD(&list);
INIT_LIST_HEAD(&duplicates);
tv.bo = &bo_va->bo->tbo;
tv.shared = true;
list_add(&tv.head, &list);
amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd); list_for_each_entry(entry, list, head) {
/* Provide duplicates to avoid -EALREADY */
r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates);
if (r)
goto error_print;
list_for_each_entry(entry, &list, head) {
struct amdgpu_bo *bo = struct amdgpu_bo *bo =
container_of(entry->bo, struct amdgpu_bo, tbo); container_of(entry->bo, struct amdgpu_bo, tbo);
/* if anything is swapped out don't swap it in here, /* if anything is swapped out don't swap it in here,
just abort and wait for the next CS */ just abort and wait for the next CS */
if (!amdgpu_bo_gpu_accessible(bo)) if (!amdgpu_bo_gpu_accessible(bo))
goto error_unreserve; goto error;
if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow)) if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))
goto error_unreserve; goto error;
} }
r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check, r = amdgpu_vm_validate_pt_bos(adev, bo_va->vm, amdgpu_gem_va_check,
NULL); NULL);
if (r) if (r)
goto error_unreserve; goto error;
r = amdgpu_vm_update_page_directory(adev, bo_va->vm); r = amdgpu_vm_update_page_directory(adev, bo_va->vm);
if (r) if (r)
goto error_unreserve; goto error;
r = amdgpu_vm_clear_freed(adev, bo_va->vm); r = amdgpu_vm_clear_freed(adev, bo_va->vm);
if (r) if (r)
goto error_unreserve; goto error;
if (operation == AMDGPU_VA_OP_MAP) if (operation == AMDGPU_VA_OP_MAP)
r = amdgpu_vm_bo_update(adev, bo_va, false); r = amdgpu_vm_bo_update(adev, bo_va, false);
error_unreserve: error:
ttm_eu_backoff_reservation(&ticket, &list);
error_print:
if (r && r != -ERESTARTSYS) if (r && r != -ERESTARTSYS)
DRM_ERROR("Couldn't update BO_VA (%d)\n", r); DRM_ERROR("Couldn't update BO_VA (%d)\n", r);
} }
...@@ -564,7 +547,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, ...@@ -564,7 +547,7 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
struct amdgpu_bo_list_entry vm_pd; struct amdgpu_bo_list_entry vm_pd;
struct ttm_validate_buffer tv; struct ttm_validate_buffer tv;
struct ww_acquire_ctx ticket; struct ww_acquire_ctx ticket;
struct list_head list, duplicates; struct list_head list;
uint32_t invalid_flags, va_flags = 0; uint32_t invalid_flags, va_flags = 0;
int r = 0; int r = 0;
...@@ -602,14 +585,13 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, ...@@ -602,14 +585,13 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
return -ENOENT; return -ENOENT;
abo = gem_to_amdgpu_bo(gobj); abo = gem_to_amdgpu_bo(gobj);
INIT_LIST_HEAD(&list); INIT_LIST_HEAD(&list);
INIT_LIST_HEAD(&duplicates);
tv.bo = &abo->tbo; tv.bo = &abo->tbo;
tv.shared = true; tv.shared = false;
list_add(&tv.head, &list); list_add(&tv.head, &list);
amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd); amdgpu_vm_get_pd_bo(&fpriv->vm, &list, &vm_pd);
r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); r = ttm_eu_reserve_buffers(&ticket, &list, true, NULL);
if (r) { if (r) {
drm_gem_object_unreference_unlocked(gobj); drm_gem_object_unreference_unlocked(gobj);
return r; return r;
...@@ -640,10 +622,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, ...@@ -640,10 +622,10 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data,
default: default:
break; break;
} }
ttm_eu_backoff_reservation(&ticket, &list);
if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) && if (!r && !(args->flags & AMDGPU_VM_DELAY_UPDATE) &&
!amdgpu_vm_debug) !amdgpu_vm_debug)
amdgpu_gem_va_update_vm(adev, bo_va, args->operation); amdgpu_gem_va_update_vm(adev, bo_va, &list, args->operation);
ttm_eu_backoff_reservation(&ticket, &list);
drm_gem_object_unreference_unlocked(gobj); drm_gem_object_unreference_unlocked(gobj);
return r; return r;
......
...@@ -97,8 +97,7 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, ...@@ -97,8 +97,7 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
{ {
struct amdgpu_gtt_mgr *mgr = man->priv; struct amdgpu_gtt_mgr *mgr = man->priv;
struct drm_mm_node *node = mem->mm_node; struct drm_mm_node *node = mem->mm_node;
enum drm_mm_search_flags sflags = DRM_MM_SEARCH_BEST; enum drm_mm_insert_mode mode;
enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT;
unsigned long fpfn, lpfn; unsigned long fpfn, lpfn;
int r; int r;
...@@ -115,15 +114,14 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man, ...@@ -115,15 +114,14 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
else else
lpfn = man->size; lpfn = man->size;
if (place && place->flags & TTM_PL_FLAG_TOPDOWN) { mode = DRM_MM_INSERT_BEST;
sflags = DRM_MM_SEARCH_BELOW; if (place && place->flags & TTM_PL_FLAG_TOPDOWN)
aflags = DRM_MM_CREATE_TOP; mode = DRM_MM_INSERT_HIGH;
}
spin_lock(&mgr->lock); spin_lock(&mgr->lock);
r = drm_mm_insert_node_in_range_generic(&mgr->mm, node, mem->num_pages, r = drm_mm_insert_node_in_range(&mgr->mm, node,
mem->page_alignment, 0, mem->num_pages, mem->page_alignment, 0,
fpfn, lpfn, sflags, aflags); fpfn, lpfn, mode);
spin_unlock(&mgr->lock); spin_unlock(&mgr->lock);
if (!r) { if (!r) {
......
...@@ -323,6 +323,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, ...@@ -323,6 +323,7 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
struct amdgpu_bo *bo; struct amdgpu_bo *bo;
enum ttm_bo_type type; enum ttm_bo_type type;
unsigned long page_align; unsigned long page_align;
u64 initial_bytes_moved;
size_t acc_size; size_t acc_size;
int r; int r;
...@@ -374,8 +375,10 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, ...@@ -374,8 +375,10 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
* See https://bugs.freedesktop.org/show_bug.cgi?id=88758 * See https://bugs.freedesktop.org/show_bug.cgi?id=88758
*/ */
#ifndef CONFIG_COMPILE_TEST
#warning Please enable CONFIG_MTRR and CONFIG_X86_PAT for better performance \ #warning Please enable CONFIG_MTRR and CONFIG_X86_PAT for better performance \
thanks to write-combining thanks to write-combining
#endif
if (bo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC) if (bo->flags & AMDGPU_GEM_CREATE_CPU_GTT_USWC)
DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for " DRM_INFO_ONCE("Please enable CONFIG_MTRR and CONFIG_X86_PAT for "
...@@ -399,12 +402,20 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev, ...@@ -399,12 +402,20 @@ int amdgpu_bo_create_restricted(struct amdgpu_device *adev,
locked = ww_mutex_trylock(&bo->tbo.ttm_resv.lock); locked = ww_mutex_trylock(&bo->tbo.ttm_resv.lock);
WARN_ON(!locked); WARN_ON(!locked);
} }
initial_bytes_moved = atomic64_read(&adev->num_bytes_moved);
r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type, r = ttm_bo_init(&adev->mman.bdev, &bo->tbo, size, type,
&bo->placement, page_align, !kernel, NULL, &bo->placement, page_align, !kernel, NULL,
acc_size, sg, resv ? resv : &bo->tbo.ttm_resv, acc_size, sg, resv ? resv : &bo->tbo.ttm_resv,
&amdgpu_ttm_bo_destroy); &amdgpu_ttm_bo_destroy);
if (unlikely(r != 0)) amdgpu_cs_report_moved_bytes(adev,
atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved);
if (unlikely(r != 0)) {
if (!resv)
ww_mutex_unlock(&bo->tbo.resv->lock);
return r; return r;
}
bo->tbo.priority = ilog2(bo->tbo.num_pages); bo->tbo.priority = ilog2(bo->tbo.num_pages);
if (kernel) if (kernel)
......
...@@ -1142,12 +1142,22 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) ...@@ -1142,12 +1142,22 @@ void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable)
/* XXX select vce level based on ring/task */ /* XXX select vce level based on ring/task */
adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL; adev->pm.dpm.vce_level = AMD_VCE_LEVEL_AC_ALL;
mutex_unlock(&adev->pm.mutex); mutex_unlock(&adev->pm.mutex);
amdgpu_pm_compute_clocks(adev);
amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE);
} else { } else {
amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_GATE);
amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_GATE);
mutex_lock(&adev->pm.mutex); mutex_lock(&adev->pm.mutex);
adev->pm.dpm.vce_active = false; adev->pm.dpm.vce_active = false;
mutex_unlock(&adev->pm.mutex); mutex_unlock(&adev->pm.mutex);
amdgpu_pm_compute_clocks(adev);
} }
amdgpu_pm_compute_clocks(adev);
} }
} }
......
...@@ -1113,6 +1113,11 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work) ...@@ -1113,6 +1113,11 @@ static void amdgpu_uvd_idle_work_handler(struct work_struct *work)
amdgpu_dpm_enable_uvd(adev, false); amdgpu_dpm_enable_uvd(adev, false);
} else { } else {
amdgpu_asic_set_uvd_clocks(adev, 0, 0); amdgpu_asic_set_uvd_clocks(adev, 0, 0);
/* shutdown the UVD block */
amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE);
amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
} }
} else { } else {
schedule_delayed_work(&adev->uvd.idle_work, UVD_IDLE_TIMEOUT); schedule_delayed_work(&adev->uvd.idle_work, UVD_IDLE_TIMEOUT);
...@@ -1129,6 +1134,10 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring) ...@@ -1129,6 +1134,10 @@ void amdgpu_uvd_ring_begin_use(struct amdgpu_ring *ring)
amdgpu_dpm_enable_uvd(adev, true); amdgpu_dpm_enable_uvd(adev, true);
} else { } else {
amdgpu_asic_set_uvd_clocks(adev, 53300, 40000); amdgpu_asic_set_uvd_clocks(adev, 53300, 40000);
amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_UNGATE);
} }
} }
} }
......
...@@ -321,6 +321,10 @@ static void amdgpu_vce_idle_work_handler(struct work_struct *work) ...@@ -321,6 +321,10 @@ static void amdgpu_vce_idle_work_handler(struct work_struct *work)
amdgpu_dpm_enable_vce(adev, false); amdgpu_dpm_enable_vce(adev, false);
} else { } else {
amdgpu_asic_set_vce_clocks(adev, 0, 0); amdgpu_asic_set_vce_clocks(adev, 0, 0);
amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_GATE);
amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_GATE);
} }
} else { } else {
schedule_delayed_work(&adev->vce.idle_work, VCE_IDLE_TIMEOUT); schedule_delayed_work(&adev->vce.idle_work, VCE_IDLE_TIMEOUT);
...@@ -346,6 +350,11 @@ void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring) ...@@ -346,6 +350,11 @@ void amdgpu_vce_ring_begin_use(struct amdgpu_ring *ring)
amdgpu_dpm_enable_vce(adev, true); amdgpu_dpm_enable_vce(adev, true);
} else { } else {
amdgpu_asic_set_vce_clocks(adev, 53300, 40000); amdgpu_asic_set_vce_clocks(adev, 53300, 40000);
amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE);
amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
} }
} }
mutex_unlock(&adev->vce.idle_mutex); mutex_unlock(&adev->vce.idle_mutex);
......
...@@ -83,7 +83,6 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm) ...@@ -83,7 +83,6 @@ int amdgpu_map_static_csa(struct amdgpu_device *adev, struct amdgpu_vm *vm)
DRM_ERROR("failed to do bo_map on static CSA, err=%d\n", r); DRM_ERROR("failed to do bo_map on static CSA, err=%d\n", r);
amdgpu_vm_bo_rmv(adev, bo_va); amdgpu_vm_bo_rmv(adev, bo_va);
ttm_eu_backoff_reservation(&ticket, &list); ttm_eu_backoff_reservation(&ticket, &list);
kfree(bo_va);
return r; return r;
} }
......
...@@ -97,8 +97,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, ...@@ -97,8 +97,7 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
struct amdgpu_vram_mgr *mgr = man->priv; struct amdgpu_vram_mgr *mgr = man->priv;
struct drm_mm *mm = &mgr->mm; struct drm_mm *mm = &mgr->mm;
struct drm_mm_node *nodes; struct drm_mm_node *nodes;
enum drm_mm_search_flags sflags = DRM_MM_SEARCH_DEFAULT; enum drm_mm_insert_mode mode;
enum drm_mm_allocator_flags aflags = DRM_MM_CREATE_DEFAULT;
unsigned long lpfn, num_nodes, pages_per_node, pages_left; unsigned long lpfn, num_nodes, pages_per_node, pages_left;
unsigned i; unsigned i;
int r; int r;
...@@ -121,10 +120,9 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, ...@@ -121,10 +120,9 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
if (!nodes) if (!nodes)
return -ENOMEM; return -ENOMEM;
if (place->flags & TTM_PL_FLAG_TOPDOWN) { mode = DRM_MM_INSERT_BEST;
sflags = DRM_MM_SEARCH_BELOW; if (place->flags & TTM_PL_FLAG_TOPDOWN)
aflags = DRM_MM_CREATE_TOP; mode = DRM_MM_INSERT_HIGH;
}
pages_left = mem->num_pages; pages_left = mem->num_pages;
...@@ -135,13 +133,11 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man, ...@@ -135,13 +133,11 @@ static int amdgpu_vram_mgr_new(struct ttm_mem_type_manager *man,
if (pages == pages_per_node) if (pages == pages_per_node)
alignment = pages_per_node; alignment = pages_per_node;
else
sflags |= DRM_MM_SEARCH_BEST;
r = drm_mm_insert_node_in_range_generic(mm, &nodes[i], pages, r = drm_mm_insert_node_in_range(mm, &nodes[i],
alignment, 0, pages, alignment, 0,
place->fpfn, lpfn, place->fpfn, lpfn,
sflags, aflags); mode);
if (unlikely(r)) if (unlikely(r))
goto error; goto error;
......
...@@ -2210,7 +2210,6 @@ static void ci_clear_vc(struct amdgpu_device *adev) ...@@ -2210,7 +2210,6 @@ static void ci_clear_vc(struct amdgpu_device *adev)
static int ci_upload_firmware(struct amdgpu_device *adev) static int ci_upload_firmware(struct amdgpu_device *adev)
{ {
struct ci_power_info *pi = ci_get_pi(adev);
int i, ret; int i, ret;
if (amdgpu_ci_is_smc_running(adev)) { if (amdgpu_ci_is_smc_running(adev)) {
...@@ -2227,7 +2226,7 @@ static int ci_upload_firmware(struct amdgpu_device *adev) ...@@ -2227,7 +2226,7 @@ static int ci_upload_firmware(struct amdgpu_device *adev)
amdgpu_ci_stop_smc_clock(adev); amdgpu_ci_stop_smc_clock(adev);
amdgpu_ci_reset_smc(adev); amdgpu_ci_reset_smc(adev);
ret = amdgpu_ci_load_smc_ucode(adev, pi->sram_end); ret = amdgpu_ci_load_smc_ucode(adev, SMC_RAM_END);
return ret; return ret;
...@@ -4257,12 +4256,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev, ...@@ -4257,12 +4256,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev,
if (amdgpu_current_state->evclk != amdgpu_new_state->evclk) { if (amdgpu_current_state->evclk != amdgpu_new_state->evclk) {
if (amdgpu_new_state->evclk) { if (amdgpu_new_state->evclk) {
/* turn the clocks on when encoding */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE);
if (ret)
return ret;
pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(adev); pi->smc_state_table.VceBootLevel = ci_get_vce_boot_level(adev);
tmp = RREG32_SMC(ixDPM_TABLE_475); tmp = RREG32_SMC(ixDPM_TABLE_475);
tmp &= ~DPM_TABLE_475__VceBootLevel_MASK; tmp &= ~DPM_TABLE_475__VceBootLevel_MASK;
...@@ -4274,9 +4267,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev, ...@@ -4274,9 +4267,6 @@ static int ci_update_vce_dpm(struct amdgpu_device *adev,
ret = ci_enable_vce_dpm(adev, false); ret = ci_enable_vce_dpm(adev, false);
if (ret) if (ret)
return ret; return ret;
/* turn the clocks off when not encoding */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_GATE);
} }
} }
return ret; return ret;
...@@ -6278,13 +6268,13 @@ static int ci_dpm_sw_init(void *handle) ...@@ -6278,13 +6268,13 @@ static int ci_dpm_sw_init(void *handle)
adev->pm.current_mclk = adev->clock.default_mclk; adev->pm.current_mclk = adev->clock.default_mclk;
adev->pm.int_thermal_type = THERMAL_TYPE_NONE; adev->pm.int_thermal_type = THERMAL_TYPE_NONE;
if (amdgpu_dpm == 0)
return 0;
ret = ci_dpm_init_microcode(adev); ret = ci_dpm_init_microcode(adev);
if (ret) if (ret)
return ret; return ret;
if (amdgpu_dpm == 0)
return 0;
INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler); INIT_WORK(&adev->pm.dpm.thermal.work, amdgpu_dpm_thermal_work_handler);
mutex_lock(&adev->pm.mutex); mutex_lock(&adev->pm.mutex);
ret = ci_dpm_init(adev); ret = ci_dpm_init(adev);
...@@ -6328,8 +6318,15 @@ static int ci_dpm_hw_init(void *handle) ...@@ -6328,8 +6318,15 @@ static int ci_dpm_hw_init(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (!amdgpu_dpm) if (!amdgpu_dpm) {
ret = ci_upload_firmware(adev);
if (ret) {
DRM_ERROR("ci_upload_firmware failed\n");
return ret;
}
ci_dpm_start_smc(adev);
return 0; return 0;
}
mutex_lock(&adev->pm.mutex); mutex_lock(&adev->pm.mutex);
ci_dpm_setup_asic(adev); ci_dpm_setup_asic(adev);
...@@ -6351,6 +6348,8 @@ static int ci_dpm_hw_fini(void *handle) ...@@ -6351,6 +6348,8 @@ static int ci_dpm_hw_fini(void *handle)
mutex_lock(&adev->pm.mutex); mutex_lock(&adev->pm.mutex);
ci_dpm_disable(adev); ci_dpm_disable(adev);
mutex_unlock(&adev->pm.mutex); mutex_unlock(&adev->pm.mutex);
} else {
ci_dpm_stop_smc(adev);
} }
return 0; return 0;
......
...@@ -1722,8 +1722,8 @@ static int cik_common_early_init(void *handle) ...@@ -1722,8 +1722,8 @@ static int cik_common_early_init(void *handle)
AMD_PG_SUPPORT_GFX_SMG | AMD_PG_SUPPORT_GFX_SMG |
AMD_PG_SUPPORT_GFX_DMG |*/ AMD_PG_SUPPORT_GFX_DMG |*/
AMD_PG_SUPPORT_UVD | AMD_PG_SUPPORT_UVD |
/*AMD_PG_SUPPORT_VCE | AMD_PG_SUPPORT_VCE |
AMD_PG_SUPPORT_CP | /* AMD_PG_SUPPORT_CP |
AMD_PG_SUPPORT_GDS | AMD_PG_SUPPORT_GDS |
AMD_PG_SUPPORT_RLC_SMU_HS | AMD_PG_SUPPORT_RLC_SMU_HS |
AMD_PG_SUPPORT_ACP | AMD_PG_SUPPORT_ACP |
......
...@@ -1325,21 +1325,19 @@ static u32 gfx_v6_0_create_bitmask(u32 bit_width) ...@@ -1325,21 +1325,19 @@ static u32 gfx_v6_0_create_bitmask(u32 bit_width)
return (u32)(((u64)1 << bit_width) - 1); return (u32)(((u64)1 << bit_width) - 1);
} }
static u32 gfx_v6_0_get_rb_disabled(struct amdgpu_device *adev, static u32 gfx_v6_0_get_rb_active_bitmap(struct amdgpu_device *adev)
u32 max_rb_num_per_se,
u32 sh_per_se)
{ {
u32 data, mask; u32 data, mask;
data = RREG32(mmCC_RB_BACKEND_DISABLE); data = RREG32(mmCC_RB_BACKEND_DISABLE) |
data &= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK; RREG32(mmGC_USER_RB_BACKEND_DISABLE);
data |= RREG32(mmGC_USER_RB_BACKEND_DISABLE);
data >>= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT; data = REG_GET_FIELD(data, GC_USER_RB_BACKEND_DISABLE, BACKEND_DISABLE);
mask = gfx_v6_0_create_bitmask(max_rb_num_per_se / sh_per_se); mask = gfx_v6_0_create_bitmask(adev->gfx.config.max_backends_per_se/
adev->gfx.config.max_sh_per_se);
return data & mask; return ~data & mask;
} }
static void gfx_v6_0_raster_config(struct amdgpu_device *adev, u32 *rconf) static void gfx_v6_0_raster_config(struct amdgpu_device *adev, u32 *rconf)
...@@ -1468,68 +1466,55 @@ static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev, ...@@ -1468,68 +1466,55 @@ static void gfx_v6_0_write_harvested_raster_configs(struct amdgpu_device *adev,
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
} }
static void gfx_v6_0_setup_rb(struct amdgpu_device *adev, static void gfx_v6_0_setup_rb(struct amdgpu_device *adev)
u32 se_num, u32 sh_per_se,
u32 max_rb_num_per_se)
{ {
int i, j; int i, j;
u32 data, mask; u32 data;
u32 disabled_rbs = 0; u32 raster_config = 0;
u32 enabled_rbs = 0; u32 active_rbs = 0;
u32 rb_bitmap_width_per_sh = adev->gfx.config.max_backends_per_se /
adev->gfx.config.max_sh_per_se;
unsigned num_rb_pipes; unsigned num_rb_pipes;
mutex_lock(&adev->grbm_idx_mutex); mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < se_num; i++) { for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < sh_per_se; j++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff); gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
data = gfx_v6_0_get_rb_disabled(adev, max_rb_num_per_se, sh_per_se); data = gfx_v6_0_get_rb_active_bitmap(adev);
disabled_rbs |= data << ((i * sh_per_se + j) * 2); active_rbs |= data << ((i * adev->gfx.config.max_sh_per_se + j) *
rb_bitmap_width_per_sh);
} }
} }
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
mask = 1;
for (i = 0; i < max_rb_num_per_se * se_num; i++) {
if (!(disabled_rbs & mask))
enabled_rbs |= mask;
mask <<= 1;
}
adev->gfx.config.backend_enable_mask = enabled_rbs; adev->gfx.config.backend_enable_mask = active_rbs;
adev->gfx.config.num_rbs = hweight32(enabled_rbs); adev->gfx.config.num_rbs = hweight32(active_rbs);
num_rb_pipes = min_t(unsigned, adev->gfx.config.max_backends_per_se * num_rb_pipes = min_t(unsigned, adev->gfx.config.max_backends_per_se *
adev->gfx.config.max_shader_engines, 16); adev->gfx.config.max_shader_engines, 16);
mutex_lock(&adev->grbm_idx_mutex); gfx_v6_0_raster_config(adev, &raster_config);
for (i = 0; i < se_num; i++) {
gfx_v6_0_select_se_sh(adev, i, 0xffffffff, 0xffffffff);
data = 0;
for (j = 0; j < sh_per_se; j++) {
switch (enabled_rbs & 3) {
case 1:
data |= (RASTER_CONFIG_RB_MAP_0 << (i * sh_per_se + j) * 2);
break;
case 2:
data |= (RASTER_CONFIG_RB_MAP_3 << (i * sh_per_se + j) * 2);
break;
case 3:
default:
data |= (RASTER_CONFIG_RB_MAP_2 << (i * sh_per_se + j) * 2);
break;
}
enabled_rbs >>= 2;
}
gfx_v6_0_raster_config(adev, &data);
if (!adev->gfx.config.backend_enable_mask || if (!adev->gfx.config.backend_enable_mask ||
adev->gfx.config.num_rbs >= num_rb_pipes) adev->gfx.config.num_rbs >= num_rb_pipes) {
WREG32(mmPA_SC_RASTER_CONFIG, data); WREG32(mmPA_SC_RASTER_CONFIG, raster_config);
else } else {
gfx_v6_0_write_harvested_raster_configs(adev, data, gfx_v6_0_write_harvested_raster_configs(adev, raster_config,
adev->gfx.config.backend_enable_mask, adev->gfx.config.backend_enable_mask,
num_rb_pipes); num_rb_pipes);
}
/* cache the values for userspace */
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
adev->gfx.config.rb_config[i][j].rb_backend_disable =
RREG32(mmCC_RB_BACKEND_DISABLE);
adev->gfx.config.rb_config[i][j].user_rb_backend_disable =
RREG32(mmGC_USER_RB_BACKEND_DISABLE);
adev->gfx.config.rb_config[i][j].raster_config =
RREG32(mmPA_SC_RASTER_CONFIG);
}
} }
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
...@@ -1540,36 +1525,44 @@ static void gmc_v6_0_init_compute_vmid(struct amdgpu_device *adev) ...@@ -1540,36 +1525,44 @@ static void gmc_v6_0_init_compute_vmid(struct amdgpu_device *adev)
} }
*/ */
static u32 gfx_v6_0_get_cu_enabled(struct amdgpu_device *adev, u32 cu_per_sh) static void gfx_v6_0_set_user_cu_inactive_bitmap(struct amdgpu_device *adev,
u32 bitmap)
{ {
u32 data, mask; u32 data;
data = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG); if (!bitmap)
data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK; return;
data |= RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT; data = bitmap << GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
data &= GC_USER_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
mask = gfx_v6_0_create_bitmask(cu_per_sh); WREG32(mmGC_USER_SHADER_ARRAY_CONFIG, data);
}
return ~data & mask; static u32 gfx_v6_0_get_cu_enabled(struct amdgpu_device *adev)
{
u32 data, mask;
data = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG) |
RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
mask = gfx_v6_0_create_bitmask(adev->gfx.config.max_cu_per_sh);
return ~REG_GET_FIELD(data, CC_GC_SHADER_ARRAY_CONFIG, INACTIVE_CUS) & mask;
} }
static void gfx_v6_0_setup_spi(struct amdgpu_device *adev, static void gfx_v6_0_setup_spi(struct amdgpu_device *adev)
u32 se_num, u32 sh_per_se,
u32 cu_per_sh)
{ {
int i, j, k; int i, j, k;
u32 data, mask; u32 data, mask;
u32 active_cu = 0; u32 active_cu = 0;
mutex_lock(&adev->grbm_idx_mutex); mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < se_num; i++) { for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < sh_per_se; j++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff); gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
data = RREG32(mmSPI_STATIC_THREAD_MGMT_3); data = RREG32(mmSPI_STATIC_THREAD_MGMT_3);
active_cu = gfx_v6_0_get_cu_enabled(adev, cu_per_sh); active_cu = gfx_v6_0_get_cu_enabled(adev);
mask = 1; mask = 1;
for (k = 0; k < 16; k++) { for (k = 0; k < 16; k++) {
...@@ -1717,6 +1710,9 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev) ...@@ -1717,6 +1710,9 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
gb_addr_config |= 2 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT; gb_addr_config |= 2 << GB_ADDR_CONFIG__ROW_SIZE__SHIFT;
break; break;
} }
gb_addr_config &= ~GB_ADDR_CONFIG__NUM_SHADER_ENGINES_MASK;
if (adev->gfx.config.max_shader_engines == 2)
gb_addr_config |= 1 << GB_ADDR_CONFIG__NUM_SHADER_ENGINES__SHIFT;
adev->gfx.config.gb_addr_config = gb_addr_config; adev->gfx.config.gb_addr_config = gb_addr_config;
WREG32(mmGB_ADDR_CONFIG, gb_addr_config); WREG32(mmGB_ADDR_CONFIG, gb_addr_config);
...@@ -1735,13 +1731,9 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev) ...@@ -1735,13 +1731,9 @@ static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
#endif #endif
gfx_v6_0_tiling_mode_table_init(adev); gfx_v6_0_tiling_mode_table_init(adev);
gfx_v6_0_setup_rb(adev, adev->gfx.config.max_shader_engines, gfx_v6_0_setup_rb(adev);
adev->gfx.config.max_sh_per_se,
adev->gfx.config.max_backends_per_se);
gfx_v6_0_setup_spi(adev, adev->gfx.config.max_shader_engines, gfx_v6_0_setup_spi(adev);
adev->gfx.config.max_sh_per_se,
adev->gfx.config.max_cu_per_sh);
gfx_v6_0_get_cu_info(adev); gfx_v6_0_get_cu_info(adev);
...@@ -2941,61 +2933,16 @@ static void gfx_v6_0_enable_gfx_cgpg(struct amdgpu_device *adev, ...@@ -2941,61 +2933,16 @@ static void gfx_v6_0_enable_gfx_cgpg(struct amdgpu_device *adev,
} }
} }
static u32 gfx_v6_0_get_cu_active_bitmap(struct amdgpu_device *adev,
u32 se, u32 sh)
{
u32 mask = 0, tmp, tmp1;
int i;
mutex_lock(&adev->grbm_idx_mutex);
gfx_v6_0_select_se_sh(adev, se, sh, 0xffffffff);
tmp = RREG32(mmCC_GC_SHADER_ARRAY_CONFIG);
tmp1 = RREG32(mmGC_USER_SHADER_ARRAY_CONFIG);
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
tmp &= 0xffff0000;
tmp |= tmp1;
tmp >>= 16;
for (i = 0; i < adev->gfx.config.max_cu_per_sh; i ++) {
mask <<= 1;
mask |= 1;
}
return (~tmp) & mask;
}
static void gfx_v6_0_init_ao_cu_mask(struct amdgpu_device *adev) static void gfx_v6_0_init_ao_cu_mask(struct amdgpu_device *adev)
{ {
u32 i, j, k, active_cu_number = 0; u32 tmp;
u32 mask, counter, cu_bitmap;
u32 tmp = 0;
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
mask = 1;
cu_bitmap = 0;
counter = 0;
for (k = 0; k < adev->gfx.config.max_cu_per_sh; k++) {
if (gfx_v6_0_get_cu_active_bitmap(adev, i, j) & mask) {
if (counter < 2)
cu_bitmap |= mask;
counter++;
}
mask <<= 1;
}
active_cu_number += counter; WREG32(mmRLC_PG_ALWAYS_ON_CU_MASK, adev->gfx.cu_info.ao_cu_mask);
tmp |= (cu_bitmap << (i * 16 + j * 8));
}
}
WREG32(mmRLC_PG_AO_CU_MASK, tmp); tmp = RREG32(mmRLC_MAX_PG_CU);
WREG32_FIELD(RLC_MAX_PG_CU, MAX_POWERED_UP_CU, active_cu_number); tmp &= ~RLC_MAX_PG_CU__MAX_POWERED_UP_CU_MASK;
tmp |= (adev->gfx.cu_info.number << RLC_MAX_PG_CU__MAX_POWERED_UP_CU__SHIFT);
WREG32(mmRLC_MAX_PG_CU, tmp);
} }
static void gfx_v6_0_enable_gfx_static_mgpg(struct amdgpu_device *adev, static void gfx_v6_0_enable_gfx_static_mgpg(struct amdgpu_device *adev,
...@@ -3770,18 +3717,26 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev) ...@@ -3770,18 +3717,26 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev)
int i, j, k, counter, active_cu_number = 0; int i, j, k, counter, active_cu_number = 0;
u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0; u32 mask, bitmap, ao_bitmap, ao_cu_mask = 0;
struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info; struct amdgpu_cu_info *cu_info = &adev->gfx.cu_info;
unsigned disable_masks[4 * 2];
memset(cu_info, 0, sizeof(*cu_info)); memset(cu_info, 0, sizeof(*cu_info));
amdgpu_gfx_parse_disable_cu(disable_masks, 4, 2);
mutex_lock(&adev->grbm_idx_mutex);
for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { for (i = 0; i < adev->gfx.config.max_shader_engines; i++) {
for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
mask = 1; mask = 1;
ao_bitmap = 0; ao_bitmap = 0;
counter = 0; counter = 0;
bitmap = gfx_v6_0_get_cu_active_bitmap(adev, i, j); gfx_v6_0_select_se_sh(adev, i, j, 0xffffffff);
if (i < 4 && j < 2)
gfx_v6_0_set_user_cu_inactive_bitmap(
adev, disable_masks[i * 2 + j]);
bitmap = gfx_v6_0_get_cu_enabled(adev);
cu_info->bitmap[i][j] = bitmap; cu_info->bitmap[i][j] = bitmap;
for (k = 0; k < adev->gfx.config.max_cu_per_sh; k ++) { for (k = 0; k < 16; k++) {
if (bitmap & mask) { if (bitmap & mask) {
if (counter < 2) if (counter < 2)
ao_bitmap |= mask; ao_bitmap |= mask;
...@@ -3794,6 +3749,9 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev) ...@@ -3794,6 +3749,9 @@ static void gfx_v6_0_get_cu_info(struct amdgpu_device *adev)
} }
} }
gfx_v6_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex);
cu_info->number = active_cu_number; cu_info->number = active_cu_number;
cu_info->ao_cu_mask = ao_cu_mask; cu_info->ao_cu_mask = ao_cu_mask;
} }
......
...@@ -1550,11 +1550,6 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev, ...@@ -1550,11 +1550,6 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev,
if (amdgpu_new_state->evclk > 0 && amdgpu_current_state->evclk == 0) { if (amdgpu_new_state->evclk > 0 && amdgpu_current_state->evclk == 0) {
kv_dpm_powergate_vce(adev, false); kv_dpm_powergate_vce(adev, false);
/* turn the clocks on when encoding */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE);
if (ret)
return ret;
if (pi->caps_stable_p_state) if (pi->caps_stable_p_state)
pi->vce_boot_level = table->count - 1; pi->vce_boot_level = table->count - 1;
else else
...@@ -1573,15 +1568,9 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev, ...@@ -1573,15 +1568,9 @@ static int kv_update_vce_dpm(struct amdgpu_device *adev,
amdgpu_kv_send_msg_to_smc_with_parameter(adev, amdgpu_kv_send_msg_to_smc_with_parameter(adev,
PPSMC_MSG_VCEDPM_SetEnabledMask, PPSMC_MSG_VCEDPM_SetEnabledMask,
(1 << pi->vce_boot_level)); (1 << pi->vce_boot_level));
kv_enable_vce_dpm(adev, true); kv_enable_vce_dpm(adev, true);
} else if (amdgpu_new_state->evclk == 0 && amdgpu_current_state->evclk > 0) { } else if (amdgpu_new_state->evclk == 0 && amdgpu_current_state->evclk > 0) {
kv_enable_vce_dpm(adev, false); kv_enable_vce_dpm(adev, false);
/* turn the clocks off when not encoding */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_GATE);
if (ret)
return ret;
kv_dpm_powergate_vce(adev, true); kv_dpm_powergate_vce(adev, true);
} }
...@@ -1688,70 +1677,44 @@ static void kv_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate) ...@@ -1688,70 +1677,44 @@ static void kv_dpm_powergate_uvd(struct amdgpu_device *adev, bool gate)
struct kv_power_info *pi = kv_get_pi(adev); struct kv_power_info *pi = kv_get_pi(adev);
int ret; int ret;
if (pi->uvd_power_gated == gate)
return;
pi->uvd_power_gated = gate; pi->uvd_power_gated = gate;
if (gate) { if (gate) {
if (pi->caps_uvd_pg) { /* stop the UVD block */
/* disable clockgating so we can properly shut down the block */ ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD, AMD_PG_STATE_GATE);
AMD_CG_STATE_UNGATE);
/* shutdown the UVD block */
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE);
/* XXX: check for errors */
}
kv_update_uvd_dpm(adev, gate); kv_update_uvd_dpm(adev, gate);
if (pi->caps_uvd_pg) if (pi->caps_uvd_pg)
/* power off the UVD block */ /* power off the UVD block */
amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerOFF); amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerOFF);
} else { } else {
if (pi->caps_uvd_pg) { if (pi->caps_uvd_pg)
/* power on the UVD block */ /* power on the UVD block */
amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerON); amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_UVDPowerON);
/* re-init the UVD block */ /* re-init the UVD block */
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_UNGATE);
/* enable clockgating. hw will dynamically gate/ungate clocks on the fly */
ret = amdgpu_set_clockgating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
/* XXX: check for errors */
}
kv_update_uvd_dpm(adev, gate); kv_update_uvd_dpm(adev, gate);
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_UNGATE);
} }
} }
static void kv_dpm_powergate_vce(struct amdgpu_device *adev, bool gate) static void kv_dpm_powergate_vce(struct amdgpu_device *adev, bool gate)
{ {
struct kv_power_info *pi = kv_get_pi(adev); struct kv_power_info *pi = kv_get_pi(adev);
int ret;
if (pi->vce_power_gated == gate) if (pi->vce_power_gated == gate)
return; return;
pi->vce_power_gated = gate; pi->vce_power_gated = gate;
if (gate) { if (!pi->caps_vce_pg)
if (pi->caps_vce_pg) { return;
/* shutdown the VCE block */
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE, if (gate)
AMD_PG_STATE_GATE); amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF);
/* XXX: check for errors */ else
/* power off the VCE block */ amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON);
amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerOFF);
}
} else {
if (pi->caps_vce_pg) {
/* power on the VCE block */
amdgpu_kv_notify_message_to_smu(adev, PPSMC_MSG_VCEPowerON);
/* re-init the VCE block */
ret = amdgpu_set_powergating_state(adev, AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
/* XXX: check for errors */
}
}
} }
static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate) static void kv_dpm_powergate_samu(struct amdgpu_device *adev, bool gate)
...@@ -3009,8 +2972,7 @@ static int kv_dpm_late_init(void *handle) ...@@ -3009,8 +2972,7 @@ static int kv_dpm_late_init(void *handle)
kv_dpm_powergate_acp(adev, true); kv_dpm_powergate_acp(adev, true);
kv_dpm_powergate_samu(adev, true); kv_dpm_powergate_samu(adev, true);
kv_dpm_powergate_vce(adev, true);
kv_dpm_powergate_uvd(adev, true);
return 0; return 0;
} }
......
...@@ -1010,24 +1010,81 @@ static struct amdgpu_allowed_register_entry si_allowed_read_registers[] = { ...@@ -1010,24 +1010,81 @@ static struct amdgpu_allowed_register_entry si_allowed_read_registers[] = {
{PA_SC_RASTER_CONFIG, false, true}, {PA_SC_RASTER_CONFIG, false, true},
}; };
static uint32_t si_read_indexed_register(struct amdgpu_device *adev, static uint32_t si_get_register_value(struct amdgpu_device *adev,
u32 se_num, u32 sh_num, bool indexed, u32 se_num,
u32 reg_offset) u32 sh_num, u32 reg_offset)
{ {
uint32_t val; if (indexed) {
uint32_t val;
unsigned se_idx = (se_num == 0xffffffff) ? 0 : se_num;
unsigned sh_idx = (sh_num == 0xffffffff) ? 0 : sh_num;
switch (reg_offset) {
case mmCC_RB_BACKEND_DISABLE:
return adev->gfx.config.rb_config[se_idx][sh_idx].rb_backend_disable;
case mmGC_USER_RB_BACKEND_DISABLE:
return adev->gfx.config.rb_config[se_idx][sh_idx].user_rb_backend_disable;
case mmPA_SC_RASTER_CONFIG:
return adev->gfx.config.rb_config[se_idx][sh_idx].raster_config;
}
mutex_lock(&adev->grbm_idx_mutex); mutex_lock(&adev->grbm_idx_mutex);
if (se_num != 0xffffffff || sh_num != 0xffffffff) if (se_num != 0xffffffff || sh_num != 0xffffffff)
amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff); amdgpu_gfx_select_se_sh(adev, se_num, sh_num, 0xffffffff);
val = RREG32(reg_offset); val = RREG32(reg_offset);
if (se_num != 0xffffffff || sh_num != 0xffffffff) if (se_num != 0xffffffff || sh_num != 0xffffffff)
amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff); amdgpu_gfx_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
mutex_unlock(&adev->grbm_idx_mutex); mutex_unlock(&adev->grbm_idx_mutex);
return val; return val;
} else {
unsigned idx;
switch (reg_offset) {
case mmGB_ADDR_CONFIG:
return adev->gfx.config.gb_addr_config;
case mmMC_ARB_RAMCFG:
return adev->gfx.config.mc_arb_ramcfg;
case mmGB_TILE_MODE0:
case mmGB_TILE_MODE1:
case mmGB_TILE_MODE2:
case mmGB_TILE_MODE3:
case mmGB_TILE_MODE4:
case mmGB_TILE_MODE5:
case mmGB_TILE_MODE6:
case mmGB_TILE_MODE7:
case mmGB_TILE_MODE8:
case mmGB_TILE_MODE9:
case mmGB_TILE_MODE10:
case mmGB_TILE_MODE11:
case mmGB_TILE_MODE12:
case mmGB_TILE_MODE13:
case mmGB_TILE_MODE14:
case mmGB_TILE_MODE15:
case mmGB_TILE_MODE16:
case mmGB_TILE_MODE17:
case mmGB_TILE_MODE18:
case mmGB_TILE_MODE19:
case mmGB_TILE_MODE20:
case mmGB_TILE_MODE21:
case mmGB_TILE_MODE22:
case mmGB_TILE_MODE23:
case mmGB_TILE_MODE24:
case mmGB_TILE_MODE25:
case mmGB_TILE_MODE26:
case mmGB_TILE_MODE27:
case mmGB_TILE_MODE28:
case mmGB_TILE_MODE29:
case mmGB_TILE_MODE30:
case mmGB_TILE_MODE31:
idx = (reg_offset - mmGB_TILE_MODE0);
return adev->gfx.config.tile_mode_array[idx];
default:
return RREG32(reg_offset);
}
}
} }
static int si_read_register(struct amdgpu_device *adev, u32 se_num, static int si_read_register(struct amdgpu_device *adev, u32 se_num,
u32 sh_num, u32 reg_offset, u32 *value) u32 sh_num, u32 reg_offset, u32 *value)
{ {
...@@ -1039,10 +1096,9 @@ static int si_read_register(struct amdgpu_device *adev, u32 se_num, ...@@ -1039,10 +1096,9 @@ static int si_read_register(struct amdgpu_device *adev, u32 se_num,
continue; continue;
if (!si_allowed_read_registers[i].untouched) if (!si_allowed_read_registers[i].untouched)
*value = si_allowed_read_registers[i].grbm_indexed ? *value = si_get_register_value(adev,
si_read_indexed_register(adev, se_num, si_allowed_read_registers[i].grbm_indexed,
sh_num, reg_offset) : se_num, sh_num, reg_offset);
RREG32(reg_offset);
return 0; return 0;
} }
return -EINVAL; return -EINVAL;
......
...@@ -143,8 +143,8 @@ ...@@ -143,8 +143,8 @@
#define RLC_CLEAR_STATE_DESCRIPTOR_OFFSET 0x3D #define RLC_CLEAR_STATE_DESCRIPTOR_OFFSET 0x3D
#define TAHITI_GB_ADDR_CONFIG_GOLDEN 0x12011003 #define TAHITI_GB_ADDR_CONFIG_GOLDEN 0x12011003
#define VERDE_GB_ADDR_CONFIG_GOLDEN 0x12010002 #define VERDE_GB_ADDR_CONFIG_GOLDEN 0x02010002
#define HAINAN_GB_ADDR_CONFIG_GOLDEN 0x02010001 #define HAINAN_GB_ADDR_CONFIG_GOLDEN 0x02011003
#define PACKET3(op, n) ((RADEON_PACKET_TYPE3 << 30) | \ #define PACKET3(op, n) ((RADEON_PACKET_TYPE3 << 30) | \
(((op) & 0xFF) << 8) | \ (((op) & 0xFF) << 8) | \
......
...@@ -159,9 +159,6 @@ static int uvd_v4_2_hw_init(void *handle) ...@@ -159,9 +159,6 @@ static int uvd_v4_2_hw_init(void *handle)
uvd_v4_2_enable_mgcg(adev, true); uvd_v4_2_enable_mgcg(adev, true);
amdgpu_asic_set_uvd_clocks(adev, 10000, 10000); amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
r = uvd_v4_2_start(adev);
if (r)
goto done;
ring->ready = true; ring->ready = true;
r = amdgpu_ring_test_ring(ring); r = amdgpu_ring_test_ring(ring);
...@@ -198,7 +195,6 @@ static int uvd_v4_2_hw_init(void *handle) ...@@ -198,7 +195,6 @@ static int uvd_v4_2_hw_init(void *handle)
amdgpu_ring_commit(ring); amdgpu_ring_commit(ring);
done: done:
if (!r) if (!r)
DRM_INFO("UVD initialized successfully.\n"); DRM_INFO("UVD initialized successfully.\n");
...@@ -217,7 +213,9 @@ static int uvd_v4_2_hw_fini(void *handle) ...@@ -217,7 +213,9 @@ static int uvd_v4_2_hw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct amdgpu_ring *ring = &adev->uvd.ring; struct amdgpu_ring *ring = &adev->uvd.ring;
uvd_v4_2_stop(adev); if (RREG32(mmUVD_STATUS) != 0)
uvd_v4_2_stop(adev);
ring->ready = false; ring->ready = false;
return 0; return 0;
...@@ -267,37 +265,26 @@ static int uvd_v4_2_start(struct amdgpu_device *adev) ...@@ -267,37 +265,26 @@ static int uvd_v4_2_start(struct amdgpu_device *adev)
struct amdgpu_ring *ring = &adev->uvd.ring; struct amdgpu_ring *ring = &adev->uvd.ring;
uint32_t rb_bufsz; uint32_t rb_bufsz;
int i, j, r; int i, j, r;
u32 tmp;
/* disable byte swapping */ /* disable byte swapping */
u32 lmi_swap_cntl = 0; u32 lmi_swap_cntl = 0;
u32 mp_swap_cntl = 0; u32 mp_swap_cntl = 0;
WREG32(mmUVD_CGC_GATE, 0); /* set uvd busy */
uvd_v4_2_set_dcm(adev, true); WREG32_P(mmUVD_STATUS, 1<<2, ~(1<<2));
uvd_v4_2_mc_resume(adev); uvd_v4_2_set_dcm(adev, true);
WREG32(mmUVD_CGC_GATE, 0);
/* disable interupt */
WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
/* Stall UMC and register bus before resetting VCPU */
WREG32_P(mmUVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
mdelay(1);
/* put LMI, VCPU, RBC etc... into reset */
WREG32(mmUVD_SOFT_RESET, UVD_SOFT_RESET__LMI_SOFT_RESET_MASK |
UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK | UVD_SOFT_RESET__LBSI_SOFT_RESET_MASK |
UVD_SOFT_RESET__RBC_SOFT_RESET_MASK | UVD_SOFT_RESET__CSM_SOFT_RESET_MASK |
UVD_SOFT_RESET__CXW_SOFT_RESET_MASK | UVD_SOFT_RESET__TAP_SOFT_RESET_MASK |
UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK);
mdelay(5);
/* take UVD block out of reset */ /* take UVD block out of reset */
WREG32_P(mmSRBM_SOFT_RESET, 0, ~SRBM_SOFT_RESET__SOFT_RESET_UVD_MASK); WREG32_P(mmSRBM_SOFT_RESET, 0, ~SRBM_SOFT_RESET__SOFT_RESET_UVD_MASK);
mdelay(5); mdelay(5);
/* initialize UVD memory controller */ /* enable VCPU clock */
WREG32(mmUVD_LMI_CTRL, 0x40 | (1 << 8) | (1 << 13) | WREG32(mmUVD_VCPU_CNTL, 1 << 9);
(1 << 21) | (1 << 9) | (1 << 20));
/* disable interupt */
WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
/* swap (8 in 32) RB and IB */ /* swap (8 in 32) RB and IB */
...@@ -306,6 +293,11 @@ static int uvd_v4_2_start(struct amdgpu_device *adev) ...@@ -306,6 +293,11 @@ static int uvd_v4_2_start(struct amdgpu_device *adev)
#endif #endif
WREG32(mmUVD_LMI_SWAP_CNTL, lmi_swap_cntl); WREG32(mmUVD_LMI_SWAP_CNTL, lmi_swap_cntl);
WREG32(mmUVD_MP_SWAP_CNTL, mp_swap_cntl); WREG32(mmUVD_MP_SWAP_CNTL, mp_swap_cntl);
/* initialize UVD memory controller */
WREG32(mmUVD_LMI_CTRL, 0x203108);
tmp = RREG32(mmUVD_MPC_CNTL);
WREG32(mmUVD_MPC_CNTL, tmp | 0x10);
WREG32(mmUVD_MPC_SET_MUXA0, 0x40c2040); WREG32(mmUVD_MPC_SET_MUXA0, 0x40c2040);
WREG32(mmUVD_MPC_SET_MUXA1, 0x0); WREG32(mmUVD_MPC_SET_MUXA1, 0x0);
...@@ -314,18 +306,20 @@ static int uvd_v4_2_start(struct amdgpu_device *adev) ...@@ -314,18 +306,20 @@ static int uvd_v4_2_start(struct amdgpu_device *adev)
WREG32(mmUVD_MPC_SET_ALU, 0); WREG32(mmUVD_MPC_SET_ALU, 0);
WREG32(mmUVD_MPC_SET_MUX, 0x88); WREG32(mmUVD_MPC_SET_MUX, 0x88);
/* take all subblocks out of reset, except VCPU */ uvd_v4_2_mc_resume(adev);
WREG32(mmUVD_SOFT_RESET, UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);
mdelay(5);
/* enable VCPU clock */ tmp = RREG32_UVD_CTX(ixUVD_LMI_CACHE_CTRL);
WREG32(mmUVD_VCPU_CNTL, 1 << 9); WREG32_UVD_CTX(ixUVD_LMI_CACHE_CTRL, tmp & (~0x10));
/* enable UMC */ /* enable UMC */
WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8)); WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8));
/* boot up the VCPU */ WREG32_P(mmUVD_SOFT_RESET, 0, ~UVD_SOFT_RESET__LMI_SOFT_RESET_MASK);
WREG32(mmUVD_SOFT_RESET, 0);
WREG32_P(mmUVD_SOFT_RESET, 0, ~UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK);
WREG32_P(mmUVD_SOFT_RESET, 0, ~UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);
mdelay(10); mdelay(10);
for (i = 0; i < 10; ++i) { for (i = 0; i < 10; ++i) {
...@@ -357,6 +351,8 @@ static int uvd_v4_2_start(struct amdgpu_device *adev) ...@@ -357,6 +351,8 @@ static int uvd_v4_2_start(struct amdgpu_device *adev)
/* enable interupt */ /* enable interupt */
WREG32_P(mmUVD_MASTINT_EN, 3<<1, ~(3 << 1)); WREG32_P(mmUVD_MASTINT_EN, 3<<1, ~(3 << 1));
WREG32_P(mmUVD_STATUS, 0, ~(1<<2));
/* force RBC into idle state */ /* force RBC into idle state */
WREG32(mmUVD_RBC_RB_CNTL, 0x11010101); WREG32(mmUVD_RBC_RB_CNTL, 0x11010101);
...@@ -393,22 +389,54 @@ static int uvd_v4_2_start(struct amdgpu_device *adev) ...@@ -393,22 +389,54 @@ static int uvd_v4_2_start(struct amdgpu_device *adev)
*/ */
static void uvd_v4_2_stop(struct amdgpu_device *adev) static void uvd_v4_2_stop(struct amdgpu_device *adev)
{ {
/* force RBC into idle state */ uint32_t i, j;
uint32_t status;
WREG32(mmUVD_RBC_RB_CNTL, 0x11010101); WREG32(mmUVD_RBC_RB_CNTL, 0x11010101);
for (i = 0; i < 10; ++i) {
for (j = 0; j < 100; ++j) {
status = RREG32(mmUVD_STATUS);
if (status & 2)
break;
mdelay(1);
}
break;
}
for (i = 0; i < 10; ++i) {
for (j = 0; j < 100; ++j) {
status = RREG32(mmUVD_LMI_STATUS);
if (status & 0xf)
break;
mdelay(1);
}
break;
}
/* Stall UMC and register bus before resetting VCPU */ /* Stall UMC and register bus before resetting VCPU */
WREG32_P(mmUVD_LMI_CTRL2, 1 << 8, ~(1 << 8)); WREG32_P(mmUVD_LMI_CTRL2, 1 << 8, ~(1 << 8));
mdelay(1);
/* put VCPU into reset */ for (i = 0; i < 10; ++i) {
WREG32(mmUVD_SOFT_RESET, UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK); for (j = 0; j < 100; ++j) {
mdelay(5); status = RREG32(mmUVD_LMI_STATUS);
if (status & 0x240)
break;
mdelay(1);
}
break;
}
/* disable VCPU clock */ WREG32_P(0x3D49, 0, ~(1 << 2));
WREG32(mmUVD_VCPU_CNTL, 0x0);
/* Unstall UMC and register bus */ WREG32_P(mmUVD_VCPU_CNTL, 0, ~(1 << 9));
WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8));
/* put LMI, VCPU, RBC etc... into reset */
WREG32(mmUVD_SOFT_RESET, UVD_SOFT_RESET__LMI_SOFT_RESET_MASK |
UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK |
UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK);
WREG32(mmUVD_STATUS, 0);
uvd_v4_2_set_dcm(adev, false); uvd_v4_2_set_dcm(adev, false);
} }
...@@ -694,8 +722,24 @@ static int uvd_v4_2_set_powergating_state(void *handle, ...@@ -694,8 +722,24 @@ static int uvd_v4_2_set_powergating_state(void *handle,
if (state == AMD_PG_STATE_GATE) { if (state == AMD_PG_STATE_GATE) {
uvd_v4_2_stop(adev); uvd_v4_2_stop(adev);
if (adev->pg_flags & AMD_PG_SUPPORT_UVD && amdgpu_dpm == 0) {
if (!(RREG32_SMC(ixCURRENT_PG_STATUS) & 0x4)) {
WREG32(mmUVD_PGFSM_CONFIG, (UVD_PGFSM_CONFIG__UVD_PGFSM_FSM_ADDR_MASK |
UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_DOWN_MASK |
UVD_PGFSM_CONFIG__UVD_PGFSM_P1_SELECT_MASK));
mdelay(20);
}
}
return 0; return 0;
} else { } else {
if (adev->pg_flags & AMD_PG_SUPPORT_UVD && amdgpu_dpm == 0) {
if (RREG32_SMC(ixCURRENT_PG_STATUS) & 0x4) {
WREG32(mmUVD_PGFSM_CONFIG, (UVD_PGFSM_CONFIG__UVD_PGFSM_FSM_ADDR_MASK |
UVD_PGFSM_CONFIG__UVD_PGFSM_POWER_UP_MASK |
UVD_PGFSM_CONFIG__UVD_PGFSM_P1_SELECT_MASK));
mdelay(30);
}
}
return uvd_v4_2_start(adev); return uvd_v4_2_start(adev);
} }
} }
......
...@@ -152,9 +152,9 @@ static int uvd_v5_0_hw_init(void *handle) ...@@ -152,9 +152,9 @@ static int uvd_v5_0_hw_init(void *handle)
uint32_t tmp; uint32_t tmp;
int r; int r;
r = uvd_v5_0_start(adev); amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
if (r) uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
goto done; uvd_v5_0_enable_mgcg(adev, true);
ring->ready = true; ring->ready = true;
r = amdgpu_ring_test_ring(ring); r = amdgpu_ring_test_ring(ring);
...@@ -189,11 +189,13 @@ static int uvd_v5_0_hw_init(void *handle) ...@@ -189,11 +189,13 @@ static int uvd_v5_0_hw_init(void *handle)
amdgpu_ring_write(ring, 3); amdgpu_ring_write(ring, 3);
amdgpu_ring_commit(ring); amdgpu_ring_commit(ring);
done: done:
if (!r) if (!r)
DRM_INFO("UVD initialized successfully.\n"); DRM_INFO("UVD initialized successfully.\n");
return r; return r;
} }
/** /**
...@@ -208,7 +210,9 @@ static int uvd_v5_0_hw_fini(void *handle) ...@@ -208,7 +210,9 @@ static int uvd_v5_0_hw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct amdgpu_ring *ring = &adev->uvd.ring; struct amdgpu_ring *ring = &adev->uvd.ring;
uvd_v5_0_stop(adev); if (RREG32(mmUVD_STATUS) != 0)
uvd_v5_0_stop(adev);
ring->ready = false; ring->ready = false;
return 0; return 0;
...@@ -310,10 +314,6 @@ static int uvd_v5_0_start(struct amdgpu_device *adev) ...@@ -310,10 +314,6 @@ static int uvd_v5_0_start(struct amdgpu_device *adev)
uvd_v5_0_mc_resume(adev); uvd_v5_0_mc_resume(adev);
amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
uvd_v5_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
uvd_v5_0_enable_mgcg(adev, true);
/* disable interupt */ /* disable interupt */
WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1)); WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1));
...@@ -456,6 +456,8 @@ static void uvd_v5_0_stop(struct amdgpu_device *adev) ...@@ -456,6 +456,8 @@ static void uvd_v5_0_stop(struct amdgpu_device *adev)
/* Unstall UMC and register bus */ /* Unstall UMC and register bus */
WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8)); WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8));
WREG32(mmUVD_STATUS, 0);
} }
/** /**
...@@ -792,9 +794,6 @@ static int uvd_v5_0_set_clockgating_state(void *handle, ...@@ -792,9 +794,6 @@ static int uvd_v5_0_set_clockgating_state(void *handle,
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
bool enable = (state == AMD_CG_STATE_GATE) ? true : false; bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
return 0;
if (enable) { if (enable) {
/* wait for STATUS to clear */ /* wait for STATUS to clear */
if (uvd_v5_0_wait_for_idle(handle)) if (uvd_v5_0_wait_for_idle(handle))
...@@ -824,9 +823,6 @@ static int uvd_v5_0_set_powergating_state(void *handle, ...@@ -824,9 +823,6 @@ static int uvd_v5_0_set_powergating_state(void *handle,
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int ret = 0; int ret = 0;
if (!(adev->pg_flags & AMD_PG_SUPPORT_UVD))
return 0;
if (state == AMD_PG_STATE_GATE) { if (state == AMD_PG_STATE_GATE) {
uvd_v5_0_stop(adev); uvd_v5_0_stop(adev);
adev->uvd.is_powergated = true; adev->uvd.is_powergated = true;
......
...@@ -155,9 +155,9 @@ static int uvd_v6_0_hw_init(void *handle) ...@@ -155,9 +155,9 @@ static int uvd_v6_0_hw_init(void *handle)
uint32_t tmp; uint32_t tmp;
int r; int r;
r = uvd_v6_0_start(adev); amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
if (r) uvd_v6_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
goto done; uvd_v6_0_enable_mgcg(adev, true);
ring->ready = true; ring->ready = true;
r = amdgpu_ring_test_ring(ring); r = amdgpu_ring_test_ring(ring);
...@@ -212,7 +212,9 @@ static int uvd_v6_0_hw_fini(void *handle) ...@@ -212,7 +212,9 @@ static int uvd_v6_0_hw_fini(void *handle)
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
struct amdgpu_ring *ring = &adev->uvd.ring; struct amdgpu_ring *ring = &adev->uvd.ring;
uvd_v6_0_stop(adev); if (RREG32(mmUVD_STATUS) != 0)
uvd_v6_0_stop(adev);
ring->ready = false; ring->ready = false;
return 0; return 0;
...@@ -397,9 +399,6 @@ static int uvd_v6_0_start(struct amdgpu_device *adev) ...@@ -397,9 +399,6 @@ static int uvd_v6_0_start(struct amdgpu_device *adev)
lmi_swap_cntl = 0; lmi_swap_cntl = 0;
mp_swap_cntl = 0; mp_swap_cntl = 0;
amdgpu_asic_set_uvd_clocks(adev, 10000, 10000);
uvd_v6_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE);
uvd_v6_0_enable_mgcg(adev, true);
uvd_v6_0_mc_resume(adev); uvd_v6_0_mc_resume(adev);
/* disable interupt */ /* disable interupt */
...@@ -554,6 +553,8 @@ static void uvd_v6_0_stop(struct amdgpu_device *adev) ...@@ -554,6 +553,8 @@ static void uvd_v6_0_stop(struct amdgpu_device *adev)
/* Unstall UMC and register bus */ /* Unstall UMC and register bus */
WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8)); WREG32_P(mmUVD_LMI_CTRL2, 0, ~(1 << 8));
WREG32(mmUVD_STATUS, 0);
} }
/** /**
...@@ -1018,9 +1019,6 @@ static int uvd_v6_0_set_clockgating_state(void *handle, ...@@ -1018,9 +1019,6 @@ static int uvd_v6_0_set_clockgating_state(void *handle,
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
bool enable = (state == AMD_CG_STATE_GATE) ? true : false; bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
if (!(adev->cg_flags & AMD_CG_SUPPORT_UVD_MGCG))
return 0;
if (enable) { if (enable) {
/* wait for STATUS to clear */ /* wait for STATUS to clear */
if (uvd_v6_0_wait_for_idle(handle)) if (uvd_v6_0_wait_for_idle(handle))
...@@ -1049,9 +1047,6 @@ static int uvd_v6_0_set_powergating_state(void *handle, ...@@ -1049,9 +1047,6 @@ static int uvd_v6_0_set_powergating_state(void *handle,
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int ret = 0; int ret = 0;
if (!(adev->pg_flags & AMD_PG_SUPPORT_UVD))
return 0;
WREG32(mmUVD_POWER_STATUS, UVD_POWER_STATUS__UVD_PG_EN_MASK); WREG32(mmUVD_POWER_STATUS, UVD_POWER_STATUS__UVD_PG_EN_MASK);
if (state == AMD_PG_STATE_GATE) { if (state == AMD_PG_STATE_GATE) {
......
...@@ -42,10 +42,9 @@ ...@@ -42,10 +42,9 @@
#define VCE_V2_0_DATA_SIZE (23552 * AMDGPU_MAX_VCE_HANDLES) #define VCE_V2_0_DATA_SIZE (23552 * AMDGPU_MAX_VCE_HANDLES)
#define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK 0x02 #define VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK 0x02
static void vce_v2_0_mc_resume(struct amdgpu_device *adev);
static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev); static void vce_v2_0_set_ring_funcs(struct amdgpu_device *adev);
static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev); static void vce_v2_0_set_irq_funcs(struct amdgpu_device *adev);
static int vce_v2_0_wait_for_idle(void *handle);
/** /**
* vce_v2_0_ring_get_rptr - get read pointer * vce_v2_0_ring_get_rptr - get read pointer
* *
...@@ -140,6 +139,86 @@ static int vce_v2_0_firmware_loaded(struct amdgpu_device *adev) ...@@ -140,6 +139,86 @@ static int vce_v2_0_firmware_loaded(struct amdgpu_device *adev)
return -ETIMEDOUT; return -ETIMEDOUT;
} }
static void vce_v2_0_disable_cg(struct amdgpu_device *adev)
{
WREG32(mmVCE_CGTT_CLK_OVERRIDE, 7);
}
static void vce_v2_0_init_cg(struct amdgpu_device *adev)
{
u32 tmp;
tmp = RREG32(mmVCE_CLOCK_GATING_A);
tmp &= ~0xfff;
tmp |= ((0 << 0) | (4 << 4));
tmp |= 0x40000;
WREG32(mmVCE_CLOCK_GATING_A, tmp);
tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
tmp &= ~0xfff;
tmp |= ((0 << 0) | (4 << 4));
WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
tmp = RREG32(mmVCE_CLOCK_GATING_B);
tmp |= 0x10;
tmp &= ~0x100000;
WREG32(mmVCE_CLOCK_GATING_B, tmp);
}
static void vce_v2_0_mc_resume(struct amdgpu_device *adev)
{
uint64_t addr = adev->vce.gpu_addr;
uint32_t size;
WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
WREG32(mmVCE_LMI_CTRL, 0x00398000);
WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
WREG32(mmVCE_LMI_SWAP_CNTL, 0);
WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
WREG32(mmVCE_LMI_VM_CTRL, 0);
addr += AMDGPU_VCE_FIRMWARE_OFFSET;
size = VCE_V2_0_FW_SIZE;
WREG32(mmVCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff);
WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
addr += size;
size = VCE_V2_0_STACK_SIZE;
WREG32(mmVCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff);
WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
addr += size;
size = VCE_V2_0_DATA_SIZE;
WREG32(mmVCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff);
WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1);
}
static bool vce_v2_0_is_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK);
}
static int vce_v2_0_wait_for_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
unsigned i;
for (i = 0; i < adev->usec_timeout; i++) {
if (vce_v2_0_is_idle(handle))
return 0;
}
return -ETIMEDOUT;
}
/** /**
* vce_v2_0_start - start VCE block * vce_v2_0_start - start VCE block
* *
...@@ -152,11 +231,14 @@ static int vce_v2_0_start(struct amdgpu_device *adev) ...@@ -152,11 +231,14 @@ static int vce_v2_0_start(struct amdgpu_device *adev)
struct amdgpu_ring *ring; struct amdgpu_ring *ring;
int r; int r;
vce_v2_0_mc_resume(adev);
/* set BUSY flag */ /* set BUSY flag */
WREG32_P(mmVCE_STATUS, 1, ~1); WREG32_P(mmVCE_STATUS, 1, ~1);
vce_v2_0_init_cg(adev);
vce_v2_0_disable_cg(adev);
vce_v2_0_mc_resume(adev);
ring = &adev->vce.ring[0]; ring = &adev->vce.ring[0];
WREG32(mmVCE_RB_RPTR, ring->wptr); WREG32(mmVCE_RB_RPTR, ring->wptr);
WREG32(mmVCE_RB_WPTR, ring->wptr); WREG32(mmVCE_RB_WPTR, ring->wptr);
...@@ -189,6 +271,145 @@ static int vce_v2_0_start(struct amdgpu_device *adev) ...@@ -189,6 +271,145 @@ static int vce_v2_0_start(struct amdgpu_device *adev)
return 0; return 0;
} }
static int vce_v2_0_stop(struct amdgpu_device *adev)
{
int i, j;
int status;
if (vce_v2_0_lmi_clean(adev)) {
DRM_INFO("vce is not idle \n");
return 0;
}
/*
for (i = 0; i < 10; ++i) {
for (j = 0; j < 100; ++j) {
status = RREG32(mmVCE_FW_REG_STATUS);
if (!(status & 1))
break;
mdelay(1);
}
break;
}
*/
if (vce_v2_0_wait_for_idle(adev)) {
DRM_INFO("VCE is busy, Can't set clock gateing");
return 0;
}
/* Stall UMC and register bus before resetting VCPU */
WREG32_P(mmVCE_LMI_CTRL2, 1 << 8, ~(1 << 8));
for (i = 0; i < 10; ++i) {
for (j = 0; j < 100; ++j) {
status = RREG32(mmVCE_LMI_STATUS);
if (status & 0x240)
break;
mdelay(1);
}
break;
}
WREG32_P(mmVCE_VCPU_CNTL, 0, ~0x80001);
/* put LMI, VCPU, RBC etc... into reset */
WREG32_P(mmVCE_SOFT_RESET, 1, ~0x1);
WREG32(mmVCE_STATUS, 0);
return 0;
}
static void vce_v2_0_set_sw_cg(struct amdgpu_device *adev, bool gated)
{
u32 tmp;
if (gated) {
tmp = RREG32(mmVCE_CLOCK_GATING_B);
tmp |= 0xe70000;
WREG32(mmVCE_CLOCK_GATING_B, tmp);
tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
tmp |= 0xff000000;
WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
tmp &= ~0x3fc;
WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
} else {
tmp = RREG32(mmVCE_CLOCK_GATING_B);
tmp |= 0xe7;
tmp &= ~0xe70000;
WREG32(mmVCE_CLOCK_GATING_B, tmp);
tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
tmp |= 0x1fe000;
tmp &= ~0xff000000;
WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
tmp |= 0x3fc;
WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
}
}
static void vce_v2_0_set_dyn_cg(struct amdgpu_device *adev, bool gated)
{
u32 orig, tmp;
/* LMI_MC/LMI_UMC always set in dynamic,
* set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {0, 0}
*/
tmp = RREG32(mmVCE_CLOCK_GATING_B);
tmp &= ~0x00060006;
/* Exception for ECPU, IH, SEM, SYS blocks needs to be turned on/off by SW */
if (gated) {
tmp |= 0xe10000;
WREG32(mmVCE_CLOCK_GATING_B, tmp);
} else {
tmp |= 0xe1;
tmp &= ~0xe10000;
WREG32(mmVCE_CLOCK_GATING_B, tmp);
}
orig = tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
tmp &= ~0x1fe000;
tmp &= ~0xff000000;
if (tmp != orig)
WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
orig = tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
tmp &= ~0x3fc;
if (tmp != orig)
WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
/* set VCE_UENC_REG_CLOCK_GATING always in dynamic mode */
WREG32(mmVCE_UENC_REG_CLOCK_GATING, 0x00);
if(gated)
WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
}
static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable,
bool sw_cg)
{
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) {
if (sw_cg)
vce_v2_0_set_sw_cg(adev, true);
else
vce_v2_0_set_dyn_cg(adev, true);
} else {
vce_v2_0_disable_cg(adev);
if (sw_cg)
vce_v2_0_set_sw_cg(adev, false);
else
vce_v2_0_set_dyn_cg(adev, false);
}
}
static int vce_v2_0_early_init(void *handle) static int vce_v2_0_early_init(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
...@@ -254,11 +475,8 @@ static int vce_v2_0_hw_init(void *handle) ...@@ -254,11 +475,8 @@ static int vce_v2_0_hw_init(void *handle)
int r, i; int r, i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
r = vce_v2_0_start(adev); amdgpu_asic_set_vce_clocks(adev, 10000, 10000);
/* this error mean vcpu not in running state, so just skip ring test, not stop driver initialize */ vce_v2_0_enable_mgcg(adev, true, false);
if (r)
return 0;
for (i = 0; i < adev->vce.num_rings; i++) for (i = 0; i < adev->vce.num_rings; i++)
adev->vce.ring[i].ready = false; adev->vce.ring[i].ready = false;
...@@ -312,190 +530,6 @@ static int vce_v2_0_resume(void *handle) ...@@ -312,190 +530,6 @@ static int vce_v2_0_resume(void *handle)
return r; return r;
} }
static void vce_v2_0_set_sw_cg(struct amdgpu_device *adev, bool gated)
{
u32 tmp;
if (gated) {
tmp = RREG32(mmVCE_CLOCK_GATING_B);
tmp |= 0xe70000;
WREG32(mmVCE_CLOCK_GATING_B, tmp);
tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
tmp |= 0xff000000;
WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
tmp &= ~0x3fc;
WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
} else {
tmp = RREG32(mmVCE_CLOCK_GATING_B);
tmp |= 0xe7;
tmp &= ~0xe70000;
WREG32(mmVCE_CLOCK_GATING_B, tmp);
tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
tmp |= 0x1fe000;
tmp &= ~0xff000000;
WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
tmp = RREG32(mmVCE_UENC_REG_CLOCK_GATING);
tmp |= 0x3fc;
WREG32(mmVCE_UENC_REG_CLOCK_GATING, tmp);
}
}
static void vce_v2_0_set_dyn_cg(struct amdgpu_device *adev, bool gated)
{
if (vce_v2_0_wait_for_idle(adev)) {
DRM_INFO("VCE is busy, Can't set clock gateing");
return;
}
WREG32_P(mmVCE_LMI_CTRL2, 0x100, ~0x100);
if (vce_v2_0_lmi_clean(adev)) {
DRM_INFO("LMI is busy, Can't set clock gateing");
return;
}
WREG32_P(mmVCE_VCPU_CNTL, 0, ~VCE_VCPU_CNTL__CLK_EN_MASK);
WREG32_P(mmVCE_SOFT_RESET,
VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK,
~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
WREG32(mmVCE_STATUS, 0);
if (gated)
WREG32(mmVCE_CGTT_CLK_OVERRIDE, 0);
/* LMI_MC/LMI_UMC always set in dynamic, set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {0, 0} */
if (gated) {
/* Force CLOCK OFF , set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {*, 1} */
WREG32(mmVCE_CLOCK_GATING_B, 0xe90010);
} else {
/* Force CLOCK ON, set {CGC_*_GATE_MODE, CGC_*_SW_GATE} = {1, 0} */
WREG32(mmVCE_CLOCK_GATING_B, 0x800f1);
}
/* Set VCE_UENC_CLOCK_GATING always in dynamic mode {*_FORCE_ON, *_FORCE_OFF} = {0, 0}*/;
WREG32(mmVCE_UENC_CLOCK_GATING, 0x40);
/* set VCE_UENC_REG_CLOCK_GATING always in dynamic mode */
WREG32(mmVCE_UENC_REG_CLOCK_GATING, 0x00);
WREG32_P(mmVCE_LMI_CTRL2, 0, ~0x100);
if(!gated) {
WREG32_P(mmVCE_VCPU_CNTL, VCE_VCPU_CNTL__CLK_EN_MASK, ~VCE_VCPU_CNTL__CLK_EN_MASK);
mdelay(100);
WREG32_P(mmVCE_SOFT_RESET, 0, ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK);
vce_v2_0_firmware_loaded(adev);
WREG32_P(mmVCE_STATUS, 0, ~VCE_STATUS__JOB_BUSY_MASK);
}
}
static void vce_v2_0_disable_cg(struct amdgpu_device *adev)
{
WREG32(mmVCE_CGTT_CLK_OVERRIDE, 7);
}
static void vce_v2_0_enable_mgcg(struct amdgpu_device *adev, bool enable)
{
bool sw_cg = false;
if (enable && (adev->cg_flags & AMD_CG_SUPPORT_VCE_MGCG)) {
if (sw_cg)
vce_v2_0_set_sw_cg(adev, true);
else
vce_v2_0_set_dyn_cg(adev, true);
} else {
vce_v2_0_disable_cg(adev);
if (sw_cg)
vce_v2_0_set_sw_cg(adev, false);
else
vce_v2_0_set_dyn_cg(adev, false);
}
}
static void vce_v2_0_init_cg(struct amdgpu_device *adev)
{
u32 tmp;
tmp = RREG32(mmVCE_CLOCK_GATING_A);
tmp &= ~0xfff;
tmp |= ((0 << 0) | (4 << 4));
tmp |= 0x40000;
WREG32(mmVCE_CLOCK_GATING_A, tmp);
tmp = RREG32(mmVCE_UENC_CLOCK_GATING);
tmp &= ~0xfff;
tmp |= ((0 << 0) | (4 << 4));
WREG32(mmVCE_UENC_CLOCK_GATING, tmp);
tmp = RREG32(mmVCE_CLOCK_GATING_B);
tmp |= 0x10;
tmp &= ~0x100000;
WREG32(mmVCE_CLOCK_GATING_B, tmp);
}
static void vce_v2_0_mc_resume(struct amdgpu_device *adev)
{
uint64_t addr = adev->vce.gpu_addr;
uint32_t size;
WREG32_P(mmVCE_CLOCK_GATING_A, 0, ~(1 << 16));
WREG32_P(mmVCE_UENC_CLOCK_GATING, 0x1FF000, ~0xFF9FF000);
WREG32_P(mmVCE_UENC_REG_CLOCK_GATING, 0x3F, ~0x3F);
WREG32(mmVCE_CLOCK_GATING_B, 0xf7);
WREG32(mmVCE_LMI_CTRL, 0x00398000);
WREG32_P(mmVCE_LMI_CACHE_CTRL, 0x0, ~0x1);
WREG32(mmVCE_LMI_SWAP_CNTL, 0);
WREG32(mmVCE_LMI_SWAP_CNTL1, 0);
WREG32(mmVCE_LMI_VM_CTRL, 0);
addr += AMDGPU_VCE_FIRMWARE_OFFSET;
size = VCE_V2_0_FW_SIZE;
WREG32(mmVCE_VCPU_CACHE_OFFSET0, addr & 0x7fffffff);
WREG32(mmVCE_VCPU_CACHE_SIZE0, size);
addr += size;
size = VCE_V2_0_STACK_SIZE;
WREG32(mmVCE_VCPU_CACHE_OFFSET1, addr & 0x7fffffff);
WREG32(mmVCE_VCPU_CACHE_SIZE1, size);
addr += size;
size = VCE_V2_0_DATA_SIZE;
WREG32(mmVCE_VCPU_CACHE_OFFSET2, addr & 0x7fffffff);
WREG32(mmVCE_VCPU_CACHE_SIZE2, size);
WREG32_P(mmVCE_LMI_CTRL2, 0x0, ~0x100);
WREG32_FIELD(VCE_SYS_INT_EN, VCE_SYS_INT_TRAP_INTERRUPT_EN, 1);
vce_v2_0_init_cg(adev);
}
static bool vce_v2_0_is_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
return !(RREG32(mmSRBM_STATUS2) & SRBM_STATUS2__VCE_BUSY_MASK);
}
static int vce_v2_0_wait_for_idle(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
unsigned i;
for (i = 0; i < adev->usec_timeout; i++) {
if (vce_v2_0_is_idle(handle))
return 0;
}
return -ETIMEDOUT;
}
static int vce_v2_0_soft_reset(void *handle) static int vce_v2_0_soft_reset(void *handle)
{ {
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
...@@ -539,33 +573,20 @@ static int vce_v2_0_process_interrupt(struct amdgpu_device *adev, ...@@ -539,33 +573,20 @@ static int vce_v2_0_process_interrupt(struct amdgpu_device *adev,
return 0; return 0;
} }
static void vce_v2_0_set_bypass_mode(struct amdgpu_device *adev, bool enable)
{
u32 tmp = RREG32_SMC(ixGCK_DFS_BYPASS_CNTL);
if (enable)
tmp |= GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK;
else
tmp &= ~GCK_DFS_BYPASS_CNTL__BYPASSECLK_MASK;
WREG32_SMC(ixGCK_DFS_BYPASS_CNTL, tmp);
}
static int vce_v2_0_set_clockgating_state(void *handle, static int vce_v2_0_set_clockgating_state(void *handle,
enum amd_clockgating_state state) enum amd_clockgating_state state)
{ {
bool gate = false; bool gate = false;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; bool sw_cg = false;
bool enable = (state == AMD_CG_STATE_GATE) ? true : false;
vce_v2_0_set_bypass_mode(adev, enable); struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (state == AMD_CG_STATE_GATE) if (state == AMD_CG_STATE_GATE) {
gate = true; gate = true;
sw_cg = true;
}
vce_v2_0_enable_mgcg(adev, gate); vce_v2_0_enable_mgcg(adev, gate, sw_cg);
return 0; return 0;
} }
...@@ -582,12 +603,8 @@ static int vce_v2_0_set_powergating_state(void *handle, ...@@ -582,12 +603,8 @@ static int vce_v2_0_set_powergating_state(void *handle,
*/ */
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE))
return 0;
if (state == AMD_PG_STATE_GATE) if (state == AMD_PG_STATE_GATE)
/* XXX do we need a vce_v2_0_stop()? */ return vce_v2_0_stop(adev);
return 0;
else else
return vce_v2_0_start(adev); return vce_v2_0_start(adev);
} }
......
...@@ -230,10 +230,6 @@ static int vce_v3_0_start(struct amdgpu_device *adev) ...@@ -230,10 +230,6 @@ static int vce_v3_0_start(struct amdgpu_device *adev)
struct amdgpu_ring *ring; struct amdgpu_ring *ring;
int idx, r; int idx, r;
vce_v3_0_override_vce_clock_gating(adev, true);
if (!(adev->flags & AMD_IS_APU))
amdgpu_asic_set_vce_clocks(adev, 10000, 10000);
ring = &adev->vce.ring[0]; ring = &adev->vce.ring[0];
WREG32(mmVCE_RB_RPTR, ring->wptr); WREG32(mmVCE_RB_RPTR, ring->wptr);
WREG32(mmVCE_RB_WPTR, ring->wptr); WREG32(mmVCE_RB_WPTR, ring->wptr);
...@@ -436,9 +432,9 @@ static int vce_v3_0_hw_init(void *handle) ...@@ -436,9 +432,9 @@ static int vce_v3_0_hw_init(void *handle)
int r, i; int r, i;
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
r = vce_v3_0_start(adev); vce_v3_0_override_vce_clock_gating(adev, true);
if (r) if (!(adev->flags & AMD_IS_APU))
return r; amdgpu_asic_set_vce_clocks(adev, 10000, 10000);
for (i = 0; i < adev->vce.num_rings; i++) for (i = 0; i < adev->vce.num_rings; i++)
adev->vce.ring[i].ready = false; adev->vce.ring[i].ready = false;
...@@ -766,12 +762,11 @@ static int vce_v3_0_set_powergating_state(void *handle, ...@@ -766,12 +762,11 @@ static int vce_v3_0_set_powergating_state(void *handle,
struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_device *adev = (struct amdgpu_device *)handle;
int ret = 0; int ret = 0;
if (!(adev->pg_flags & AMD_PG_SUPPORT_VCE))
return 0;
if (state == AMD_PG_STATE_GATE) { if (state == AMD_PG_STATE_GATE) {
ret = vce_v3_0_stop(adev);
if (ret)
goto out;
adev->vce.is_powergated = true; adev->vce.is_powergated = true;
/* XXX do we need a vce_v3_0_stop()? */
} else { } else {
ret = vce_v3_0_start(adev); ret = vce_v3_0_start(adev);
if (ret) if (ret)
......
...@@ -1310,5 +1310,6 @@ ...@@ -1310,5 +1310,6 @@
#define ixROM_SW_DATA_62 0xc060012c #define ixROM_SW_DATA_62 0xc060012c
#define ixROM_SW_DATA_63 0xc0600130 #define ixROM_SW_DATA_63 0xc0600130
#define ixROM_SW_DATA_64 0xc0600134 #define ixROM_SW_DATA_64 0xc0600134
#define ixCURRENT_PG_STATUS 0xc020029c
#endif /* SMU_7_0_1_D_H */ #endif /* SMU_7_0_1_D_H */
...@@ -161,28 +161,25 @@ int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) ...@@ -161,28 +161,25 @@ int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
{ {
struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
if (cz_hwmgr->uvd_power_gated == bgate)
return 0;
cz_hwmgr->uvd_power_gated = bgate; cz_hwmgr->uvd_power_gated = bgate;
if (bgate) { if (bgate) {
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
cgs_set_powergating_state(hwmgr->device, cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE); AMD_PG_STATE_GATE);
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
cz_dpm_update_uvd_dpm(hwmgr, true); cz_dpm_update_uvd_dpm(hwmgr, true);
cz_dpm_powerdown_uvd(hwmgr); cz_dpm_powerdown_uvd(hwmgr);
} else { } else {
cz_dpm_powerup_uvd(hwmgr); cz_dpm_powerup_uvd(hwmgr);
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
cgs_set_clockgating_state(hwmgr->device, cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_UNGATE); AMD_PG_STATE_UNGATE);
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
cz_dpm_update_uvd_dpm(hwmgr, false); cz_dpm_update_uvd_dpm(hwmgr, false);
} }
...@@ -193,47 +190,34 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) ...@@ -193,47 +190,34 @@ int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
{ {
struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend);
if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, if (bgate) {
PHM_PlatformCaps_VCEPowerGating)) { cgs_set_powergating_state(
if (cz_hwmgr->vce_power_gated != bgate) { hwmgr->device,
if (bgate) { AMD_IP_BLOCK_TYPE_VCE,
cgs_set_clockgating_state( AMD_PG_STATE_GATE);
hwmgr->device, cgs_set_clockgating_state(
AMD_IP_BLOCK_TYPE_VCE, hwmgr->device,
AMD_CG_STATE_GATE); AMD_IP_BLOCK_TYPE_VCE,
cgs_set_powergating_state( AMD_CG_STATE_GATE);
hwmgr->device, cz_enable_disable_vce_dpm(hwmgr, false);
AMD_IP_BLOCK_TYPE_VCE, cz_dpm_powerdown_vce(hwmgr);
AMD_PG_STATE_GATE); cz_hwmgr->vce_power_gated = true;
cz_enable_disable_vce_dpm(hwmgr, false);
cz_dpm_powerdown_vce(hwmgr);
cz_hwmgr->vce_power_gated = true;
} else {
cz_dpm_powerup_vce(hwmgr);
cz_hwmgr->vce_power_gated = false;
cgs_set_powergating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE);
cgs_set_clockgating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
cz_dpm_update_vce_dpm(hwmgr);
cz_enable_disable_vce_dpm(hwmgr, true);
return 0;
}
}
} else { } else {
cz_hwmgr->vce_power_gated = bgate; cz_dpm_powerup_vce(hwmgr);
cz_hwmgr->vce_power_gated = false;
cgs_set_clockgating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
cgs_set_powergating_state(
hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE);
cz_dpm_update_vce_dpm(hwmgr); cz_dpm_update_vce_dpm(hwmgr);
cz_enable_disable_vce_dpm(hwmgr, !bgate); cz_enable_disable_vce_dpm(hwmgr, true);
return 0; return 0;
} }
if (!cz_hwmgr->vce_power_gated)
cz_dpm_update_vce_dpm(hwmgr);
return 0; return 0;
} }
......
...@@ -147,22 +147,22 @@ int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) ...@@ -147,22 +147,22 @@ int smu7_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate)
data->uvd_power_gated = bgate; data->uvd_power_gated = bgate;
if (bgate) { if (bgate) {
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
cgs_set_powergating_state(hwmgr->device, cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD, AMD_IP_BLOCK_TYPE_UVD,
AMD_PG_STATE_GATE); AMD_PG_STATE_GATE);
cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_GATE);
smu7_update_uvd_dpm(hwmgr, true); smu7_update_uvd_dpm(hwmgr, true);
smu7_powerdown_uvd(hwmgr); smu7_powerdown_uvd(hwmgr);
} else { } else {
smu7_powerup_uvd(hwmgr); smu7_powerup_uvd(hwmgr);
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
cgs_set_clockgating_state(hwmgr->device, cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD, AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE); AMD_CG_STATE_UNGATE);
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_UVD,
AMD_CG_STATE_UNGATE);
smu7_update_uvd_dpm(hwmgr, false); smu7_update_uvd_dpm(hwmgr, false);
} }
...@@ -173,12 +173,12 @@ int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) ...@@ -173,12 +173,12 @@ int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
{ {
struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
if (data->vce_power_gated == bgate)
return 0;
data->vce_power_gated = bgate; data->vce_power_gated = bgate;
if (bgate) { if (bgate) {
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
cgs_set_clockgating_state(hwmgr->device, cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_GATE); AMD_CG_STATE_GATE);
...@@ -186,10 +186,13 @@ int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) ...@@ -186,10 +186,13 @@ int smu7_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate)
smu7_powerdown_vce(hwmgr); smu7_powerdown_vce(hwmgr);
} else { } else {
smu7_powerup_vce(hwmgr); smu7_powerup_vce(hwmgr);
smu7_update_vce_dpm(hwmgr, false);
cgs_set_clockgating_state(hwmgr->device, cgs_set_clockgating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE, AMD_IP_BLOCK_TYPE_VCE,
AMD_CG_STATE_UNGATE); AMD_CG_STATE_UNGATE);
cgs_set_powergating_state(hwmgr->device,
AMD_IP_BLOCK_TYPE_VCE,
AMD_PG_STATE_UNGATE);
smu7_update_vce_dpm(hwmgr, false);
} }
return 0; return 0;
} }
......
...@@ -2624,6 +2624,7 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, ...@@ -2624,6 +2624,7 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr,
smu7_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask); smu7_force_clock_level(hwmgr, PP_SCLK, 1<<sclk_mask);
smu7_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask); smu7_force_clock_level(hwmgr, PP_MCLK, 1<<mclk_mask);
smu7_force_clock_level(hwmgr, PP_PCIE, 1<<pcie_mask); smu7_force_clock_level(hwmgr, PP_PCIE, 1<<pcie_mask);
break; break;
case AMD_DPM_FORCED_LEVEL_MANUAL: case AMD_DPM_FORCED_LEVEL_MANUAL:
hwmgr->dpm_level = level; hwmgr->dpm_level = level;
...@@ -2633,9 +2634,9 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr, ...@@ -2633,9 +2634,9 @@ static int smu7_force_dpm_level(struct pp_hwmgr *hwmgr,
break; break;
} }
if (level & (AMD_DPM_FORCED_LEVEL_PROFILE_PEAK | AMD_DPM_FORCED_LEVEL_HIGH)) if (level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100); smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
else else if (level != AMD_DPM_FORCED_LEVEL_PROFILE_PEAK && hwmgr->saved_dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)
smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr); smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr);
return 0; return 0;
...@@ -4397,16 +4398,14 @@ static int smu7_get_sclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) ...@@ -4397,16 +4398,14 @@ static int smu7_get_sclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks)
if (table_info == NULL || table_info->vdd_dep_on_sclk == NULL) if (table_info == NULL || table_info->vdd_dep_on_sclk == NULL)
return -EINVAL; return -EINVAL;
dep_sclk_table = table_info->vdd_dep_on_sclk; dep_sclk_table = table_info->vdd_dep_on_sclk;
for (i = 0; i < dep_sclk_table->count; i++) { for (i = 0; i < dep_sclk_table->count; i++)
clocks->clock[i] = dep_sclk_table->entries[i].clk; clocks->clock[i] = dep_sclk_table->entries[i].clk;
clocks->count++; clocks->count = dep_sclk_table->count;
}
} else if (hwmgr->pp_table_version == PP_TABLE_V0) { } else if (hwmgr->pp_table_version == PP_TABLE_V0) {
sclk_table = hwmgr->dyn_state.vddc_dependency_on_sclk; sclk_table = hwmgr->dyn_state.vddc_dependency_on_sclk;
for (i = 0; i < sclk_table->count; i++) { for (i = 0; i < sclk_table->count; i++)
clocks->clock[i] = sclk_table->entries[i].clk; clocks->clock[i] = sclk_table->entries[i].clk;
clocks->count++; clocks->count = sclk_table->count;
}
} }
return 0; return 0;
...@@ -4440,14 +4439,13 @@ static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks) ...@@ -4440,14 +4439,13 @@ static int smu7_get_mclks(struct pp_hwmgr *hwmgr, struct amd_pp_clocks *clocks)
clocks->clock[i] = dep_mclk_table->entries[i].clk; clocks->clock[i] = dep_mclk_table->entries[i].clk;
clocks->latency[i] = smu7_get_mem_latency(hwmgr, clocks->latency[i] = smu7_get_mem_latency(hwmgr,
dep_mclk_table->entries[i].clk); dep_mclk_table->entries[i].clk);
clocks->count++;
} }
clocks->count = dep_mclk_table->count;
} else if (hwmgr->pp_table_version == PP_TABLE_V0) { } else if (hwmgr->pp_table_version == PP_TABLE_V0) {
mclk_table = hwmgr->dyn_state.vddc_dependency_on_mclk; mclk_table = hwmgr->dyn_state.vddc_dependency_on_mclk;
for (i = 0; i < mclk_table->count; i++) { for (i = 0; i < mclk_table->count; i++)
clocks->clock[i] = mclk_table->entries[i].clk; clocks->clock[i] = mclk_table->entries[i].clk;
clocks->count++; clocks->count = mclk_table->count;
}
} }
return 0; return 0;
} }
......
...@@ -37,8 +37,10 @@ MODULE_FIRMWARE("amdgpu/tonga_k_smc.bin"); ...@@ -37,8 +37,10 @@ MODULE_FIRMWARE("amdgpu/tonga_k_smc.bin");
MODULE_FIRMWARE("amdgpu/fiji_smc.bin"); MODULE_FIRMWARE("amdgpu/fiji_smc.bin");
MODULE_FIRMWARE("amdgpu/polaris10_smc.bin"); MODULE_FIRMWARE("amdgpu/polaris10_smc.bin");
MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin"); MODULE_FIRMWARE("amdgpu/polaris10_smc_sk.bin");
MODULE_FIRMWARE("amdgpu/polaris10_k_smc.bin");
MODULE_FIRMWARE("amdgpu/polaris11_smc.bin"); MODULE_FIRMWARE("amdgpu/polaris11_smc.bin");
MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin"); MODULE_FIRMWARE("amdgpu/polaris11_smc_sk.bin");
MODULE_FIRMWARE("amdgpu/polaris11_k_smc.bin");
MODULE_FIRMWARE("amdgpu/polaris12_smc.bin"); MODULE_FIRMWARE("amdgpu/polaris12_smc.bin");
......
...@@ -135,8 +135,7 @@ static int arcpgu_load(struct drm_device *drm) ...@@ -135,8 +135,7 @@ static int arcpgu_load(struct drm_device *drm)
drm_kms_helper_poll_init(drm); drm_kms_helper_poll_init(drm);
arcpgu->fbdev = drm_fbdev_cma_init(drm, 16, arcpgu->fbdev = drm_fbdev_cma_init(drm, 16,
drm->mode_config.num_crtc, drm->mode_config.num_connector);
drm->mode_config.num_connector);
if (IS_ERR(arcpgu->fbdev)) { if (IS_ERR(arcpgu->fbdev)) {
ret = PTR_ERR(arcpgu->fbdev); ret = PTR_ERR(arcpgu->fbdev);
arcpgu->fbdev = NULL; arcpgu->fbdev = NULL;
......
...@@ -349,7 +349,7 @@ static int hdlcd_drm_bind(struct device *dev) ...@@ -349,7 +349,7 @@ static int hdlcd_drm_bind(struct device *dev)
drm_mode_config_reset(drm); drm_mode_config_reset(drm);
drm_kms_helper_poll_init(drm); drm_kms_helper_poll_init(drm);
hdlcd->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, hdlcd->fbdev = drm_fbdev_cma_init(drm, 32,
drm->mode_config.num_connector); drm->mode_config.num_connector);
if (IS_ERR(hdlcd->fbdev)) { if (IS_ERR(hdlcd->fbdev)) {
......
...@@ -457,7 +457,7 @@ static int malidp_bind(struct device *dev) ...@@ -457,7 +457,7 @@ static int malidp_bind(struct device *dev)
drm_mode_config_reset(drm); drm_mode_config_reset(drm);
malidp->fbdev = drm_fbdev_cma_init(drm, 32, drm->mode_config.num_crtc, malidp->fbdev = drm_fbdev_cma_init(drm, 32,
drm->mode_config.num_connector); drm->mode_config.num_connector);
if (IS_ERR(malidp->fbdev)) { if (IS_ERR(malidp->fbdev)) {
......
...@@ -137,7 +137,7 @@ int armada_fbdev_init(struct drm_device *dev) ...@@ -137,7 +137,7 @@ int armada_fbdev_init(struct drm_device *dev)
drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs); drm_fb_helper_prepare(dev, fbh, &armada_fb_helper_funcs);
ret = drm_fb_helper_init(dev, fbh, 1, 1); ret = drm_fb_helper_init(dev, fbh, 1);
if (ret) { if (ret) {
DRM_ERROR("failed to initialize drm fb helper\n"); DRM_ERROR("failed to initialize drm fb helper\n");
goto err_fb_helper; goto err_fb_helper;
......
...@@ -148,8 +148,8 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj) ...@@ -148,8 +148,8 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj)
return -ENOSPC; return -ENOSPC;
mutex_lock(&priv->linear_lock); mutex_lock(&priv->linear_lock);
ret = drm_mm_insert_node(&priv->linear, node, size, align, ret = drm_mm_insert_node_generic(&priv->linear, node,
DRM_MM_SEARCH_DEFAULT); size, align, 0, 0);
mutex_unlock(&priv->linear_lock); mutex_unlock(&priv->linear_lock);
if (ret) { if (ret) {
kfree(node); kfree(node);
......
...@@ -315,8 +315,7 @@ int ast_fbdev_init(struct drm_device *dev) ...@@ -315,8 +315,7 @@ int ast_fbdev_init(struct drm_device *dev)
drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs); drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs);
ret = drm_fb_helper_init(dev, &afbdev->helper, ret = drm_fb_helper_init(dev, &afbdev->helper, 1);
1, 1);
if (ret) if (ret)
goto free; goto free;
......
...@@ -647,7 +647,6 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev) ...@@ -647,7 +647,6 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
dc->fbdev = drm_fbdev_cma_init(dev, 24, dc->fbdev = drm_fbdev_cma_init(dev, 24,
dev->mode_config.num_crtc,
dev->mode_config.num_connector); dev->mode_config.num_connector);
if (IS_ERR(dc->fbdev)) if (IS_ERR(dc->fbdev))
dc->fbdev = NULL; dc->fbdev = NULL;
......
...@@ -12,6 +12,10 @@ ...@@ -12,6 +12,10 @@
#include "bochs.h" #include "bochs.h"
static int bochs_modeset = -1;
module_param_named(modeset, bochs_modeset, int, 0444);
MODULE_PARM_DESC(modeset, "enable/disable kernel modesetting");
static bool enable_fbdev = true; static bool enable_fbdev = true;
module_param_named(fbdev, enable_fbdev, bool, 0444); module_param_named(fbdev, enable_fbdev, bool, 0444);
MODULE_PARM_DESC(fbdev, "register fbdev device"); MODULE_PARM_DESC(fbdev, "register fbdev device");
...@@ -214,6 +218,12 @@ static struct pci_driver bochs_pci_driver = { ...@@ -214,6 +218,12 @@ static struct pci_driver bochs_pci_driver = {
static int __init bochs_init(void) static int __init bochs_init(void)
{ {
if (vgacon_text_force() && bochs_modeset == -1)
return -EINVAL;
if (bochs_modeset == 0)
return -EINVAL;
return drm_pci_init(&bochs_driver, &bochs_pci_driver); return drm_pci_init(&bochs_driver, &bochs_pci_driver);
} }
......
...@@ -169,8 +169,7 @@ int bochs_fbdev_init(struct bochs_device *bochs) ...@@ -169,8 +169,7 @@ int bochs_fbdev_init(struct bochs_device *bochs)
drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper, drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper,
&bochs_fb_helper_funcs); &bochs_fb_helper_funcs);
ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, 1);
1, 1);
if (ret) if (ret)
return ret; return ret;
......
...@@ -353,7 +353,7 @@ ...@@ -353,7 +353,7 @@
#define REG_TTXNUMB 0x0116 #define REG_TTXNUMB 0x0116
#define MSK_TTXNUMB_TTX_AFFCTRL_3_0 0xf0 #define MSK_TTXNUMB_TTX_AFFCTRL_3_0 0xf0
#define BIT_TTXNUMB_TTX_COM1_AT_SYNC_WAIT BIT(3) #define BIT_TTXNUMB_TTX_COM1_AT_SYNC_WAIT BIT(3)
#define MSK_TTXNUMB_TTX_NUMBPS_2_0 0x07 #define MSK_TTXNUMB_TTX_NUMBPS 0x07
/* TDM TX NUMSPISYM, default value: 0x04 */ /* TDM TX NUMSPISYM, default value: 0x04 */
#define REG_TTXSPINUMS 0x0117 #define REG_TTXSPINUMS 0x0117
...@@ -403,12 +403,16 @@ ...@@ -403,12 +403,16 @@
/* TDM RX Status 2nd, default value: 0x00 */ /* TDM RX Status 2nd, default value: 0x00 */
#define REG_TRXSTA2 0x015c #define REG_TRXSTA2 0x015c
#define MSK_TDM_SYNCHRONIZED 0xc0
#define VAL_TDM_SYNCHRONIZED 0x80
/* TDM RX INT Low, default value: 0x00 */ /* TDM RX INT Low, default value: 0x00 */
#define REG_TRXINTL 0x0163 #define REG_TRXINTL 0x0163
/* TDM RX INT High, default value: 0x00 */ /* TDM RX INT High, default value: 0x00 */
#define REG_TRXINTH 0x0164 #define REG_TRXINTH 0x0164
#define BIT_TDM_INTR_SYNC_DATA BIT(0)
#define BIT_TDM_INTR_SYNC_WAIT BIT(1)
/* TDM RX INTMASK High, default value: 0x00 */ /* TDM RX INTMASK High, default value: 0x00 */
#define REG_TRXINTMH 0x0166 #define REG_TRXINTMH 0x0166
...@@ -429,12 +433,14 @@ ...@@ -429,12 +433,14 @@
/* HSIC Keeper, default value: 0x00 */ /* HSIC Keeper, default value: 0x00 */
#define REG_KEEPER 0x0181 #define REG_KEEPER 0x0181
#define MSK_KEEPER_KEEPER_MODE_1_0 0x03 #define MSK_KEEPER_MODE 0x03
#define VAL_KEEPER_MODE_HOST 0
#define VAL_KEEPER_MODE_DEVICE 2
/* HSIC Flow Control General, default value: 0x02 */ /* HSIC Flow Control General, default value: 0x02 */
#define REG_FCGC 0x0183 #define REG_FCGC 0x0183
#define BIT_FCGC_HSIC_FC_HOSTMODE BIT(1) #define BIT_FCGC_HSIC_HOSTMODE BIT(1)
#define BIT_FCGC_HSIC_FC_ENABLE BIT(0) #define BIT_FCGC_HSIC_ENABLE BIT(0)
/* HSIC Flow Control CTR13, default value: 0xfc */ /* HSIC Flow Control CTR13, default value: 0xfc */
#define REG_FCCTR13 0x0191 #define REG_FCCTR13 0x0191
...@@ -841,6 +847,8 @@ ...@@ -841,6 +847,8 @@
#define MSK_MHL_DP_CTL7_DT_DRV_VBIAS_CASCTL 0xf0 #define MSK_MHL_DP_CTL7_DT_DRV_VBIAS_CASCTL 0xf0
#define MSK_MHL_DP_CTL7_DT_DRV_IREF_CTL 0x0f #define MSK_MHL_DP_CTL7_DT_DRV_IREF_CTL 0x0f
#define REG_MHL_DP_CTL8 0x0352
/* Tx Zone Ctl1, default value: 0x00 */ /* Tx Zone Ctl1, default value: 0x00 */
#define REG_TX_ZONE_CTL1 0x0361 #define REG_TX_ZONE_CTL1 0x0361
#define VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE 0x08 #define VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE 0x08
...@@ -1078,16 +1086,26 @@ ...@@ -1078,16 +1086,26 @@
/* TPI Info Frame Select, default value: 0x00 */ /* TPI Info Frame Select, default value: 0x00 */
#define REG_TPI_INFO_FSEL 0x06bf #define REG_TPI_INFO_FSEL 0x06bf
#define BIT_TPI_INFO_FSEL_TPI_INFO_EN BIT(7) #define BIT_TPI_INFO_FSEL_EN BIT(7)
#define BIT_TPI_INFO_FSEL_TPI_INFO_RPT BIT(6) #define BIT_TPI_INFO_FSEL_RPT BIT(6)
#define BIT_TPI_INFO_FSEL_TPI_INFO_READ_FLAG BIT(5) #define BIT_TPI_INFO_FSEL_READ_FLAG BIT(5)
#define MSK_TPI_INFO_FSEL_TPI_INFO_SEL 0x07 #define MSK_TPI_INFO_FSEL_PKT 0x07
#define VAL_TPI_INFO_FSEL_AVI 0x00
#define VAL_TPI_INFO_FSEL_SPD 0x01
#define VAL_TPI_INFO_FSEL_AUD 0x02
#define VAL_TPI_INFO_FSEL_MPG 0x03
#define VAL_TPI_INFO_FSEL_GEN 0x04
#define VAL_TPI_INFO_FSEL_GEN2 0x05
#define VAL_TPI_INFO_FSEL_VSI 0x06
/* TPI Info Byte #0, default value: 0x00 */ /* TPI Info Byte #0, default value: 0x00 */
#define REG_TPI_INFO_B0 0x06c0 #define REG_TPI_INFO_B0 0x06c0
/* CoC Status, default value: 0x00 */ /* CoC Status, default value: 0x00 */
#define REG_COC_STAT_0 0x0700 #define REG_COC_STAT_0 0x0700
#define BIT_COC_STAT_0_PLL_LOCKED BIT(7)
#define MSK_COC_STAT_0_FSM_STATE 0x0f
#define REG_COC_STAT_1 0x0701 #define REG_COC_STAT_1 0x0701
#define REG_COC_STAT_2 0x0702 #define REG_COC_STAT_2 0x0702
#define REG_COC_STAT_3 0x0703 #define REG_COC_STAT_3 0x0703
...@@ -1282,14 +1300,14 @@ ...@@ -1282,14 +1300,14 @@
/* MDT Transmit Control, default value: 0x70 */ /* MDT Transmit Control, default value: 0x70 */
#define REG_MDT_XMIT_CTRL 0x0588 #define REG_MDT_XMIT_CTRL 0x0588
#define BIT_MDT_XMIT_CTRL_MDT_XMIT_EN BIT(7) #define BIT_MDT_XMIT_CTRL_EN BIT(7)
#define BIT_MDT_XMIT_CTRL_MDT_XMIT_CMD_MERGE_EN BIT(6) #define BIT_MDT_XMIT_CTRL_CMD_MERGE_EN BIT(6)
#define BIT_MDT_XMIT_CTRL_MDT_XMIT_FIXED_BURST_LEN BIT(5) #define BIT_MDT_XMIT_CTRL_FIXED_BURST_LEN BIT(5)
#define BIT_MDT_XMIT_CTRL_MDT_XMIT_FIXED_AID BIT(4) #define BIT_MDT_XMIT_CTRL_FIXED_AID BIT(4)
#define BIT_MDT_XMIT_CTRL_MDT_XMIT_SINGLE_RUN_EN BIT(3) #define BIT_MDT_XMIT_CTRL_SINGLE_RUN_EN BIT(3)
#define BIT_MDT_XMIT_CTRL_MDT_CLR_ABORT_WAIT BIT(2) #define BIT_MDT_XMIT_CTRL_CLR_ABORT_WAIT BIT(2)
#define BIT_MDT_XMIT_CTRL_MDT_XFIFO_CLR_ALL BIT(1) #define BIT_MDT_XMIT_CTRL_XFIFO_CLR_ALL BIT(1)
#define BIT_MDT_XMIT_CTRL_MDT_XFIFO_CLR_CUR BIT(0) #define BIT_MDT_XMIT_CTRL_XFIFO_CLR_CUR BIT(0)
/* MDT Receive WRITE Port, default value: 0x00 */ /* MDT Receive WRITE Port, default value: 0x00 */
#define REG_MDT_XMIT_WRITE_PORT 0x0589 #define REG_MDT_XMIT_WRITE_PORT 0x0589
......
...@@ -289,7 +289,7 @@ int cirrus_fbdev_init(struct cirrus_device *cdev) ...@@ -289,7 +289,7 @@ int cirrus_fbdev_init(struct cirrus_device *cdev)
&cirrus_fb_helper_funcs); &cirrus_fb_helper_funcs);
ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper, ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
cdev->num_crtc, CIRRUSFB_CONN_LIMIT); CIRRUSFB_CONN_LIMIT);
if (ret) if (ret)
return ret; return ret;
......
...@@ -307,9 +307,8 @@ static s64 __user *get_out_fence_for_crtc(struct drm_atomic_state *state, ...@@ -307,9 +307,8 @@ static s64 __user *get_out_fence_for_crtc(struct drm_atomic_state *state,
* @state: the CRTC whose incoming state to update * @state: the CRTC whose incoming state to update
* @mode: kernel-internal mode to use for the CRTC, or NULL to disable * @mode: kernel-internal mode to use for the CRTC, or NULL to disable
* *
* Set a mode (originating from the kernel) on the desired CRTC state. Does * Set a mode (originating from the kernel) on the desired CRTC state and update
* not change any other state properties, including enable, active, or * the enable property.
* mode_changed.
* *
* RETURNS: * RETURNS:
* Zero on success, error code on failure. Cannot return -EDEADLK. * Zero on success, error code on failure. Cannot return -EDEADLK.
......
...@@ -369,7 +369,7 @@ mode_fixup(struct drm_atomic_state *state) ...@@ -369,7 +369,7 @@ mode_fixup(struct drm_atomic_state *state)
struct drm_connector *connector; struct drm_connector *connector;
struct drm_connector_state *conn_state; struct drm_connector_state *conn_state;
int i; int i;
bool ret; int ret;
for_each_crtc_in_state(state, crtc, crtc_state, i) { for_each_crtc_in_state(state, crtc, crtc_state, i) {
if (!crtc_state->mode_changed && if (!crtc_state->mode_changed &&
......
...@@ -87,6 +87,30 @@ ...@@ -87,6 +87,30 @@
* "GAMMA_LUT" property above. * "GAMMA_LUT" property above.
*/ */
/**
* drm_color_lut_extract - clamp and round LUT entries
* @user_input: input value
* @bit_precision: number of bits the hw LUT supports
*
* Extract a degamma/gamma LUT value provided by user (in the form of
* &drm_color_lut entries) and round it to the precision supported by the
* hardware.
*/
uint32_t drm_color_lut_extract(uint32_t user_input, uint32_t bit_precision)
{
uint32_t val = user_input;
uint32_t max = 0xffff >> (16 - bit_precision);
/* Round only if we're not using full precision. */
if (bit_precision < 16) {
val += 1UL << (16 - bit_precision - 1);
val >>= 16 - bit_precision;
}
return clamp_val(val, 0, max);
}
EXPORT_SYMBOL(drm_color_lut_extract);
/** /**
* drm_crtc_enable_color_mgmt - enable color management properties * drm_crtc_enable_color_mgmt - enable color management properties
* @crtc: DRM CRTC * @crtc: DRM CRTC
......
...@@ -207,3 +207,6 @@ int drm_mode_cursor2_ioctl(struct drm_device *dev, ...@@ -207,3 +207,6 @@ int drm_mode_cursor2_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv); void *data, struct drm_file *file_priv);
int drm_mode_page_flip_ioctl(struct drm_device *dev, int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv); void *data, struct drm_file *file_priv);
/* drm_edid.c */
void drm_mode_fixup_1366x768(struct drm_display_mode *mode);
...@@ -465,7 +465,10 @@ static void drm_fs_inode_free(struct inode *inode) ...@@ -465,7 +465,10 @@ static void drm_fs_inode_free(struct inode *inode)
* that do embed &struct drm_device it must be placed first in the overall * that do embed &struct drm_device it must be placed first in the overall
* structure, and the overall structure must be allocated using kmalloc(): The * structure, and the overall structure must be allocated using kmalloc(): The
* drm core's release function unconditionally calls kfree() on the @dev pointer * drm core's release function unconditionally calls kfree() on the @dev pointer
* when the final reference is released. * when the final reference is released. To override this behaviour, and so
* allow embedding of the drm_device inside the driver's device struct at an
* arbitrary offset, you must supply a &drm_driver.release callback and control
* the finalization explicitly.
* *
* RETURNS: * RETURNS:
* 0 on success, or error code on failure. * 0 on success, or error code on failure.
...@@ -552,6 +555,41 @@ int drm_dev_init(struct drm_device *dev, ...@@ -552,6 +555,41 @@ int drm_dev_init(struct drm_device *dev,
} }
EXPORT_SYMBOL(drm_dev_init); EXPORT_SYMBOL(drm_dev_init);
/**
* drm_dev_fini - Finalize a dead DRM device
* @dev: DRM device
*
* Finalize a dead DRM device. This is the converse to drm_dev_init() and
* frees up all data allocated by it. All driver private data should be
* finalized first. Note that this function does not free the @dev, that is
* left to the caller.
*
* The ref-count of @dev must be zero, and drm_dev_fini() should only be called
* from a &drm_driver.release callback.
*/
void drm_dev_fini(struct drm_device *dev)
{
drm_vblank_cleanup(dev);
if (drm_core_check_feature(dev, DRIVER_GEM))
drm_gem_destroy(dev);
drm_legacy_ctxbitmap_cleanup(dev);
drm_ht_remove(&dev->map_hash);
drm_fs_inode_free(dev->anon_inode);
drm_minor_free(dev, DRM_MINOR_PRIMARY);
drm_minor_free(dev, DRM_MINOR_RENDER);
drm_minor_free(dev, DRM_MINOR_CONTROL);
mutex_destroy(&dev->master_mutex);
mutex_destroy(&dev->ctxlist_mutex);
mutex_destroy(&dev->filelist_mutex);
mutex_destroy(&dev->struct_mutex);
kfree(dev->unique);
}
EXPORT_SYMBOL(drm_dev_fini);
/** /**
* drm_dev_alloc - Allocate new DRM device * drm_dev_alloc - Allocate new DRM device
* @driver: DRM driver to allocate device for * @driver: DRM driver to allocate device for
...@@ -598,25 +636,12 @@ static void drm_dev_release(struct kref *ref) ...@@ -598,25 +636,12 @@ static void drm_dev_release(struct kref *ref)
{ {
struct drm_device *dev = container_of(ref, struct drm_device, ref); struct drm_device *dev = container_of(ref, struct drm_device, ref);
drm_vblank_cleanup(dev); if (dev->driver->release) {
dev->driver->release(dev);
if (drm_core_check_feature(dev, DRIVER_GEM)) } else {
drm_gem_destroy(dev); drm_dev_fini(dev);
kfree(dev);
drm_legacy_ctxbitmap_cleanup(dev); }
drm_ht_remove(&dev->map_hash);
drm_fs_inode_free(dev->anon_inode);
drm_minor_free(dev, DRM_MINOR_PRIMARY);
drm_minor_free(dev, DRM_MINOR_RENDER);
drm_minor_free(dev, DRM_MINOR_CONTROL);
mutex_destroy(&dev->master_mutex);
mutex_destroy(&dev->ctxlist_mutex);
mutex_destroy(&dev->filelist_mutex);
mutex_destroy(&dev->struct_mutex);
kfree(dev->unique);
kfree(dev);
} }
/** /**
......
...@@ -38,6 +38,8 @@ ...@@ -38,6 +38,8 @@
#include <drm/drm_encoder.h> #include <drm/drm_encoder.h>
#include <drm/drm_displayid.h> #include <drm/drm_displayid.h>
#include "drm_crtc_internal.h"
#define version_greater(edid, maj, min) \ #define version_greater(edid, maj, min) \
(((edid)->version > (maj)) || \ (((edid)->version > (maj)) || \
((edid)->version == (maj) && (edid)->revision > (min))) ((edid)->version == (maj) && (edid)->revision > (min)))
...@@ -2153,7 +2155,7 @@ drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid, ...@@ -2153,7 +2155,7 @@ drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid,
/* fix up 1366x768 mode from 1368x768; /* fix up 1366x768 mode from 1368x768;
* GFT/CVT can't express 1366 width which isn't dividable by 8 * GFT/CVT can't express 1366 width which isn't dividable by 8
*/ */
static void fixup_mode_1366x768(struct drm_display_mode *mode) void drm_mode_fixup_1366x768(struct drm_display_mode *mode)
{ {
if (mode->hdisplay == 1368 && mode->vdisplay == 768) { if (mode->hdisplay == 1368 && mode->vdisplay == 768) {
mode->hdisplay = 1366; mode->hdisplay = 1366;
...@@ -2177,7 +2179,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, ...@@ -2177,7 +2179,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid,
if (!newmode) if (!newmode)
return modes; return modes;
fixup_mode_1366x768(newmode); drm_mode_fixup_1366x768(newmode);
if (!mode_in_range(newmode, edid, timing) || if (!mode_in_range(newmode, edid, timing) ||
!valid_inferred_mode(connector, newmode)) { !valid_inferred_mode(connector, newmode)) {
drm_mode_destroy(dev, newmode); drm_mode_destroy(dev, newmode);
...@@ -2206,7 +2208,7 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid, ...@@ -2206,7 +2208,7 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid,
if (!newmode) if (!newmode)
return modes; return modes;
fixup_mode_1366x768(newmode); drm_mode_fixup_1366x768(newmode);
if (!mode_in_range(newmode, edid, timing) || if (!mode_in_range(newmode, edid, timing) ||
!valid_inferred_mode(connector, newmode)) { !valid_inferred_mode(connector, newmode)) {
drm_mode_destroy(dev, newmode); drm_mode_destroy(dev, newmode);
......
...@@ -489,15 +489,14 @@ static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = { ...@@ -489,15 +489,14 @@ static const struct drm_fb_helper_funcs drm_fb_cma_helper_funcs = {
* drm_fbdev_cma_init_with_funcs() - Allocate and initializes a drm_fbdev_cma struct * drm_fbdev_cma_init_with_funcs() - Allocate and initializes a drm_fbdev_cma struct
* @dev: DRM device * @dev: DRM device
* @preferred_bpp: Preferred bits per pixel for the device * @preferred_bpp: Preferred bits per pixel for the device
* @num_crtc: Number of CRTCs
* @max_conn_count: Maximum number of connectors * @max_conn_count: Maximum number of connectors
* @funcs: fb helper functions, in particular a custom dirty() callback * @funcs: fb helper functions, in particular a custom dirty() callback
* *
* Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR. * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
*/ */
struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev, struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int num_crtc, unsigned int preferred_bpp, unsigned int max_conn_count,
unsigned int max_conn_count, const struct drm_framebuffer_funcs *funcs) const struct drm_framebuffer_funcs *funcs)
{ {
struct drm_fbdev_cma *fbdev_cma; struct drm_fbdev_cma *fbdev_cma;
struct drm_fb_helper *helper; struct drm_fb_helper *helper;
...@@ -514,7 +513,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev, ...@@ -514,7 +513,7 @@ struct drm_fbdev_cma *drm_fbdev_cma_init_with_funcs(struct drm_device *dev,
drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs); drm_fb_helper_prepare(dev, helper, &drm_fb_cma_helper_funcs);
ret = drm_fb_helper_init(dev, helper, num_crtc, max_conn_count); ret = drm_fb_helper_init(dev, helper, max_conn_count);
if (ret < 0) { if (ret < 0) {
dev_err(dev->dev, "Failed to initialize drm fb helper.\n"); dev_err(dev->dev, "Failed to initialize drm fb helper.\n");
goto err_free; goto err_free;
...@@ -554,11 +553,11 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init_with_funcs); ...@@ -554,11 +553,11 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_init_with_funcs);
* Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR. * Returns a newly allocated drm_fbdev_cma struct or a ERR_PTR.
*/ */
struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev, struct drm_fbdev_cma *drm_fbdev_cma_init(struct drm_device *dev,
unsigned int preferred_bpp, unsigned int num_crtc, unsigned int preferred_bpp, unsigned int max_conn_count)
unsigned int max_conn_count)
{ {
return drm_fbdev_cma_init_with_funcs(dev, preferred_bpp, num_crtc, return drm_fbdev_cma_init_with_funcs(dev, preferred_bpp,
max_conn_count, &drm_fb_cma_funcs); max_conn_count,
&drm_fb_cma_funcs);
} }
EXPORT_SYMBOL_GPL(drm_fbdev_cma_init); EXPORT_SYMBOL_GPL(drm_fbdev_cma_init);
......
...@@ -712,7 +712,6 @@ EXPORT_SYMBOL(drm_fb_helper_prepare); ...@@ -712,7 +712,6 @@ EXPORT_SYMBOL(drm_fb_helper_prepare);
* drm_fb_helper_init - initialize a drm_fb_helper structure * drm_fb_helper_init - initialize a drm_fb_helper structure
* @dev: drm device * @dev: drm device
* @fb_helper: driver-allocated fbdev helper structure to initialize * @fb_helper: driver-allocated fbdev helper structure to initialize
* @crtc_count: maximum number of crtcs to support in this fbdev emulation
* @max_conn_count: max connector count * @max_conn_count: max connector count
* *
* This allocates the structures for the fbdev helper with the given limits. * This allocates the structures for the fbdev helper with the given limits.
...@@ -727,9 +726,10 @@ EXPORT_SYMBOL(drm_fb_helper_prepare); ...@@ -727,9 +726,10 @@ EXPORT_SYMBOL(drm_fb_helper_prepare);
*/ */
int drm_fb_helper_init(struct drm_device *dev, int drm_fb_helper_init(struct drm_device *dev,
struct drm_fb_helper *fb_helper, struct drm_fb_helper *fb_helper,
int crtc_count, int max_conn_count) int max_conn_count)
{ {
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_mode_config *config = &dev->mode_config;
int i; int i;
if (!drm_fbdev_emulation) if (!drm_fbdev_emulation)
...@@ -738,11 +738,11 @@ int drm_fb_helper_init(struct drm_device *dev, ...@@ -738,11 +738,11 @@ int drm_fb_helper_init(struct drm_device *dev,
if (!max_conn_count) if (!max_conn_count)
return -EINVAL; return -EINVAL;
fb_helper->crtc_info = kcalloc(crtc_count, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL); fb_helper->crtc_info = kcalloc(config->num_crtc, sizeof(struct drm_fb_helper_crtc), GFP_KERNEL);
if (!fb_helper->crtc_info) if (!fb_helper->crtc_info)
return -ENOMEM; return -ENOMEM;
fb_helper->crtc_count = crtc_count; fb_helper->crtc_count = config->num_crtc;
fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL); fb_helper->connector_info = kcalloc(dev->mode_config.num_connector, sizeof(struct drm_fb_helper_connector *), GFP_KERNEL);
if (!fb_helper->connector_info) { if (!fb_helper->connector_info) {
kfree(fb_helper->crtc_info); kfree(fb_helper->crtc_info);
...@@ -751,7 +751,7 @@ int drm_fb_helper_init(struct drm_device *dev, ...@@ -751,7 +751,7 @@ int drm_fb_helper_init(struct drm_device *dev,
fb_helper->connector_info_alloc_count = dev->mode_config.num_connector; fb_helper->connector_info_alloc_count = dev->mode_config.num_connector;
fb_helper->connector_count = 0; fb_helper->connector_count = 0;
for (i = 0; i < crtc_count; i++) { for (i = 0; i < fb_helper->crtc_count; i++) {
fb_helper->crtc_info[i].mode_set.connectors = fb_helper->crtc_info[i].mode_set.connectors =
kcalloc(max_conn_count, kcalloc(max_conn_count,
sizeof(struct drm_connector *), sizeof(struct drm_connector *),
...@@ -860,6 +860,9 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper) ...@@ -860,6 +860,9 @@ void drm_fb_helper_fini(struct drm_fb_helper *fb_helper)
if (!drm_fbdev_emulation) if (!drm_fbdev_emulation)
return; return;
cancel_work_sync(&fb_helper->resume_work);
cancel_work_sync(&fb_helper->dirty_work);
mutex_lock(&kernel_fb_helper_lock); mutex_lock(&kernel_fb_helper_lock);
if (!list_empty(&fb_helper->kernel_fb_list)) { if (!list_empty(&fb_helper->kernel_fb_list)) {
list_del(&fb_helper->kernel_fb_list); list_del(&fb_helper->kernel_fb_list);
......
...@@ -97,14 +97,6 @@ ...@@ -97,14 +97,6 @@
* locking would be fully redundant. * locking would be fully redundant.
*/ */
static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
u64 size,
u64 alignment,
unsigned long color,
u64 start,
u64 end,
enum drm_mm_search_flags flags);
#ifdef CONFIG_DRM_DEBUG_MM #ifdef CONFIG_DRM_DEBUG_MM
#include <linux/stackdepot.h> #include <linux/stackdepot.h>
...@@ -226,69 +218,151 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node, ...@@ -226,69 +218,151 @@ static void drm_mm_interval_tree_add_node(struct drm_mm_node *hole_node,
&drm_mm_interval_tree_augment); &drm_mm_interval_tree_augment);
} }
static void drm_mm_insert_helper(struct drm_mm_node *hole_node, #define RB_INSERT(root, member, expr) do { \
struct drm_mm_node *node, struct rb_node **link = &root.rb_node, *rb = NULL; \
u64 size, u64 alignment, u64 x = expr(node); \
unsigned long color, while (*link) { \
u64 range_start, u64 range_end, rb = *link; \
enum drm_mm_allocator_flags flags) if (x < expr(rb_entry(rb, struct drm_mm_node, member))) \
link = &rb->rb_left; \
else \
link = &rb->rb_right; \
} \
rb_link_node(&node->member, rb, link); \
rb_insert_color(&node->member, &root); \
} while (0)
#define HOLE_SIZE(NODE) ((NODE)->hole_size)
#define HOLE_ADDR(NODE) (__drm_mm_hole_node_start(NODE))
static void add_hole(struct drm_mm_node *node)
{ {
struct drm_mm *mm = hole_node->mm; struct drm_mm *mm = node->mm;
u64 hole_start = drm_mm_hole_node_start(hole_node);
u64 hole_end = drm_mm_hole_node_end(hole_node);
u64 adj_start = hole_start;
u64 adj_end = hole_end;
DRM_MM_BUG_ON(!drm_mm_hole_follows(hole_node) || node->allocated); node->hole_size =
__drm_mm_hole_node_end(node) - __drm_mm_hole_node_start(node);
DRM_MM_BUG_ON(!drm_mm_hole_follows(node));
if (mm->color_adjust) RB_INSERT(mm->holes_size, rb_hole_size, HOLE_SIZE);
mm->color_adjust(hole_node, color, &adj_start, &adj_end); RB_INSERT(mm->holes_addr, rb_hole_addr, HOLE_ADDR);
adj_start = max(adj_start, range_start); list_add(&node->hole_stack, &mm->hole_stack);
adj_end = min(adj_end, range_end); }
if (flags & DRM_MM_CREATE_TOP) static void rm_hole(struct drm_mm_node *node)
adj_start = adj_end - size; {
DRM_MM_BUG_ON(!drm_mm_hole_follows(node));
if (alignment) { list_del(&node->hole_stack);
u64 rem; rb_erase(&node->rb_hole_size, &node->mm->holes_size);
rb_erase(&node->rb_hole_addr, &node->mm->holes_addr);
node->hole_size = 0;
div64_u64_rem(adj_start, alignment, &rem); DRM_MM_BUG_ON(drm_mm_hole_follows(node));
if (rem) { }
if (flags & DRM_MM_CREATE_TOP)
adj_start -= rem; static inline struct drm_mm_node *rb_hole_size_to_node(struct rb_node *rb)
else {
adj_start += alignment - rem; return rb_entry_safe(rb, struct drm_mm_node, rb_hole_size);
}
static inline struct drm_mm_node *rb_hole_addr_to_node(struct rb_node *rb)
{
return rb_entry_safe(rb, struct drm_mm_node, rb_hole_addr);
}
static inline u64 rb_hole_size(struct rb_node *rb)
{
return rb_entry(rb, struct drm_mm_node, rb_hole_size)->hole_size;
}
static struct drm_mm_node *best_hole(struct drm_mm *mm, u64 size)
{
struct rb_node *best = NULL;
struct rb_node **link = &mm->holes_size.rb_node;
while (*link) {
struct rb_node *rb = *link;
if (size <= rb_hole_size(rb)) {
link = &rb->rb_left;
best = rb;
} else {
link = &rb->rb_right;
} }
} }
if (adj_start == hole_start) { return rb_hole_size_to_node(best);
hole_node->hole_follows = 0; }
list_del(&hole_node->hole_stack);
static struct drm_mm_node *find_hole(struct drm_mm *mm, u64 addr)
{
struct drm_mm_node *node = NULL;
struct rb_node **link = &mm->holes_addr.rb_node;
while (*link) {
u64 hole_start;
node = rb_hole_addr_to_node(*link);
hole_start = __drm_mm_hole_node_start(node);
if (addr < hole_start)
link = &node->rb_hole_addr.rb_left;
else if (addr > hole_start + node->hole_size)
link = &node->rb_hole_addr.rb_right;
else
break;
} }
node->start = adj_start; return node;
node->size = size; }
node->mm = mm;
node->color = color;
node->allocated = 1;
list_add(&node->node_list, &hole_node->node_list); static struct drm_mm_node *
first_hole(struct drm_mm *mm,
u64 start, u64 end, u64 size,
enum drm_mm_insert_mode mode)
{
if (RB_EMPTY_ROOT(&mm->holes_size))
return NULL;
drm_mm_interval_tree_add_node(hole_node, node); switch (mode) {
default:
case DRM_MM_INSERT_BEST:
return best_hole(mm, size);
DRM_MM_BUG_ON(node->start < range_start); case DRM_MM_INSERT_LOW:
DRM_MM_BUG_ON(node->start < adj_start); return find_hole(mm, start);
DRM_MM_BUG_ON(node->start + node->size > adj_end);
DRM_MM_BUG_ON(node->start + node->size > range_end);
node->hole_follows = 0; case DRM_MM_INSERT_HIGH:
if (__drm_mm_hole_node_start(node) < hole_end) { return find_hole(mm, end);
list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1; case DRM_MM_INSERT_EVICT:
return list_first_entry_or_null(&mm->hole_stack,
struct drm_mm_node,
hole_stack);
} }
}
save_stack(node); static struct drm_mm_node *
next_hole(struct drm_mm *mm,
struct drm_mm_node *node,
enum drm_mm_insert_mode mode)
{
switch (mode) {
default:
case DRM_MM_INSERT_BEST:
return rb_hole_size_to_node(rb_next(&node->rb_hole_size));
case DRM_MM_INSERT_LOW:
return rb_hole_addr_to_node(rb_next(&node->rb_hole_addr));
case DRM_MM_INSERT_HIGH:
return rb_hole_addr_to_node(rb_prev(&node->rb_hole_addr));
case DRM_MM_INSERT_EVICT:
node = list_next_entry(node, hole_stack);
return &node->hole_stack == &mm->hole_stack ? NULL : node;
}
} }
/** /**
...@@ -317,21 +391,12 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) ...@@ -317,21 +391,12 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
return -ENOSPC; return -ENOSPC;
/* Find the relevant hole to add our node to */ /* Find the relevant hole to add our node to */
hole = drm_mm_interval_tree_iter_first(&mm->interval_tree, hole = find_hole(mm, node->start);
node->start, ~(u64)0); if (!hole)
if (hole) {
if (hole->start < end)
return -ENOSPC;
} else {
hole = list_entry(drm_mm_nodes(mm), typeof(*hole), node_list);
}
hole = list_last_entry(&hole->node_list, typeof(*hole), node_list);
if (!drm_mm_hole_follows(hole))
return -ENOSPC; return -ENOSPC;
adj_start = hole_start = __drm_mm_hole_node_start(hole); adj_start = hole_start = __drm_mm_hole_node_start(hole);
adj_end = hole_end = __drm_mm_hole_node_end(hole); adj_end = hole_end = hole_start + hole->hole_size;
if (mm->color_adjust) if (mm->color_adjust)
mm->color_adjust(hole, node->color, &adj_start, &adj_end); mm->color_adjust(hole, node->color, &adj_start, &adj_end);
...@@ -340,70 +405,130 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node) ...@@ -340,70 +405,130 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
return -ENOSPC; return -ENOSPC;
node->mm = mm; node->mm = mm;
node->allocated = 1;
list_add(&node->node_list, &hole->node_list); list_add(&node->node_list, &hole->node_list);
drm_mm_interval_tree_add_node(hole, node); drm_mm_interval_tree_add_node(hole, node);
node->allocated = true;
node->hole_size = 0;
if (node->start == hole_start) { rm_hole(hole);
hole->hole_follows = 0; if (node->start > hole_start)
list_del(&hole->hole_stack); add_hole(hole);
} if (end < hole_end)
add_hole(node);
node->hole_follows = 0;
if (end != hole_end) {
list_add(&node->hole_stack, &mm->hole_stack);
node->hole_follows = 1;
}
save_stack(node); save_stack(node);
return 0; return 0;
} }
EXPORT_SYMBOL(drm_mm_reserve_node); EXPORT_SYMBOL(drm_mm_reserve_node);
/** /**
* drm_mm_insert_node_in_range_generic - ranged search for space and insert @node * drm_mm_insert_node_in_range - ranged search for space and insert @node
* @mm: drm_mm to allocate from * @mm: drm_mm to allocate from
* @node: preallocate node to insert * @node: preallocate node to insert
* @size: size of the allocation * @size: size of the allocation
* @alignment: alignment of the allocation * @alignment: alignment of the allocation
* @color: opaque tag value to use for this node * @color: opaque tag value to use for this node
* @start: start of the allowed range for this node * @range_start: start of the allowed range for this node
* @end: end of the allowed range for this node * @range_end: end of the allowed range for this node
* @sflags: flags to fine-tune the allocation search * @mode: fine-tune the allocation search and placement
* @aflags: flags to fine-tune the allocation behavior
* *
* The preallocated @node must be cleared to 0. * The preallocated @node must be cleared to 0.
* *
* Returns: * Returns:
* 0 on success, -ENOSPC if there's no suitable hole. * 0 on success, -ENOSPC if there's no suitable hole.
*/ */
int drm_mm_insert_node_in_range_generic(struct drm_mm *mm, struct drm_mm_node *node, int drm_mm_insert_node_in_range(struct drm_mm * const mm,
u64 size, u64 alignment, struct drm_mm_node * const node,
unsigned long color, u64 size, u64 alignment,
u64 start, u64 end, unsigned long color,
enum drm_mm_search_flags sflags, u64 range_start, u64 range_end,
enum drm_mm_allocator_flags aflags) enum drm_mm_insert_mode mode)
{ {
struct drm_mm_node *hole_node; struct drm_mm_node *hole;
u64 remainder_mask;
if (WARN_ON(size == 0)) DRM_MM_BUG_ON(range_start >= range_end);
return -EINVAL;
hole_node = drm_mm_search_free_in_range_generic(mm, if (unlikely(size == 0 || range_end - range_start < size))
size, alignment, color,
start, end, sflags);
if (!hole_node)
return -ENOSPC; return -ENOSPC;
drm_mm_insert_helper(hole_node, node, if (alignment <= 1)
size, alignment, color, alignment = 0;
start, end, aflags);
return 0; remainder_mask = is_power_of_2(alignment) ? alignment - 1 : 0;
for (hole = first_hole(mm, range_start, range_end, size, mode); hole;
hole = next_hole(mm, hole, mode)) {
u64 hole_start = __drm_mm_hole_node_start(hole);
u64 hole_end = hole_start + hole->hole_size;
u64 adj_start, adj_end;
u64 col_start, col_end;
if (mode == DRM_MM_INSERT_LOW && hole_start >= range_end)
break;
if (mode == DRM_MM_INSERT_HIGH && hole_end <= range_start)
break;
col_start = hole_start;
col_end = hole_end;
if (mm->color_adjust)
mm->color_adjust(hole, color, &col_start, &col_end);
adj_start = max(col_start, range_start);
adj_end = min(col_end, range_end);
if (adj_end <= adj_start || adj_end - adj_start < size)
continue;
if (mode == DRM_MM_INSERT_HIGH)
adj_start = adj_end - size;
if (alignment) {
u64 rem;
if (likely(remainder_mask))
rem = adj_start & remainder_mask;
else
div64_u64_rem(adj_start, alignment, &rem);
if (rem) {
adj_start -= rem;
if (mode != DRM_MM_INSERT_HIGH)
adj_start += alignment;
if (adj_start < max(col_start, range_start) ||
min(col_end, range_end) - adj_start < size)
continue;
if (adj_end <= adj_start ||
adj_end - adj_start < size)
continue;
}
}
node->mm = mm;
node->size = size;
node->start = adj_start;
node->color = color;
node->hole_size = 0;
list_add(&node->node_list, &hole->node_list);
drm_mm_interval_tree_add_node(hole, node);
node->allocated = true;
rm_hole(hole);
if (adj_start > hole_start)
add_hole(hole);
if (adj_start + size < hole_end)
add_hole(node);
save_stack(node);
return 0;
}
return -ENOSPC;
} }
EXPORT_SYMBOL(drm_mm_insert_node_in_range_generic); EXPORT_SYMBOL(drm_mm_insert_node_in_range);
/** /**
* drm_mm_remove_node - Remove a memory node from the allocator. * drm_mm_remove_node - Remove a memory node from the allocator.
...@@ -421,92 +546,20 @@ void drm_mm_remove_node(struct drm_mm_node *node) ...@@ -421,92 +546,20 @@ void drm_mm_remove_node(struct drm_mm_node *node)
DRM_MM_BUG_ON(!node->allocated); DRM_MM_BUG_ON(!node->allocated);
DRM_MM_BUG_ON(node->scanned_block); DRM_MM_BUG_ON(node->scanned_block);
prev_node = prev_node = list_prev_entry(node, node_list);
list_entry(node->node_list.prev, struct drm_mm_node, node_list);
if (drm_mm_hole_follows(node)) {
DRM_MM_BUG_ON(__drm_mm_hole_node_start(node) ==
__drm_mm_hole_node_end(node));
list_del(&node->hole_stack);
} else {
DRM_MM_BUG_ON(__drm_mm_hole_node_start(node) !=
__drm_mm_hole_node_end(node));
}
if (!drm_mm_hole_follows(prev_node)) { if (drm_mm_hole_follows(node))
prev_node->hole_follows = 1; rm_hole(node);
list_add(&prev_node->hole_stack, &mm->hole_stack);
} else
list_move(&prev_node->hole_stack, &mm->hole_stack);
drm_mm_interval_tree_remove(node, &mm->interval_tree); drm_mm_interval_tree_remove(node, &mm->interval_tree);
list_del(&node->node_list); list_del(&node->node_list);
node->allocated = 0; node->allocated = false;
}
EXPORT_SYMBOL(drm_mm_remove_node);
static int check_free_hole(u64 start, u64 end, u64 size, u64 alignment)
{
if (end - start < size)
return 0;
if (alignment) {
u64 rem;
div64_u64_rem(start, alignment, &rem);
if (rem)
start += alignment - rem;
}
return end >= start + size; if (drm_mm_hole_follows(prev_node))
} rm_hole(prev_node);
add_hole(prev_node);
static struct drm_mm_node *drm_mm_search_free_in_range_generic(const struct drm_mm *mm,
u64 size,
u64 alignment,
unsigned long color,
u64 start,
u64 end,
enum drm_mm_search_flags flags)
{
struct drm_mm_node *entry;
struct drm_mm_node *best;
u64 adj_start;
u64 adj_end;
u64 best_size;
DRM_MM_BUG_ON(mm->scan_active);
best = NULL;
best_size = ~0UL;
__drm_mm_for_each_hole(entry, mm, adj_start, adj_end,
flags & DRM_MM_SEARCH_BELOW) {
u64 hole_size = adj_end - adj_start;
if (mm->color_adjust) {
mm->color_adjust(entry, color, &adj_start, &adj_end);
if (adj_end <= adj_start)
continue;
}
adj_start = max(adj_start, start);
adj_end = min(adj_end, end);
if (!check_free_hole(adj_start, adj_end, size, alignment))
continue;
if (!(flags & DRM_MM_SEARCH_BEST))
return entry;
if (hole_size < best_size) {
best = entry;
best_size = hole_size;
}
}
return best;
} }
EXPORT_SYMBOL(drm_mm_remove_node);
/** /**
* drm_mm_replace_node - move an allocation from @old to @new * drm_mm_replace_node - move an allocation from @old to @new
...@@ -521,18 +574,23 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new) ...@@ -521,18 +574,23 @@ void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
{ {
DRM_MM_BUG_ON(!old->allocated); DRM_MM_BUG_ON(!old->allocated);
*new = *old;
list_replace(&old->node_list, &new->node_list); list_replace(&old->node_list, &new->node_list);
list_replace(&old->hole_stack, &new->hole_stack);
rb_replace_node(&old->rb, &new->rb, &old->mm->interval_tree); rb_replace_node(&old->rb, &new->rb, &old->mm->interval_tree);
new->hole_follows = old->hole_follows;
new->mm = old->mm; if (drm_mm_hole_follows(old)) {
new->start = old->start; list_replace(&old->hole_stack, &new->hole_stack);
new->size = old->size; rb_replace_node(&old->rb_hole_size,
new->color = old->color; &new->rb_hole_size,
new->__subtree_last = old->__subtree_last; &old->mm->holes_size);
rb_replace_node(&old->rb_hole_addr,
old->allocated = 0; &new->rb_hole_addr,
new->allocated = 1; &old->mm->holes_addr);
}
old->allocated = false;
new->allocated = true;
} }
EXPORT_SYMBOL(drm_mm_replace_node); EXPORT_SYMBOL(drm_mm_replace_node);
...@@ -577,7 +635,7 @@ EXPORT_SYMBOL(drm_mm_replace_node); ...@@ -577,7 +635,7 @@ EXPORT_SYMBOL(drm_mm_replace_node);
* @color: opaque tag value to use for the allocation * @color: opaque tag value to use for the allocation
* @start: start of the allowed range for the allocation * @start: start of the allowed range for the allocation
* @end: end of the allowed range for the allocation * @end: end of the allowed range for the allocation
* @flags: flags to specify how the allocation will be performed afterwards * @mode: fine-tune the allocation search and placement
* *
* This simply sets up the scanning routines with the parameters for the desired * This simply sets up the scanning routines with the parameters for the desired
* hole. * hole.
...@@ -593,7 +651,7 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, ...@@ -593,7 +651,7 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan,
unsigned long color, unsigned long color,
u64 start, u64 start,
u64 end, u64 end,
unsigned int flags) enum drm_mm_insert_mode mode)
{ {
DRM_MM_BUG_ON(start >= end); DRM_MM_BUG_ON(start >= end);
DRM_MM_BUG_ON(!size || size > end - start); DRM_MM_BUG_ON(!size || size > end - start);
...@@ -608,7 +666,7 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan, ...@@ -608,7 +666,7 @@ void drm_mm_scan_init_with_range(struct drm_mm_scan *scan,
scan->alignment = alignment; scan->alignment = alignment;
scan->remainder_mask = is_power_of_2(alignment) ? alignment - 1 : 0; scan->remainder_mask = is_power_of_2(alignment) ? alignment - 1 : 0;
scan->size = size; scan->size = size;
scan->flags = flags; scan->mode = mode;
DRM_MM_BUG_ON(end <= start); DRM_MM_BUG_ON(end <= start);
scan->range_start = start; scan->range_start = start;
...@@ -667,7 +725,7 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, ...@@ -667,7 +725,7 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan,
if (adj_end <= adj_start || adj_end - adj_start < scan->size) if (adj_end <= adj_start || adj_end - adj_start < scan->size)
return false; return false;
if (scan->flags == DRM_MM_CREATE_TOP) if (scan->mode == DRM_MM_INSERT_HIGH)
adj_start = adj_end - scan->size; adj_start = adj_end - scan->size;
if (scan->alignment) { if (scan->alignment) {
...@@ -679,7 +737,7 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan, ...@@ -679,7 +737,7 @@ bool drm_mm_scan_add_block(struct drm_mm_scan *scan,
div64_u64_rem(adj_start, scan->alignment, &rem); div64_u64_rem(adj_start, scan->alignment, &rem);
if (rem) { if (rem) {
adj_start -= rem; adj_start -= rem;
if (scan->flags != DRM_MM_CREATE_TOP) if (scan->mode != DRM_MM_INSERT_HIGH)
adj_start += scan->alignment; adj_start += scan->alignment;
if (adj_start < max(col_start, scan->range_start) || if (adj_start < max(col_start, scan->range_start) ||
min(col_end, scan->range_end) - adj_start < scan->size) min(col_end, scan->range_end) - adj_start < scan->size)
...@@ -775,7 +833,7 @@ struct drm_mm_node *drm_mm_scan_color_evict(struct drm_mm_scan *scan) ...@@ -775,7 +833,7 @@ struct drm_mm_node *drm_mm_scan_color_evict(struct drm_mm_scan *scan)
hole = list_first_entry(&mm->hole_stack, typeof(*hole), hole_stack); hole = list_first_entry(&mm->hole_stack, typeof(*hole), hole_stack);
hole_start = __drm_mm_hole_node_start(hole); hole_start = __drm_mm_hole_node_start(hole);
hole_end = __drm_mm_hole_node_end(hole); hole_end = hole_start + hole->hole_size;
DRM_MM_BUG_ON(hole_start > scan->hit_start); DRM_MM_BUG_ON(hole_start > scan->hit_start);
DRM_MM_BUG_ON(hole_end < scan->hit_end); DRM_MM_BUG_ON(hole_end < scan->hit_end);
...@@ -802,21 +860,22 @@ void drm_mm_init(struct drm_mm *mm, u64 start, u64 size) ...@@ -802,21 +860,22 @@ void drm_mm_init(struct drm_mm *mm, u64 start, u64 size)
{ {
DRM_MM_BUG_ON(start + size <= start); DRM_MM_BUG_ON(start + size <= start);
mm->color_adjust = NULL;
INIT_LIST_HEAD(&mm->hole_stack); INIT_LIST_HEAD(&mm->hole_stack);
mm->scan_active = 0; mm->interval_tree = RB_ROOT;
mm->holes_size = RB_ROOT;
mm->holes_addr = RB_ROOT;
/* Clever trick to avoid a special case in the free hole tracking. */ /* Clever trick to avoid a special case in the free hole tracking. */
INIT_LIST_HEAD(&mm->head_node.node_list); INIT_LIST_HEAD(&mm->head_node.node_list);
mm->head_node.allocated = 0; mm->head_node.allocated = false;
mm->head_node.hole_follows = 1;
mm->head_node.mm = mm; mm->head_node.mm = mm;
mm->head_node.start = start + size; mm->head_node.start = start + size;
mm->head_node.size = start - mm->head_node.start; mm->head_node.size = -size;
list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack); add_hole(&mm->head_node);
mm->interval_tree = RB_ROOT; mm->scan_active = 0;
mm->color_adjust = NULL;
} }
EXPORT_SYMBOL(drm_mm_init); EXPORT_SYMBOL(drm_mm_init);
...@@ -837,20 +896,17 @@ EXPORT_SYMBOL(drm_mm_takedown); ...@@ -837,20 +896,17 @@ EXPORT_SYMBOL(drm_mm_takedown);
static u64 drm_mm_dump_hole(struct drm_printer *p, const struct drm_mm_node *entry) static u64 drm_mm_dump_hole(struct drm_printer *p, const struct drm_mm_node *entry)
{ {
u64 hole_start, hole_end, hole_size; u64 start, size;
if (entry->hole_follows) { size = entry->hole_size;
hole_start = drm_mm_hole_node_start(entry); if (size) {
hole_end = drm_mm_hole_node_end(entry); start = drm_mm_hole_node_start(entry);
hole_size = hole_end - hole_start; drm_printf(p, "%#018llx-%#018llx: %llu: free\n",
drm_printf(p, "%#018llx-%#018llx: %llu: free\n", hole_start, start, start + size, size);
hole_end, hole_size);
return hole_size;
} }
return 0; return size;
} }
/** /**
* drm_mm_print - print allocator state * drm_mm_print - print allocator state
* @mm: drm_mm allocator to print * @mm: drm_mm allocator to print
......
...@@ -1481,12 +1481,8 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev, ...@@ -1481,12 +1481,8 @@ drm_mode_create_from_cmdline_mode(struct drm_device *dev,
mode->type |= DRM_MODE_TYPE_USERDEF; mode->type |= DRM_MODE_TYPE_USERDEF;
/* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */ /* fix up 1368x768: GFT/CVT can't express 1366 width due to alignment */
if (cmd->xres == 1366 && mode->hdisplay == 1368) { if (cmd->xres == 1366)
mode->hdisplay = 1366; drm_mode_fixup_1366x768(mode);
mode->hsync_start--;
mode->hsync_end--;
drm_mode_set_name(mode);
}
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V); drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
return mode; return mode;
} }
......
...@@ -212,8 +212,7 @@ int drm_vma_offset_add(struct drm_vma_offset_manager *mgr, ...@@ -212,8 +212,7 @@ int drm_vma_offset_add(struct drm_vma_offset_manager *mgr,
goto out_unlock; goto out_unlock;
} }
ret = drm_mm_insert_node(&mgr->vm_addr_space_mm, &node->vm_node, ret = drm_mm_insert_node(&mgr->vm_addr_space_mm, &node->vm_node, pages);
pages, 0, DRM_MM_SEARCH_DEFAULT);
if (ret) if (ret)
goto out_unlock; goto out_unlock;
......
etnaviv-y := \ etnaviv-y := \
etnaviv_buffer.o \ etnaviv_buffer.o \
etnaviv_cmd_parser.o \ etnaviv_cmd_parser.o \
etnaviv_cmdbuf.o \
etnaviv_drv.o \ etnaviv_drv.o \
etnaviv_dump.o \ etnaviv_dump.o \
etnaviv_gem_prime.o \ etnaviv_gem_prime.o \
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
* this program. If not, see <http://www.gnu.org/licenses/>. * this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include "etnaviv_cmdbuf.h"
#include "etnaviv_gpu.h" #include "etnaviv_gpu.h"
#include "etnaviv_gem.h" #include "etnaviv_gem.h"
#include "etnaviv_mmu.h" #include "etnaviv_mmu.h"
...@@ -125,7 +126,7 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, ...@@ -125,7 +126,7 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu,
u32 *ptr = buf->vaddr + off; u32 *ptr = buf->vaddr + off;
dev_info(gpu->dev, "virt %p phys 0x%08x free 0x%08x\n", dev_info(gpu->dev, "virt %p phys 0x%08x free 0x%08x\n",
ptr, etnaviv_iommu_get_cmdbuf_va(gpu, buf) + off, size - len * 4 - off); ptr, etnaviv_cmdbuf_get_va(buf) + off, size - len * 4 - off);
print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
ptr, len * 4, 0); ptr, len * 4, 0);
...@@ -158,7 +159,7 @@ static u32 etnaviv_buffer_reserve(struct etnaviv_gpu *gpu, ...@@ -158,7 +159,7 @@ static u32 etnaviv_buffer_reserve(struct etnaviv_gpu *gpu,
if (buffer->user_size + cmd_dwords * sizeof(u64) > buffer->size) if (buffer->user_size + cmd_dwords * sizeof(u64) > buffer->size)
buffer->user_size = 0; buffer->user_size = 0;
return etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + buffer->user_size; return etnaviv_cmdbuf_get_va(buffer) + buffer->user_size;
} }
u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu) u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
...@@ -169,7 +170,7 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu) ...@@ -169,7 +170,7 @@ u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu)
buffer->user_size = 0; buffer->user_size = 0;
CMD_WAIT(buffer); CMD_WAIT(buffer);
CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
buffer->user_size - 4); buffer->user_size - 4);
return buffer->user_size / 8; return buffer->user_size / 8;
...@@ -261,7 +262,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, ...@@ -261,7 +262,7 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
if (drm_debug & DRM_UT_DRIVER) if (drm_debug & DRM_UT_DRIVER)
etnaviv_buffer_dump(gpu, buffer, 0, 0x50); etnaviv_buffer_dump(gpu, buffer, 0, 0x50);
link_target = etnaviv_iommu_get_cmdbuf_va(gpu, cmdbuf); link_target = etnaviv_cmdbuf_get_va(cmdbuf);
link_dwords = cmdbuf->size / 8; link_dwords = cmdbuf->size / 8;
/* /*
...@@ -355,12 +356,13 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, ...@@ -355,12 +356,13 @@ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event,
CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) |
VIVS_GL_EVENT_FROM_PE); VIVS_GL_EVENT_FROM_PE);
CMD_WAIT(buffer); CMD_WAIT(buffer);
CMD_LINK(buffer, 2, etnaviv_iommu_get_cmdbuf_va(gpu, buffer) + CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) +
buffer->user_size - 4); buffer->user_size - 4);
if (drm_debug & DRM_UT_DRIVER) if (drm_debug & DRM_UT_DRIVER)
pr_info("stream link to 0x%08x @ 0x%08x %p\n", pr_info("stream link to 0x%08x @ 0x%08x %p\n",
return_target, etnaviv_iommu_get_cmdbuf_va(gpu, cmdbuf), cmdbuf->vaddr); return_target, etnaviv_cmdbuf_get_va(cmdbuf),
cmdbuf->vaddr);
if (drm_debug & DRM_UT_DRIVER) { if (drm_debug & DRM_UT_DRIVER) {
print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4, print_hex_dump(KERN_INFO, "cmd ", DUMP_PREFIX_OFFSET, 16, 4,
......
...@@ -56,6 +56,8 @@ static const struct { ...@@ -56,6 +56,8 @@ static const struct {
ST(0x0644, 1), ST(0x0644, 1),
ST(0x064c, 1), ST(0x064c, 1),
ST(0x0680, 8), ST(0x0680, 8),
ST(0x086c, 1),
ST(0x1028, 1),
ST(0x1410, 1), ST(0x1410, 1),
ST(0x1430, 1), ST(0x1430, 1),
ST(0x1458, 1), ST(0x1458, 1),
...@@ -73,8 +75,12 @@ static const struct { ...@@ -73,8 +75,12 @@ static const struct {
ST(0x16c0, 8), ST(0x16c0, 8),
ST(0x16e0, 8), ST(0x16e0, 8),
ST(0x1740, 8), ST(0x1740, 8),
ST(0x17c0, 8),
ST(0x17e0, 8),
ST(0x2400, 14 * 16), ST(0x2400, 14 * 16),
ST(0x10800, 32 * 16), ST(0x10800, 32 * 16),
ST(0x14600, 16),
ST(0x14800, 8 * 8),
#undef ST #undef ST
}; };
......
/*
* Copyright (C) 2017 Etnaviv Project
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <drm/drm_mm.h>
#include "etnaviv_cmdbuf.h"
#include "etnaviv_gpu.h"
#include "etnaviv_mmu.h"
#define SUBALLOC_SIZE SZ_256K
#define SUBALLOC_GRANULE SZ_4K
#define SUBALLOC_GRANULES (SUBALLOC_SIZE / SUBALLOC_GRANULE)
struct etnaviv_cmdbuf_suballoc {
/* suballocated dma buffer properties */
struct etnaviv_gpu *gpu;
void *vaddr;
dma_addr_t paddr;
/* GPU mapping */
u32 iova;
struct drm_mm_node vram_node; /* only used on MMUv2 */
/* allocation management */
struct mutex lock;
DECLARE_BITMAP(granule_map, SUBALLOC_GRANULES);
int free_space;
wait_queue_head_t free_event;
};
struct etnaviv_cmdbuf_suballoc *
etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu)
{
struct etnaviv_cmdbuf_suballoc *suballoc;
int ret;
suballoc = kzalloc(sizeof(*suballoc), GFP_KERNEL);
if (!suballoc)
return ERR_PTR(-ENOMEM);
suballoc->gpu = gpu;
mutex_init(&suballoc->lock);
init_waitqueue_head(&suballoc->free_event);
suballoc->vaddr = dma_alloc_wc(gpu->dev, SUBALLOC_SIZE,
&suballoc->paddr, GFP_KERNEL);
if (!suballoc->vaddr)
goto free_suballoc;
ret = etnaviv_iommu_get_suballoc_va(gpu, suballoc->paddr,
&suballoc->vram_node, SUBALLOC_SIZE,
&suballoc->iova);
if (ret)
goto free_dma;
return suballoc;
free_dma:
dma_free_wc(gpu->dev, SUBALLOC_SIZE, suballoc->vaddr, suballoc->paddr);
free_suballoc:
kfree(suballoc);
return NULL;
}
void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc)
{
etnaviv_iommu_put_suballoc_va(suballoc->gpu, &suballoc->vram_node,
SUBALLOC_SIZE, suballoc->iova);
dma_free_wc(suballoc->gpu->dev, SUBALLOC_SIZE, suballoc->vaddr,
suballoc->paddr);
kfree(suballoc);
}
struct etnaviv_cmdbuf *
etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
size_t nr_bos)
{
struct etnaviv_cmdbuf *cmdbuf;
size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]),
sizeof(*cmdbuf));
int granule_offs, order, ret;
cmdbuf = kzalloc(sz, GFP_KERNEL);
if (!cmdbuf)
return NULL;
cmdbuf->suballoc = suballoc;
cmdbuf->size = size;
order = order_base_2(ALIGN(size, SUBALLOC_GRANULE) / SUBALLOC_GRANULE);
retry:
mutex_lock(&suballoc->lock);
granule_offs = bitmap_find_free_region(suballoc->granule_map,
SUBALLOC_GRANULES, order);
if (granule_offs < 0) {
suballoc->free_space = 0;
mutex_unlock(&suballoc->lock);
ret = wait_event_interruptible_timeout(suballoc->free_event,
suballoc->free_space,
msecs_to_jiffies(10 * 1000));
if (!ret) {
dev_err(suballoc->gpu->dev,
"Timeout waiting for cmdbuf space\n");
return NULL;
}
goto retry;
}
mutex_unlock(&suballoc->lock);
cmdbuf->suballoc_offset = granule_offs * SUBALLOC_GRANULE;
cmdbuf->vaddr = suballoc->vaddr + cmdbuf->suballoc_offset;
return cmdbuf;
}
void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf)
{
struct etnaviv_cmdbuf_suballoc *suballoc = cmdbuf->suballoc;
int order = order_base_2(ALIGN(cmdbuf->size, SUBALLOC_GRANULE) /
SUBALLOC_GRANULE);
mutex_lock(&suballoc->lock);
bitmap_release_region(suballoc->granule_map,
cmdbuf->suballoc_offset / SUBALLOC_GRANULE,
order);
suballoc->free_space = 1;
mutex_unlock(&suballoc->lock);
wake_up_all(&suballoc->free_event);
kfree(cmdbuf);
}
u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf)
{
return buf->suballoc->iova + buf->suballoc_offset;
}
dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf)
{
return buf->suballoc->paddr + buf->suballoc_offset;
}
/*
* Copyright (C) 2017 Etnaviv Project
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __ETNAVIV_CMDBUF_H__
#define __ETNAVIV_CMDBUF_H__
#include <linux/types.h>
struct etnaviv_gpu;
struct etnaviv_cmdbuf_suballoc;
struct etnaviv_cmdbuf {
/* suballocator this cmdbuf is allocated from */
struct etnaviv_cmdbuf_suballoc *suballoc;
/* user context key, must be unique between all active users */
struct etnaviv_file_private *ctx;
/* cmdbuf properties */
int suballoc_offset;
void *vaddr;
u32 size;
u32 user_size;
/* fence after which this buffer is to be disposed */
struct dma_fence *fence;
/* target exec state */
u32 exec_state;
/* per GPU in-flight list */
struct list_head node;
/* BOs attached to this command buffer */
unsigned int nr_bos;
struct etnaviv_vram_mapping *bo_map[0];
};
struct etnaviv_cmdbuf_suballoc *
etnaviv_cmdbuf_suballoc_new(struct etnaviv_gpu * gpu);
void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc);
struct etnaviv_cmdbuf *
etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size,
size_t nr_bos);
void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf);
u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf);
dma_addr_t etnaviv_cmdbuf_get_pa(struct etnaviv_cmdbuf *buf);
#endif /* __ETNAVIV_CMDBUF_H__ */
...@@ -18,11 +18,11 @@ ...@@ -18,11 +18,11 @@
#include <linux/of_platform.h> #include <linux/of_platform.h>
#include <drm/drm_of.h> #include <drm/drm_of.h>
#include "etnaviv_cmdbuf.h"
#include "etnaviv_drv.h" #include "etnaviv_drv.h"
#include "etnaviv_gpu.h" #include "etnaviv_gpu.h"
#include "etnaviv_gem.h" #include "etnaviv_gem.h"
#include "etnaviv_mmu.h" #include "etnaviv_mmu.h"
#include "etnaviv_gem.h"
#ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING #ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING
static bool reglog; static bool reglog;
...@@ -177,7 +177,8 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m) ...@@ -177,7 +177,8 @@ static void etnaviv_buffer_dump(struct etnaviv_gpu *gpu, struct seq_file *m)
u32 i; u32 i;
seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n", seq_printf(m, "virt %p - phys 0x%llx - free 0x%08x\n",
buf->vaddr, (u64)buf->paddr, size - buf->user_size); buf->vaddr, (u64)etnaviv_cmdbuf_get_pa(buf),
size - buf->user_size);
for (i = 0; i < size / 4; i++) { for (i = 0; i < size / 4; i++) {
if (i && !(i % 4)) if (i && !(i % 4))
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
#include <linux/devcoredump.h> #include <linux/devcoredump.h>
#include "etnaviv_cmdbuf.h"
#include "etnaviv_dump.h" #include "etnaviv_dump.h"
#include "etnaviv_gem.h" #include "etnaviv_gem.h"
#include "etnaviv_gpu.h" #include "etnaviv_gpu.h"
...@@ -177,12 +178,11 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu) ...@@ -177,12 +178,11 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu)
etnaviv_core_dump_mmu(&iter, gpu, mmu_size); etnaviv_core_dump_mmu(&iter, gpu, mmu_size);
etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer->vaddr, etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer->vaddr,
gpu->buffer->size, gpu->buffer->size,
etnaviv_iommu_get_cmdbuf_va(gpu, gpu->buffer)); etnaviv_cmdbuf_get_va(gpu->buffer));
list_for_each_entry(cmd, &gpu->active_cmd_list, node) list_for_each_entry(cmd, &gpu->active_cmd_list, node)
etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, cmd->vaddr, etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, cmd->vaddr,
cmd->size, cmd->size, etnaviv_cmdbuf_get_va(cmd));
etnaviv_iommu_get_cmdbuf_va(gpu, cmd));
/* Reserve space for the bomap */ /* Reserve space for the bomap */
if (n_bomap_pages) { if (n_bomap_pages) {
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
*/ */
#include <linux/reservation.h> #include <linux/reservation.h>
#include "etnaviv_cmdbuf.h"
#include "etnaviv_drv.h" #include "etnaviv_drv.h"
#include "etnaviv_gpu.h" #include "etnaviv_gpu.h"
#include "etnaviv_gem.h" #include "etnaviv_gem.h"
...@@ -332,8 +333,9 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, ...@@ -332,8 +333,9 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
bos = drm_malloc_ab(args->nr_bos, sizeof(*bos)); bos = drm_malloc_ab(args->nr_bos, sizeof(*bos));
relocs = drm_malloc_ab(args->nr_relocs, sizeof(*relocs)); relocs = drm_malloc_ab(args->nr_relocs, sizeof(*relocs));
stream = drm_malloc_ab(1, args->stream_size); stream = drm_malloc_ab(1, args->stream_size);
cmdbuf = etnaviv_gpu_cmdbuf_new(gpu, ALIGN(args->stream_size, 8) + 8, cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc,
args->nr_bos); ALIGN(args->stream_size, 8) + 8,
args->nr_bos);
if (!bos || !relocs || !stream || !cmdbuf) { if (!bos || !relocs || !stream || !cmdbuf) {
ret = -ENOMEM; ret = -ENOMEM;
goto err_submit_cmds; goto err_submit_cmds;
...@@ -422,7 +424,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, ...@@ -422,7 +424,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
err_submit_cmds: err_submit_cmds:
/* if we still own the cmdbuf */ /* if we still own the cmdbuf */
if (cmdbuf) if (cmdbuf)
etnaviv_gpu_cmdbuf_free(cmdbuf); etnaviv_cmdbuf_free(cmdbuf);
if (stream) if (stream)
drm_free_large(stream); drm_free_large(stream);
if (bos) if (bos)
......
...@@ -184,7 +184,7 @@ static void etnaviv_iommuv1_dump(struct iommu_domain *domain, void *buf) ...@@ -184,7 +184,7 @@ static void etnaviv_iommuv1_dump(struct iommu_domain *domain, void *buf)
memcpy(buf, etnaviv_domain->pgtable.pgtable, PT_SIZE); memcpy(buf, etnaviv_domain->pgtable.pgtable, PT_SIZE);
} }
static struct etnaviv_iommu_ops etnaviv_iommu_ops = { static const struct etnaviv_iommu_ops etnaviv_iommu_ops = {
.ops = { .ops = {
.domain_free = etnaviv_domain_free, .domain_free = etnaviv_domain_free,
.map = etnaviv_iommuv1_map, .map = etnaviv_iommuv1_map,
......
...@@ -125,10 +125,8 @@ static struct fimd_driver_data exynos3_fimd_driver_data = { ...@@ -125,10 +125,8 @@ static struct fimd_driver_data exynos3_fimd_driver_data = {
.timing_base = 0x20000, .timing_base = 0x20000,
.lcdblk_offset = 0x210, .lcdblk_offset = 0x210,
.lcdblk_bypass_shift = 1, .lcdblk_bypass_shift = 1,
.trg_type = I80_HW_TRG,
.has_shadowcon = 1, .has_shadowcon = 1,
.has_vidoutcon = 1, .has_vidoutcon = 1,
.has_trigger_per_te = 1,
}; };
static struct fimd_driver_data exynos4_fimd_driver_data = { static struct fimd_driver_data exynos4_fimd_driver_data = {
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册