diff options
Diffstat (limited to 'drivers/gpu')
259 files changed, 8176 insertions, 9429 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c index 7a5e8a7b4a1b..28ec5f8ac1c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.c @@ -395,11 +395,11 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, unsigned long pages_per_block; int r; - lpfn = place->lpfn << PAGE_SHIFT; + lpfn = (u64)place->lpfn << PAGE_SHIFT; if (!lpfn) lpfn = man->size; - fpfn = place->fpfn << PAGE_SHIFT; + fpfn = (u64)place->fpfn << PAGE_SHIFT; max_bytes = adev->gmc.mc_vram_size; if (tbo->type != ttm_bo_type_kernel) @@ -439,12 +439,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, /* Allocate blocks in desired range */ vres->flags |= DRM_BUDDY_RANGE_ALLOCATION; - remaining_size = vres->base.num_pages << PAGE_SHIFT; + remaining_size = (u64)vres->base.num_pages << PAGE_SHIFT; mutex_lock(&mgr->lock); while (remaining_size) { if (tbo->page_alignment) - min_block_size = tbo->page_alignment << PAGE_SHIFT; + min_block_size = (u64)tbo->page_alignment << PAGE_SHIFT; else min_block_size = mgr->default_page_size; @@ -453,12 +453,12 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, /* Limit maximum size to 2GiB due to SG table limitations */ size = min(remaining_size, 2ULL << 30); - if (size >= pages_per_block << PAGE_SHIFT) - min_block_size = pages_per_block << PAGE_SHIFT; + if (size >= (u64)pages_per_block << PAGE_SHIFT) + min_block_size = (u64)pages_per_block << PAGE_SHIFT; cur_size = size; - if (fpfn + size != place->lpfn << PAGE_SHIFT) { + if (fpfn + size != (u64)place->lpfn << PAGE_SHIFT) { /* * Except for actual range allocation, modify the size and * min_block_size conforming to continuous flag enablement @@ -498,7 +498,7 @@ static int amdgpu_vram_mgr_new(struct ttm_resource_manager *man, LIST_HEAD(temp); trim_list = &vres->blocks; - original_size = vres->base.num_pages << PAGE_SHIFT; + original_size = (u64)vres->base.num_pages << PAGE_SHIFT; /* * If size value is rounded up to min_block_size, trim the last diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h index 4b267bf1c5db..0e04e42cf809 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vram_mgr.h @@ -50,7 +50,7 @@ static inline u64 amdgpu_vram_mgr_block_start(struct drm_buddy_block *block) static inline u64 amdgpu_vram_mgr_block_size(struct drm_buddy_block *block) { - return PAGE_SIZE << drm_buddy_block_order(block); + return (u64)PAGE_SIZE << drm_buddy_block_order(block); } static inline struct amdgpu_vram_mgr_resource * diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig index 96cbc87f7b6b..413d8c6d592f 100644 --- a/drivers/gpu/drm/amd/display/Kconfig +++ b/drivers/gpu/drm/amd/display/Kconfig @@ -6,7 +6,7 @@ config DRM_AMD_DC bool "AMD DC - Enable new display engine" default y select SND_HDA_COMPONENT if SND_HDA_CORE - select DRM_AMD_DC_DCN if (X86 || PPC64) + select DRM_AMD_DC_DCN if (X86 || PPC_LONG_DOUBLE_128) help Choose this option if you want to use the new display engine support for AMDGPU. This adds required support for Vega and diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile index b7c2ae9ddfda..c20331eb62e0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn30/Makefile @@ -30,6 +30,36 @@ DCN30 = dcn30_init.o dcn30_hubbub.o dcn30_hubp.o dcn30_dpp.o dcn30_optc.o \ dcn30_dpp_cm.o dcn30_dwb_cm.o dcn30_cm_common.o dcn30_mmhubbub.o \ dcn30_dio_link_encoder.o dcn30_resource.o + +ifdef CONFIG_X86 +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -msse +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -msse +endif + +ifdef CONFIG_PPC64 +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o := -mhard-float -maltivec +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o := -mhard-float -maltivec +endif + +ifdef CONFIG_CC_IS_GCC +ifeq ($(call cc-ifversion, -lt, 0701, y), y) +IS_OLD_GCC = 1 +endif +endif + +ifdef CONFIG_X86 +ifdef IS_OLD_GCC +# Stack alignment mismatch, proceed with caution. +# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 +# (8B stack alignment). +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -mpreferred-stack-boundary=4 +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -mpreferred-stack-boundary=4 +else +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_resource.o += -msse2 +CFLAGS_$(AMDDALPATH)/dc/dcn30/dcn30_optc.o += -msse2 +endif +endif + AMD_DAL_DCN30 = $(addprefix $(AMDDALPATH)/dc/dcn30/,$(DCN30)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN30) diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index ed25168619fc..dc7d2e5b16c8 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -552,8 +552,7 @@ EXPORT_SYMBOL(drm_release_noglobal); * Since events are used by the KMS API for vblank and page flip completion this * means all modern display drivers must use it. * - * @offset is ignored, DRM events are read like a pipe. Therefore drivers also - * must set the &file_operation.llseek to no_llseek(). Polling support is + * @offset is ignored, DRM events are read like a pipe. Polling support is * provided by drm_poll(). * * This function will only ever read a full event. Therefore userspace must diff --git a/drivers/gpu/drm/drm_gem_ttm_helper.c b/drivers/gpu/drm/drm_gem_ttm_helper.c index d5962a34c01d..e5fc875990c4 100644 --- a/drivers/gpu/drm/drm_gem_ttm_helper.c +++ b/drivers/gpu/drm/drm_gem_ttm_helper.c @@ -64,8 +64,13 @@ int drm_gem_ttm_vmap(struct drm_gem_object *gem, struct iosys_map *map) { struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem); + int ret; + + dma_resv_lock(gem->resv, NULL); + ret = ttm_bo_vmap(bo, map); + dma_resv_unlock(gem->resv); - return ttm_bo_vmap(bo, map); + return ret; } EXPORT_SYMBOL(drm_gem_ttm_vmap); @@ -82,7 +87,9 @@ void drm_gem_ttm_vunmap(struct drm_gem_object *gem, { struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(gem); + dma_resv_lock(gem->resv, NULL); ttm_bo_vunmap(bo, map); + dma_resv_unlock(gem->resv); } EXPORT_SYMBOL(drm_gem_ttm_vunmap); diff --git a/drivers/gpu/drm/drm_panel_orientation_quirks.c b/drivers/gpu/drm/drm_panel_orientation_quirks.c index 7a9eeed239f3..fc1728d46ac2 100644 --- a/drivers/gpu/drm/drm_panel_orientation_quirks.c +++ b/drivers/gpu/drm/drm_panel_orientation_quirks.c @@ -286,6 +286,21 @@ static const struct dmi_system_id orientation_data[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Lenovo YB1-X9"), }, .driver_data = (void *)&lcd1200x1920_rightside_up, + }, { /* Lenovo Yoga Tablet 2 830F / 830L */ + .matches = { + /* + * Note this also matches the Lenovo Yoga Tablet 2 1050F/L + * since that uses the same mainboard. The resolution match + * will limit this to only matching on the 830F/L. Neither has + * any external video outputs so those are not a concern. + */ + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corp."), + DMI_MATCH(DMI_PRODUCT_NAME, "VALLEYVIEW C0 PLATFORM"), + DMI_MATCH(DMI_BOARD_NAME, "BYT-T FFD8"), + /* Partial match on beginning of BIOS version */ + DMI_MATCH(DMI_BIOS_VERSION, "BLADE_21"), + }, + .driver_data = (void *)&lcd1200x1920_rightside_up, }, { /* OneGX1 Pro */ .matches = { DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SYSTEM_MANUFACTURER"), diff --git a/drivers/gpu/drm/i915/gem/i915_gem_create.c b/drivers/gpu/drm/i915/gem/i915_gem_create.c index 5802692ea604..33673fe7ee0a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_create.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_create.c @@ -241,6 +241,7 @@ struct create_ext { struct drm_i915_private *i915; struct intel_memory_region *placements[INTEL_REGION_UNKNOWN]; unsigned int n_placements; + unsigned int placement_mask; unsigned long flags; }; @@ -337,6 +338,7 @@ static int set_placements(struct drm_i915_gem_create_ext_memory_regions *args, for (i = 0; i < args->num_regions; i++) ext_data->placements[i] = placements[i]; + ext_data->placement_mask = mask; return 0; out_dump: @@ -411,7 +413,7 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_object *obj; int ret; - if (args->flags) + if (args->flags & ~I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS) return -EINVAL; ret = i915_user_extensions(u64_to_user_ptr(args->extensions), @@ -427,6 +429,22 @@ i915_gem_create_ext_ioctl(struct drm_device *dev, void *data, ext_data.n_placements = 1; } + if (args->flags & I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS) { + if (ext_data.n_placements == 1) + return -EINVAL; + + /* + * We always need to be able to spill to system memory, if we + * can't place in the mappable part of LMEM. + */ + if (!(ext_data.placement_mask & BIT(INTEL_REGION_SMEM))) + return -EINVAL; + } else { + if (ext_data.n_placements > 1 || + ext_data.placements[0]->type != INTEL_MEMORY_SYSTEM) + ext_data.flags |= I915_BO_ALLOC_GPU_ONLY; + } + obj = __i915_gem_object_create_user_ext(i915, args->size, ext_data.placements, ext_data.n_placements, diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 30fe847c6664..b7b2c14fd9e1 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1951,7 +1951,7 @@ eb_find_first_request_added(struct i915_execbuffer *eb) #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) /* Stage with GFP_KERNEL allocations before we enter the signaling critical path */ -static void eb_capture_stage(struct i915_execbuffer *eb) +static int eb_capture_stage(struct i915_execbuffer *eb) { const unsigned int count = eb->buffer_count; unsigned int i = count, j; @@ -1964,6 +1964,10 @@ static void eb_capture_stage(struct i915_execbuffer *eb) if (!(flags & EXEC_OBJECT_CAPTURE)) continue; + if (i915_gem_context_is_recoverable(eb->gem_context) && + (IS_DGFX(eb->i915) || GRAPHICS_VER_FULL(eb->i915) > IP_VER(12, 0))) + return -EINVAL; + for_each_batch_create_order(eb, j) { struct i915_capture_list *capture; @@ -1976,6 +1980,8 @@ static void eb_capture_stage(struct i915_execbuffer *eb) eb->capture_lists[j] = capture; } } + + return 0; } /* Commit once we're in the critical path */ @@ -2017,8 +2023,9 @@ static void eb_capture_list_clear(struct i915_execbuffer *eb) #else -static void eb_capture_stage(struct i915_execbuffer *eb) +static int eb_capture_stage(struct i915_execbuffer *eb) { + return 0; } static void eb_capture_commit(struct i915_execbuffer *eb) @@ -3410,7 +3417,9 @@ i915_gem_do_execbuffer(struct drm_device *dev, } ww_acquire_done(&eb.ww.ctx); - eb_capture_stage(&eb); + err = eb_capture_stage(&eb); + if (err) + goto err_vma; out_fence = eb_requests_create(&eb, in_fence, out_fence_fd); if (IS_ERR(out_fence)) { diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 06b1b188ce5a..ccec4055fde3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -717,6 +717,32 @@ bool i915_gem_object_placement_possible(struct drm_i915_gem_object *obj, return false; } +/** + * i915_gem_object_needs_ccs_pages - Check whether the object requires extra + * pages when placed in system-memory, in order to save and later restore the + * flat-CCS aux state when the object is moved between local-memory and + * system-memory + * @obj: Pointer to the object + * + * Return: True if the object needs extra ccs pages. False otherwise. + */ +bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj) +{ + bool lmem_placement = false; + int i; + + for (i = 0; i < obj->mm.n_placements; i++) { + /* Compression is not allowed for the objects with smem placement */ + if (obj->mm.placements[i]->type == INTEL_MEMORY_SYSTEM) + return false; + if (!lmem_placement && + obj->mm.placements[i]->type == INTEL_MEMORY_LOCAL) + lmem_placement = true; + } + + return lmem_placement; +} + void i915_gem_init__objects(struct drm_i915_private *i915) { INIT_DELAYED_WORK(&i915->mm.free_work, __i915_gem_free_work); @@ -783,10 +809,31 @@ int i915_gem_object_wait_moving_fence(struct drm_i915_gem_object *obj, intr, MAX_SCHEDULE_TIMEOUT); if (!ret) ret = -ETIME; + else if (ret > 0 && i915_gem_object_has_unknown_state(obj)) + ret = -EIO; return ret < 0 ? ret : 0; } +/** + * i915_gem_object_has_unknown_state - Return true if the object backing pages are + * in an unknown_state. This means that userspace must NEVER be allowed to touch + * the pages, with either the GPU or CPU. + * + * ONLY valid to be called after ensuring that all kernel fences have signalled + * (in particular the fence for moving/clearing the object). + */ +bool i915_gem_object_has_unknown_state(struct drm_i915_gem_object *obj) +{ + /* + * The below barrier pairs with the dma_fence_signal() in + * __memcpy_work(). We should only sample the unknown_state after all + * the kernel fences have signalled. + */ + smp_rmb(); + return obj->mm.unknown_state; +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/huge_gem_object.c" #include "selftests/huge_pages.c" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h index e11d82a9f7c3..6f0a3ce35567 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h @@ -524,6 +524,7 @@ int i915_gem_object_get_moving_fence(struct drm_i915_gem_object *obj, struct dma_fence **fence); int i915_gem_object_wait_moving_fence(struct drm_i915_gem_object *obj, bool intr); +bool i915_gem_object_has_unknown_state(struct drm_i915_gem_object *obj); void i915_gem_object_set_cache_coherency(struct drm_i915_gem_object *obj, unsigned int cache_level); @@ -617,6 +618,8 @@ int i915_gem_object_wait_migration(struct drm_i915_gem_object *obj, bool i915_gem_object_placement_possible(struct drm_i915_gem_object *obj, enum intel_memory_type type); +bool i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj); + int shmem_sg_alloc_table(struct drm_i915_private *i915, struct sg_table *st, size_t size, struct intel_memory_region *mr, struct address_space *mapping, diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index 2c88bdb8ff7c..5cf36a130061 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -548,6 +548,24 @@ struct drm_i915_gem_object { bool ttm_shrinkable; /** + * @unknown_state: Indicate that the object is effectively + * borked. This is write-once and set if we somehow encounter a + * fatal error when moving/clearing the pages, and we are not + * able to fallback to memcpy/memset, like on small-BAR systems. + * The GPU should also be wedged (or in the process) at this + * point. + * + * Only valid to read this after acquiring the dma-resv lock and + * waiting for all DMA_RESV_USAGE_KERNEL fences to be signalled, + * or if we otherwise know that the moving fence has signalled, + * and we are certain the pages underneath are valid for + * immediate access (under normal operation), like just prior to + * binding the object or when setting up the CPU fault handler. + * See i915_gem_object_has_unknown_state(); + */ + bool unknown_state; + + /** * Priority list of potential placements for this object. */ struct intel_memory_region **placements; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c index f46ee16a323a..a4fb577eceb4 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_region.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c @@ -60,6 +60,8 @@ __i915_gem_object_create_region(struct intel_memory_region *mem, if (page_size) default_page_size = page_size; + /* We should be able to fit a page within an sg entry */ + GEM_BUG_ON(overflows_type(default_page_size, u32)); GEM_BUG_ON(!is_power_of_2_u64(default_page_size)); GEM_BUG_ON(default_page_size < PAGE_SIZE); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 4c25d9b2f138..f131dc065f47 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -266,24 +266,6 @@ static const struct i915_refct_sgt_ops tt_rsgt_ops = { .release = i915_ttm_tt_release }; -static inline bool -i915_gem_object_needs_ccs_pages(struct drm_i915_gem_object *obj) -{ - bool lmem_placement = false; - int i; - - for (i = 0; i < obj->mm.n_placements; i++) { - /* Compression is not allowed for the objects with smem placement */ - if (obj->mm.placements[i]->type == INTEL_MEMORY_SYSTEM) - return false; - if (!lmem_placement && - obj->mm.placements[i]->type == INTEL_MEMORY_LOCAL) - lmem_placement = true; - } - - return lmem_placement; -} - static struct ttm_tt *i915_ttm_tt_create(struct ttm_buffer_object *bo, uint32_t page_flags) { @@ -620,10 +602,15 @@ i915_ttm_resource_get_st(struct drm_i915_gem_object *obj, struct ttm_resource *res) { struct ttm_buffer_object *bo = i915_gem_to_ttm(obj); + u32 page_alignment; if (!i915_ttm_gtt_binds_lmem(res)) return i915_ttm_tt_get_st(bo->ttm); + page_alignment = bo->page_alignment << PAGE_SHIFT; + if (!page_alignment) + page_alignment = obj->mm.region->min_page_size; + /* * If CPU mapping differs, we need to add the ttm_tt pages to * the resulting st. Might make sense for GGTT. @@ -634,7 +621,8 @@ i915_ttm_resource_get_st(struct drm_i915_gem_object *obj, struct i915_refct_sgt *rsgt; rsgt = intel_region_ttm_resource_to_rsgt(obj->mm.region, - res); + res, + page_alignment); if (IS_ERR(rsgt)) return rsgt; @@ -643,7 +631,8 @@ i915_ttm_resource_get_st(struct drm_i915_gem_object *obj, return i915_refct_sgt_get(obj->ttm.cached_io_rsgt); } - return intel_region_ttm_resource_to_rsgt(obj->mm.region, res); + return intel_region_ttm_resource_to_rsgt(obj->mm.region, res, + page_alignment); } static int i915_ttm_truncate(struct drm_i915_gem_object *obj) @@ -675,7 +664,15 @@ static void i915_ttm_swap_notify(struct ttm_buffer_object *bo) i915_ttm_purge(obj); } -static bool i915_ttm_resource_mappable(struct ttm_resource *res) +/** + * i915_ttm_resource_mappable - Return true if the ttm resource is CPU + * accessible. + * @res: The TTM resource to check. + * + * This is interesting on small-BAR systems where we may encounter lmem objects + * that can't be accessed via the CPU. + */ +bool i915_ttm_resource_mappable(struct ttm_resource *res) { struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); @@ -687,6 +684,22 @@ static bool i915_ttm_resource_mappable(struct ttm_resource *res) static int i915_ttm_io_mem_reserve(struct ttm_device *bdev, struct ttm_resource *mem) { + struct drm_i915_gem_object *obj = i915_ttm_to_gem(mem->bo); + bool unknown_state; + + if (!obj) + return -EINVAL; + + if (!kref_get_unless_zero(&obj->base.refcount)) + return -EINVAL; + + assert_object_held(obj); + + unknown_state = i915_gem_object_has_unknown_state(obj); + i915_gem_object_put(obj); + if (unknown_state) + return -EINVAL; + if (!i915_ttm_cpu_maps_iomem(mem)) return 0; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h index 73e371aa3850..e4842b4296fc 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h @@ -92,4 +92,7 @@ static inline bool i915_ttm_cpu_maps_iomem(struct ttm_resource *mem) /* Once / if we support GGTT, this is also false for cached ttm_tts */ return mem->mem_type != I915_PL_SYSTEM; } + +bool i915_ttm_resource_mappable(struct ttm_resource *res); + #endif diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c index a10716f4e717..9a7e50534b84 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.c @@ -33,6 +33,7 @@ #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) static bool fail_gpu_migration; static bool fail_work_allocation; +static bool ban_memcpy; void i915_ttm_migrate_set_failure_modes(bool gpu_migration, bool work_allocation) @@ -40,6 +41,11 @@ void i915_ttm_migrate_set_failure_modes(bool gpu_migration, fail_gpu_migration = gpu_migration; fail_work_allocation = work_allocation; } + +void i915_ttm_migrate_set_ban_memcpy(bool ban) +{ + ban_memcpy = ban; +} #endif static enum i915_cache_level @@ -258,15 +264,23 @@ struct i915_ttm_memcpy_arg { * from the callback for lockdep reasons. * @cb: Callback for the accelerated migration fence. * @arg: The argument for the memcpy functionality. + * @i915: The i915 pointer. + * @obj: The GEM object. + * @memcpy_allowed: Instead of processing the @arg, and falling back to memcpy + * or memset, we wedge the device and set the @obj unknown_state, to prevent + * further access to the object with the CPU or GPU. On some devices we might + * only be permitted to use the blitter engine for such operations. */ struct i915_ttm_memcpy_work { struct dma_fence fence; struct work_struct work; - /* The fence lock */ spinlock_t lock; struct irq_work irq_work; struct dma_fence_cb cb; struct i915_ttm_memcpy_arg arg; + struct drm_i915_private *i915; + struct drm_i915_gem_object *obj; + bool memcpy_allowed; }; static void i915_ttm_move_memcpy(struct i915_ttm_memcpy_arg *arg) @@ -317,14 +331,42 @@ static void __memcpy_work(struct work_struct *work) struct i915_ttm_memcpy_work *copy_work = container_of(work, typeof(*copy_work), work); struct i915_ttm_memcpy_arg *arg = ©_work->arg; - bool cookie = dma_fence_begin_signalling(); + bool cookie; + + /* + * FIXME: We need to take a closer look here. We should be able to plonk + * this into the fence critical section. + */ + if (!copy_work->memcpy_allowed) { + struct intel_gt *gt; + unsigned int id; + + for_each_gt(gt, copy_work->i915, id) + intel_gt_set_wedged(gt); + } + + cookie = dma_fence_begin_signalling(); + + if (copy_work->memcpy_allowed) { + i915_ttm_move_memcpy(arg); + } else { + /* + * Prevent further use of the object. Any future GTT binding or + * CPU access is not allowed once we signal the fence. Outside + * of the fence critical section, we then also then wedge the gpu + * to indicate the device is not functional. + * + * The below dma_fence_signal() is our write-memory-barrier. + */ + copy_work->obj->mm.unknown_state = true; + } - i915_ttm_move_memcpy(arg); dma_fence_end_signalling(cookie); dma_fence_signal(©_work->fence); i915_ttm_memcpy_release(arg); + i915_gem_object_put(copy_work->obj); dma_fence_put(©_work->fence); } @@ -336,6 +378,7 @@ static void __memcpy_irq_work(struct irq_work *irq_work) dma_fence_signal(©_work->fence); i915_ttm_memcpy_release(arg); + i915_gem_object_put(copy_work->obj); dma_fence_put(©_work->fence); } @@ -389,6 +432,19 @@ i915_ttm_memcpy_work_arm(struct i915_ttm_memcpy_work *work, return &work->fence; } +static bool i915_ttm_memcpy_allowed(struct ttm_buffer_object *bo, + struct ttm_resource *dst_mem) +{ + if (i915_gem_object_needs_ccs_pages(i915_ttm_to_gem(bo))) + return false; + + if (!(i915_ttm_resource_mappable(bo->resource) && + i915_ttm_resource_mappable(dst_mem))) + return false; + + return I915_SELFTEST_ONLY(ban_memcpy) ? false : true; +} + static struct dma_fence * __i915_ttm_move(struct ttm_buffer_object *bo, const struct ttm_operation_ctx *ctx, bool clear, @@ -396,6 +452,9 @@ __i915_ttm_move(struct ttm_buffer_object *bo, struct i915_refct_sgt *dst_rsgt, bool allow_accel, const struct i915_deps *move_deps) { + const bool memcpy_allowed = i915_ttm_memcpy_allowed(bo, dst_mem); + struct drm_i915_gem_object *obj = i915_ttm_to_gem(bo); + struct drm_i915_private *i915 = to_i915(bo->base.dev); struct i915_ttm_memcpy_work *copy_work = NULL; struct i915_ttm_memcpy_arg _arg, *arg = &_arg; struct dma_fence *fence = ERR_PTR(-EINVAL); @@ -423,9 +482,14 @@ __i915_ttm_move(struct ttm_buffer_object *bo, copy_work = kzalloc(sizeof(*copy_work), GFP_KERNEL); if (copy_work) { + copy_work->i915 = i915; + copy_work->memcpy_allowed = memcpy_allowed; + copy_work->obj = i915_gem_object_get(obj); arg = ©_work->arg; - i915_ttm_memcpy_init(arg, bo, clear, dst_mem, dst_ttm, - dst_rsgt); + if (memcpy_allowed) + i915_ttm_memcpy_init(arg, bo, clear, dst_mem, + dst_ttm, dst_rsgt); + fence = i915_ttm_memcpy_work_arm(copy_work, dep); } else { dma_fence_wait(dep, false); @@ -450,17 +514,23 @@ __i915_ttm_move(struct ttm_buffer_object *bo, } /* Error intercept failed or no accelerated migration to start with */ - if (!copy_work) - i915_ttm_memcpy_init(arg, bo, clear, dst_mem, dst_ttm, - dst_rsgt); - i915_ttm_move_memcpy(arg); - i915_ttm_memcpy_release(arg); + + if (memcpy_allowed) { + if (!copy_work) + i915_ttm_memcpy_init(arg, bo, clear, dst_mem, dst_ttm, + dst_rsgt); + i915_ttm_move_memcpy(arg); + i915_ttm_memcpy_release(arg); + } + if (copy_work) + i915_gem_object_put(copy_work->obj); kfree(copy_work); - return NULL; + return memcpy_allowed ? NULL : ERR_PTR(-EIO); out: if (!fence && copy_work) { i915_ttm_memcpy_release(arg); + i915_gem_object_put(copy_work->obj); kfree(copy_work); } @@ -539,8 +609,11 @@ int i915_ttm_move(struct ttm_buffer_object *bo, bool evict, } if (migration_fence) { - ret = ttm_bo_move_accel_cleanup(bo, migration_fence, evict, - true, dst_mem); + if (I915_SELFTEST_ONLY(evict && fail_gpu_migration)) + ret = -EIO; /* never feed non-migrate fences into ttm */ + else + ret = ttm_bo_move_accel_cleanup(bo, migration_fence, evict, + true, dst_mem); if (ret) { dma_fence_wait(migration_fence, false); ttm_bo_move_sync_cleanup(bo, dst_mem); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h index d2e7f149e05c..8a5d5ab0cc34 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm_move.h @@ -22,6 +22,7 @@ int i915_ttm_move_notify(struct ttm_buffer_object *bo); I915_SELFTEST_DECLARE(void i915_ttm_migrate_set_failure_modes(bool gpu_migration, bool work_allocation)); +I915_SELFTEST_DECLARE(void i915_ttm_migrate_set_ban_memcpy(bool ban)); int i915_gem_obj_copy_ttm(struct drm_i915_gem_object *dst, struct drm_i915_gem_object *src, diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index 319936f91ac5..e6e01c2a74a6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -9,6 +9,7 @@ #include <linux/jiffies.h> #include "gt/intel_engine.h" +#include "gt/intel_rps.h" #include "i915_gem_ioctls.h" #include "i915_gem_object.h" @@ -31,6 +32,37 @@ i915_gem_object_wait_fence(struct dma_fence *fence, timeout); } +static void +i915_gem_object_boost(struct dma_resv *resv, unsigned int flags) +{ + struct dma_resv_iter cursor; + struct dma_fence *fence; + + /* + * Prescan all fences for potential boosting before we begin waiting. + * + * When we wait, we wait on outstanding fences serially. If the + * dma-resv contains a sequence such as 1:1, 1:2 instead of a reduced + * form 1:2, then as we look at each wait in turn we see that each + * request is currently executing and not worthy of boosting. But if + * we only happen to look at the final fence in the sequence (because + * of request coalescing or splitting between read/write arrays by + * the iterator), then we would boost. As such our decision to boost + * or not is delicately balanced on the order we wait on fences. + * + * So instead of looking for boosts sequentially, look for all boosts + * upfront and then wait on the outstanding fences. + */ + + dma_resv_iter_begin(&cursor, resv, + dma_resv_usage_rw(flags & I915_WAIT_ALL)); + dma_resv_for_each_fence_unlocked(&cursor, fence) + if (dma_fence_is_i915(fence) && + !i915_request_started(to_request(fence))) + intel_rps_boost(to_request(fence)); + dma_resv_iter_end(&cursor); +} + static long i915_gem_object_wait_reservation(struct dma_resv *resv, unsigned int flags, @@ -40,6 +72,8 @@ i915_gem_object_wait_reservation(struct dma_resv *resv, struct dma_fence *fence; long ret = timeout ?: 1; + i915_gem_object_boost(resv, flags); + dma_resv_iter_begin(&cursor, resv, dma_resv_usage_rw(flags & I915_WAIT_ALL)); dma_resv_for_each_fence_unlocked(&cursor, fence) { diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index ef15967be51a..72ce2c9f42fd 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -1623,6 +1623,7 @@ static int igt_shrink_thp(void *arg) struct file *file; unsigned int flags = PIN_USER; unsigned int n; + intel_wakeref_t wf; bool should_swap; int err; @@ -1659,9 +1660,11 @@ static int igt_shrink_thp(void *arg) goto out_put; } + wf = intel_runtime_pm_get(&i915->runtime_pm); /* active shrink */ + err = i915_vma_pin(vma, 0, 0, flags); if (err) - goto out_put; + goto out_wf; if (obj->mm.page_sizes.phys < I915_GTT_PAGE_SIZE_2M) { pr_info("failed to allocate THP, finishing test early\n"); @@ -1732,6 +1735,8 @@ static int igt_shrink_thp(void *arg) out_unpin: i915_vma_unpin(vma); +out_wf: + intel_runtime_pm_put(&i915->runtime_pm, wf); out_put: i915_gem_object_put(obj); out_vm: diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c index 801af51aff62..fe6c37fd7859 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c @@ -9,6 +9,7 @@ #include "i915_deps.h" +#include "selftests/igt_reset.h" #include "selftests/igt_spinner.h" static int igt_fill_check_buffer(struct drm_i915_gem_object *obj, @@ -109,7 +110,8 @@ static int igt_same_create_migrate(void *arg) static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww, struct drm_i915_gem_object *obj, - struct i915_vma *vma) + struct i915_vma *vma, + bool silent_migrate) { int err; @@ -138,7 +140,8 @@ static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww, if (i915_gem_object_is_lmem(obj)) { err = i915_gem_object_migrate(obj, ww, INTEL_REGION_SMEM); if (err) { - pr_err("Object failed migration to smem\n"); + if (!silent_migrate) + pr_err("Object failed migration to smem\n"); if (err) return err; } @@ -156,7 +159,8 @@ static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww, } else { err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM_0); if (err) { - pr_err("Object failed migration to lmem\n"); + if (!silent_migrate) + pr_err("Object failed migration to lmem\n"); if (err) return err; } @@ -179,7 +183,8 @@ static int __igt_lmem_pages_migrate(struct intel_gt *gt, struct i915_address_space *vm, struct i915_deps *deps, struct igt_spinner *spin, - struct dma_fence *spin_fence) + struct dma_fence *spin_fence, + bool borked_migrate) { struct drm_i915_private *i915 = gt->i915; struct drm_i915_gem_object *obj; @@ -242,7 +247,8 @@ static int __igt_lmem_pages_migrate(struct intel_gt *gt, */ for (i = 1; i <= 5; ++i) { for_i915_gem_ww(&ww, err, true) - err = lmem_pages_migrate_one(&ww, obj, vma); + err = lmem_pages_migrate_one(&ww, obj, vma, + borked_migrate); if (err) goto out_put; } @@ -283,23 +289,70 @@ out_put: static int igt_lmem_pages_failsafe_migrate(void *arg) { - int fail_gpu, fail_alloc, ret; + int fail_gpu, fail_alloc, ban_memcpy, ret; struct intel_gt *gt = arg; for (fail_gpu = 0; fail_gpu < 2; ++fail_gpu) { for (fail_alloc = 0; fail_alloc < 2; ++fail_alloc) { - pr_info("Simulated failure modes: gpu: %d, alloc: %d\n", - fail_gpu, fail_alloc); - i915_ttm_migrate_set_failure_modes(fail_gpu, - fail_alloc); - ret = __igt_lmem_pages_migrate(gt, NULL, NULL, NULL, NULL); - if (ret) - goto out_err; + for (ban_memcpy = 0; ban_memcpy < 2; ++ban_memcpy) { + pr_info("Simulated failure modes: gpu: %d, alloc:%d, ban_memcpy: %d\n", + fail_gpu, fail_alloc, ban_memcpy); + i915_ttm_migrate_set_ban_memcpy(ban_memcpy); + i915_ttm_migrate_set_failure_modes(fail_gpu, + fail_alloc); + ret = __igt_lmem_pages_migrate(gt, NULL, NULL, + NULL, NULL, + ban_memcpy && + fail_gpu); + + if (ban_memcpy && fail_gpu) { + struct intel_gt *__gt; + unsigned int id; + + if (ret != -EIO) { + pr_err("expected -EIO, got (%d)\n", ret); + ret = -EINVAL; + } else { + ret = 0; + } + + for_each_gt(__gt, gt->i915, id) { + intel_wakeref_t wakeref; + bool wedged; + + mutex_lock(&__gt->reset.mutex); + wedged = test_bit(I915_WEDGED, &__gt->reset.flags); + mutex_unlock(&__gt->reset.mutex); + + if (fail_gpu && !fail_alloc) { + if (!wedged) { + pr_err("gt(%u) not wedged\n", id); + ret = -EINVAL; + continue; + } + } else if (wedged) { + pr_err("gt(%u) incorrectly wedged\n", id); + ret = -EINVAL; + } else { + continue; + } + + wakeref = intel_runtime_pm_get(__gt->uncore->rpm); + igt_global_reset_lock(__gt); + intel_gt_reset(__gt, ALL_ENGINES, NULL); + igt_global_reset_unlock(__gt); + intel_runtime_pm_put(__gt->uncore->rpm, wakeref); + } + if (ret) + goto out_err; + } + } } } out_err: i915_ttm_migrate_set_failure_modes(false, false); + i915_ttm_migrate_set_ban_memcpy(false); return ret; } @@ -370,7 +423,7 @@ static int igt_async_migrate(struct intel_gt *gt) goto out_ce; err = __igt_lmem_pages_migrate(gt, &ppgtt->vm, &deps, &spin, - spin_fence); + spin_fence, false); i915_deps_fini(&deps); dma_fence_put(spin_fence); if (err) @@ -394,23 +447,67 @@ out_spin: #define ASYNC_FAIL_ALLOC 1 static int igt_lmem_async_migrate(void *arg) { - int fail_gpu, fail_alloc, ret; + int fail_gpu, fail_alloc, ban_memcpy, ret; struct intel_gt *gt = arg; for (fail_gpu = 0; fail_gpu < 2; ++fail_gpu) { for (fail_alloc = 0; fail_alloc < ASYNC_FAIL_ALLOC; ++fail_alloc) { - pr_info("Simulated failure modes: gpu: %d, alloc: %d\n", - fail_gpu, fail_alloc); - i915_ttm_migrate_set_failure_modes(fail_gpu, - fail_alloc); - ret = igt_async_migrate(gt); - if (ret) - goto out_err; + for (ban_memcpy = 0; ban_memcpy < 2; ++ban_memcpy) { + pr_info("Simulated failure modes: gpu: %d, alloc: %d, ban_memcpy: %d\n", + fail_gpu, fail_alloc, ban_memcpy); + i915_ttm_migrate_set_ban_memcpy(ban_memcpy); + i915_ttm_migrate_set_failure_modes(fail_gpu, + fail_alloc); + ret = igt_async_migrate(gt); + + if (fail_gpu && ban_memcpy) { + struct intel_gt *__gt; + unsigned int id; + + if (ret != -EIO) { + pr_err("expected -EIO, got (%d)\n", ret); + ret = -EINVAL; + } else { + ret = 0; + } + + for_each_gt(__gt, gt->i915, id) { + intel_wakeref_t wakeref; + bool wedged; + + mutex_lock(&__gt->reset.mutex); + wedged = test_bit(I915_WEDGED, &__gt->reset.flags); + mutex_unlock(&__gt->reset.mutex); + + if (fail_gpu && !fail_alloc) { + if (!wedged) { + pr_err("gt(%u) not wedged\n", id); + ret = -EINVAL; + continue; + } + } else if (wedged) { + pr_err("gt(%u) incorrectly wedged\n", id); + ret = -EINVAL; + } else { + continue; + } + + wakeref = intel_runtime_pm_get(__gt->uncore->rpm); + igt_global_reset_lock(__gt); + intel_gt_reset(__gt, ALL_ENGINES, NULL); + igt_global_reset_unlock(__gt); + intel_runtime_pm_put(__gt->uncore->rpm, wakeref); + } + } + if (ret) + goto out_err; + } } } out_err: i915_ttm_migrate_set_failure_modes(false, false); + i915_ttm_migrate_set_ban_memcpy(false); return ret; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 5bc93a1ce3e3..3ced9948a331 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -10,6 +10,7 @@ #include "gem/i915_gem_internal.h" #include "gem/i915_gem_region.h" #include "gem/i915_gem_ttm.h" +#include "gem/i915_gem_ttm_move.h" #include "gt/intel_engine_pm.h" #include "gt/intel_gpu_commands.h" #include "gt/intel_gt.h" @@ -21,6 +22,7 @@ #include "i915_selftest.h" #include "selftests/i915_random.h" #include "selftests/igt_flush_test.h" +#include "selftests/igt_reset.h" #include "selftests/igt_mmap.h" struct tile { @@ -979,6 +981,9 @@ static int igt_mmap(void *arg) }; int i; + if (mr->private) + continue; + for (i = 0; i < ARRAY_SIZE(sizes); i++) { struct drm_i915_gem_object *obj; int err; @@ -1160,6 +1165,7 @@ out_unmap: #define IGT_MMAP_MIGRATE_FILL (1 << 1) #define IGT_MMAP_MIGRATE_EVICTABLE (1 << 2) #define IGT_MMAP_MIGRATE_UNFAULTABLE (1 << 3) +#define IGT_MMAP_MIGRATE_FAIL_GPU (1 << 4) static int __igt_mmap_migrate(struct intel_memory_region **placements, int n_placements, struct intel_memory_region *expected_mr, @@ -1221,8 +1227,10 @@ static int __igt_mmap_migrate(struct intel_memory_region **placements, expand32(POISON_INUSE), &rq); i915_gem_object_unpin_pages(obj); if (rq) { - dma_resv_add_fence(obj->base.resv, &rq->fence, - DMA_RESV_USAGE_KERNEL); + err = dma_resv_reserve_fences(obj->base.resv, 1); + if (!err) + dma_resv_add_fence(obj->base.resv, &rq->fence, + DMA_RESV_USAGE_KERNEL); i915_request_put(rq); } i915_gem_object_unlock(obj); @@ -1232,13 +1240,62 @@ static int __igt_mmap_migrate(struct intel_memory_region **placements, if (flags & IGT_MMAP_MIGRATE_EVICTABLE) igt_make_evictable(&objects); + if (flags & IGT_MMAP_MIGRATE_FAIL_GPU) { + err = i915_gem_object_lock(obj, NULL); + if (err) + goto out_put; + + /* + * Ensure we only simulate the gpu failuire when faulting the + * pages. + */ + err = i915_gem_object_wait_moving_fence(obj, true); + i915_gem_object_unlock(obj); + if (err) + goto out_put; + i915_ttm_migrate_set_failure_modes(true, false); + } + err = ___igt_mmap_migrate(i915, obj, addr, flags & IGT_MMAP_MIGRATE_UNFAULTABLE); + if (!err && obj->mm.region != expected_mr) { pr_err("%s region mismatch %s\n", __func__, expected_mr->name); err = -EINVAL; } + if (flags & IGT_MMAP_MIGRATE_FAIL_GPU) { + struct intel_gt *gt; + unsigned int id; + + i915_ttm_migrate_set_failure_modes(false, false); + + for_each_gt(gt, i915, id) { + intel_wakeref_t wakeref; + bool wedged; + + mutex_lock(>->reset.mutex); + wedged = test_bit(I915_WEDGED, >->reset.flags); + mutex_unlock(>->reset.mutex); + if (!wedged) { + pr_err("gt(%u) not wedged\n", id); + err = -EINVAL; + continue; + } + + wakeref = intel_runtime_pm_get(gt->uncore->rpm); + igt_global_reset_lock(gt); + intel_gt_reset(gt, ALL_ENGINES, NULL); + igt_global_reset_unlock(gt); + intel_runtime_pm_put(gt->uncore->rpm, wakeref); + } + + if (!i915_gem_object_has_unknown_state(obj)) { + pr_err("object missing unknown_state\n"); + err = -EINVAL; + } + } + out_put: i915_gem_object_put(obj); igt_close_objects(i915, &objects); @@ -1319,6 +1376,23 @@ static int igt_mmap_migrate(void *arg) IGT_MMAP_MIGRATE_TOPDOWN | IGT_MMAP_MIGRATE_FILL | IGT_MMAP_MIGRATE_UNFAULTABLE); + if (err) + goto out_io_size; + + /* + * Allocate in the non-mappable portion, but force migrating to + * the mappable portion on fault (LMEM -> LMEM). We then also + * simulate a gpu error when moving the pages when faulting the + * pages, which should result in wedging the gpu and returning + * SIGBUS in the fault handler, since we can't fallback to + * memcpy. + */ + err = __igt_mmap_migrate(single, ARRAY_SIZE(single), mr, + IGT_MMAP_MIGRATE_TOPDOWN | + IGT_MMAP_MIGRATE_FILL | + IGT_MMAP_MIGRATE_EVICTABLE | + IGT_MMAP_MIGRATE_FAIL_GPU | + IGT_MMAP_MIGRATE_UNFAULTABLE); out_io_size: mr->io_size = saved_io_size; i915_ttm_buddy_man_force_visible_size(man, @@ -1435,6 +1509,9 @@ static int igt_mmap_access(void *arg) struct drm_i915_gem_object *obj; int err; + if (mr->private) + continue; + obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1); if (obj == ERR_PTR(-ENODEV)) continue; @@ -1580,6 +1657,9 @@ static int igt_mmap_gpu(void *arg) struct drm_i915_gem_object *obj; int err; + if (mr->private) + continue; + obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1); if (obj == ERR_PTR(-ENODEV)) continue; @@ -1727,6 +1807,9 @@ static int igt_mmap_revoke(void *arg) struct drm_i915_gem_object *obj; int err; + if (mr->private) + continue; + obj = __i915_gem_object_create_user(i915, PAGE_SIZE, &mr, 1); if (obj == ERR_PTR(-ENODEV)) continue; diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 9dc9dccf7b09..ecc990ec1b95 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -399,7 +399,8 @@ static void insert_breadcrumb(struct i915_request *rq) * the request as it may have completed and raised the interrupt as * we were attaching it into the lists. */ - irq_work_queue(&b->irq_work); + if (!b->irq_armed || __i915_request_is_complete(rq)) + irq_work_queue(&b->irq_work); } bool i915_request_enable_breadcrumb(struct i915_request *rq) diff --git a/drivers/gpu/drm/i915/gt/intel_context_types.h b/drivers/gpu/drm/i915/gt/intel_context_types.h index d2d75d9c0c8d..04eacae1aca5 100644 --- a/drivers/gpu/drm/i915/gt/intel_context_types.h +++ b/drivers/gpu/drm/i915/gt/intel_context_types.h @@ -275,10 +275,17 @@ struct intel_context { u8 child_index; /** @guc: GuC specific members for parallel submission */ struct { - /** @wqi_head: head pointer in work queue */ + /** @wqi_head: cached head pointer in work queue */ u16 wqi_head; - /** @wqi_tail: tail pointer in work queue */ + /** @wqi_tail: cached tail pointer in work queue */ u16 wqi_tail; + /** @wq_head: pointer to the actual head in work queue */ + u32 *wq_head; + /** @wq_tail: pointer to the actual head in work queue */ + u32 *wq_tail; + /** @wq_status: pointer to the status in work queue */ + u32 *wq_status; + /** * @parent_page: page in context state (ce->state) used * by parent for work queue, process descriptor diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 283870c65991..37fa813af766 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1517,7 +1517,6 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine, struct intel_instdone *instdone) { struct drm_i915_private *i915 = engine->i915; - const struct sseu_dev_info *sseu = &engine->gt->info.sseu; struct intel_uncore *uncore = engine->uncore; u32 mmio_base = engine->mmio_base; int slice; @@ -1542,32 +1541,19 @@ void intel_engine_get_instdone(const struct intel_engine_cs *engine, intel_uncore_read(uncore, GEN12_SC_INSTDONE_EXTRA2); } - if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { - for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { - instdone->sampler[slice][subslice] = - intel_gt_mcr_read(engine->gt, - GEN7_SAMPLER_INSTDONE, - slice, subslice); - instdone->row[slice][subslice] = - intel_gt_mcr_read(engine->gt, - GEN7_ROW_INSTDONE, - slice, subslice); - } - } else { - for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { - instdone->sampler[slice][subslice] = - intel_gt_mcr_read(engine->gt, - GEN7_SAMPLER_INSTDONE, - slice, subslice); - instdone->row[slice][subslice] = - intel_gt_mcr_read(engine->gt, - GEN7_ROW_INSTDONE, - slice, subslice); - } + for_each_ss_steering(iter, engine->gt, slice, subslice) { + instdone->sampler[slice][subslice] = + intel_gt_mcr_read(engine->gt, + GEN7_SAMPLER_INSTDONE, + slice, subslice); + instdone->row[slice][subslice] = + intel_gt_mcr_read(engine->gt, + GEN7_ROW_INSTDONE, + slice, subslice); } if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 55)) { - for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) + for_each_ss_steering(iter, engine->gt, slice, subslice) instdone->geom_svg[slice][subslice] = intel_gt_mcr_read(engine->gt, XEHPG_INSTDONE_GEOM_SVG, diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 2286f96f5f87..633a7e5dba3b 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -647,26 +647,4 @@ intel_engine_uses_wa_hold_ccs_switchout(struct intel_engine_cs *engine) return engine->flags & I915_ENGINE_USES_WA_HOLD_CCS_SWITCHOUT; } -#define instdone_has_slice(dev_priv___, sseu___, slice___) \ - ((GRAPHICS_VER(dev_priv___) == 7 ? 1 : ((sseu___)->slice_mask)) & BIT(slice___)) - -#define instdone_has_subslice(dev_priv__, sseu__, slice__, subslice__) \ - (GRAPHICS_VER(dev_priv__) == 7 ? (1 & BIT(subslice__)) : \ - intel_sseu_has_subslice(sseu__, 0, subslice__)) - -#define for_each_instdone_slice_subslice(dev_priv_, sseu_, slice_, subslice_) \ - for ((slice_) = 0, (subslice_) = 0; (slice_) < I915_MAX_SLICES; \ - (subslice_) = ((subslice_) + 1) % I915_MAX_SUBSLICES, \ - (slice_) += ((subslice_) == 0)) \ - for_each_if((instdone_has_slice(dev_priv_, sseu_, slice_)) && \ - (instdone_has_subslice(dev_priv_, sseu_, slice_, \ - subslice_))) - -#define for_each_instdone_gslice_dss_xehp(dev_priv_, sseu_, iter_, gslice_, dss_) \ - for ((iter_) = 0, (gslice_) = 0, (dss_) = 0; \ - (iter_) < GEN_SS_MASK_SIZE; \ - (iter_)++, (gslice_) = (iter_) / GEN_DSS_PER_GSLICE, \ - (dss_) = (iter_) % GEN_DSS_PER_GSLICE) \ - for_each_if(intel_sseu_has_subslice((sseu_), 0, (iter_))) - #endif /* __INTEL_ENGINE_TYPES_H__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 8da3314bb6bf..68c2b0d8f187 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -952,6 +952,20 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) mutex_lock(>->tlb_invalidate_lock); intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL); + spin_lock_irq(&uncore->lock); /* serialise invalidate with GT reset */ + + for_each_engine(engine, gt, id) { + struct reg_and_bit rb; + + rb = get_reg_and_bit(engine, regs == gen8_regs, regs, num); + if (!i915_mmio_reg_offset(rb.reg)) + continue; + + intel_uncore_write_fw(uncore, rb.reg, rb.bit); + } + + spin_unlock_irq(&uncore->lock); + for_each_engine(engine, gt, id) { /* * HW architecture suggest typical invalidation time at 40us, @@ -966,7 +980,6 @@ void intel_gt_invalidate_tlbs(struct intel_gt *gt) if (!i915_mmio_reg_offset(rb.reg)) continue; - intel_uncore_write_fw(uncore, rb.reg, rb.bit); if (__intel_wait_for_register_fw(uncore, rb.reg, rb.bit, 0, timeout_us, timeout_ms, diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c index 777025d5bd66..e79405a45312 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.c @@ -495,3 +495,28 @@ void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt, } } +/** + * intel_gt_mcr_get_ss_steering - returns the group/instance steering for a SS + * @gt: GT structure + * @dss: DSS ID to obtain steering for + * @group: pointer to storage for steering group ID + * @instance: pointer to storage for steering instance ID + * + * Returns the steering IDs (via the @group and @instance parameters) that + * correspond to a specific subslice/DSS ID. + */ +void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss, + unsigned int *group, unsigned int *instance) +{ + if (IS_PONTEVECCHIO(gt->i915)) { + *group = dss / GEN_DSS_PER_CSLICE; + *instance = dss % GEN_DSS_PER_CSLICE; + } else if (GRAPHICS_VER_FULL(gt->i915) >= IP_VER(12, 50)) { + *group = dss / GEN_DSS_PER_GSLICE; + *instance = dss % GEN_DSS_PER_GSLICE; + } else { + *group = dss / GEN_MAX_SS_PER_HSW_SLICE; + *instance = dss % GEN_MAX_SS_PER_HSW_SLICE; + return; + } +} diff --git a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h index 506b0cbc8db3..77a8b11c287d 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_mcr.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_mcr.h @@ -31,4 +31,28 @@ void intel_gt_mcr_get_nonterminated_steering(struct intel_gt *gt, void intel_gt_mcr_report_steering(struct drm_printer *p, struct intel_gt *gt, bool dump_table); +void intel_gt_mcr_get_ss_steering(struct intel_gt *gt, unsigned int dss, + unsigned int *group, unsigned int *instance); + +/* + * Helper for for_each_ss_steering loop. On pre-Xe_HP platforms, subslice + * presence is determined by using the group/instance as direct lookups in the + * slice/subslice topology. On Xe_HP and beyond, the steering is unrelated to + * the topology, so we lookup the DSS ID directly in "slice 0." + */ +#define _HAS_SS(ss_, gt_, group_, instance_) ( \ + GRAPHICS_VER_FULL(gt_->i915) >= IP_VER(12, 50) ? \ + intel_sseu_has_subslice(&(gt_)->info.sseu, 0, ss_) : \ + intel_sseu_has_subslice(&(gt_)->info.sseu, group_, instance_)) + +/* + * Loop over each subslice/DSS and determine the group and instance IDs that + * should be used to steer MCR accesses toward this DSS. + */ +#define for_each_ss_steering(ss_, gt_, group_, instance_) \ + for (ss_ = 0, intel_gt_mcr_get_ss_steering(gt_, 0, &group_, &instance_); \ + ss_ < I915_MAX_SS_FUSE_BITS; \ + ss_++, intel_gt_mcr_get_ss_steering(gt_, ss_, &group_, &instance_)) \ + for_each_if(_HAS_SS(ss_, gt_, group_, instance_)) + #endif /* __INTEL_GT_MCR__ */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 37c1095d8603..60d6eb5f245b 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -371,6 +371,9 @@ #define GEN9_WM_CHICKEN3 _MMIO(0x5588) #define GEN9_FACTOR_IN_CLR_VAL_HIZ (1 << 9) +#define CHICKEN_RASTER_1 _MMIO(0x6204) +#define DIS_SF_ROUND_NEAREST_EVEN REG_BIT(8) + #define VFLSKPD _MMIO(0x62a8) #define DIS_OVER_FETCH_CACHE REG_BIT(1) #define DIS_MULT_MISS_RD_SQUASH REG_BIT(0) @@ -918,6 +921,10 @@ #define GEN7_L3CNTLREG1 _MMIO(0xb01c) #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C #define GEN7_L3AGDIS (1 << 19) + +#define XEHPC_LNCFMISCCFGREG0 _MMIO(0xb01c) +#define XEHPC_OVRLSCCC REG_BIT(0) + #define GEN7_L3CNTLREG2 _MMIO(0xb020) /* MOCS (Memory Object Control State) registers */ diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c index d09b996a9759..6e90032e12e9 100644 --- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c @@ -15,6 +15,103 @@ #include "gt/intel_gt_mcr.h" #include "gt/intel_gt_regs.h" +static void _release_bars(struct pci_dev *pdev) +{ + int resno; + + for (resno = PCI_STD_RESOURCES; resno < PCI_STD_RESOURCE_END; resno++) { + if (pci_resource_len(pdev, resno)) + pci_release_resource(pdev, resno); + } +} + +static void +_resize_bar(struct drm_i915_private *i915, int resno, resource_size_t size) +{ + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); + int bar_size = pci_rebar_bytes_to_size(size); + int ret; + + _release_bars(pdev); + + ret = pci_resize_resource(pdev, resno, bar_size); + if (ret) { + drm_info(&i915->drm, "Failed to resize BAR%d to %dM (%pe)\n", + resno, 1 << bar_size, ERR_PTR(ret)); + return; + } + + drm_info(&i915->drm, "BAR%d resized to %dM\n", resno, 1 << bar_size); +} + +#define LMEM_BAR_NUM 2 +static void i915_resize_lmem_bar(struct drm_i915_private *i915, resource_size_t lmem_size) +{ + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); + struct pci_bus *root = pdev->bus; + struct resource *root_res; + resource_size_t rebar_size; + resource_size_t current_size; + u32 pci_cmd; + int i; + + current_size = roundup_pow_of_two(pci_resource_len(pdev, LMEM_BAR_NUM)); + + if (i915->params.lmem_bar_size) { + u32 bar_sizes; + + rebar_size = i915->params.lmem_bar_size * + (resource_size_t)SZ_1M; + bar_sizes = pci_rebar_get_possible_sizes(pdev, + LMEM_BAR_NUM); + + if (rebar_size == current_size) + return; + + if (!(bar_sizes & BIT(pci_rebar_bytes_to_size(rebar_size))) || + rebar_size >= roundup_pow_of_two(lmem_size)) { + rebar_size = lmem_size; + + drm_info(&i915->drm, + "Given bar size is not within supported size, setting it to default: %llu\n", + (u64)lmem_size >> 20); + } + } else { + rebar_size = current_size; + + if (rebar_size != roundup_pow_of_two(lmem_size)) + rebar_size = lmem_size; + else + return; + } + + /* Find out if root bus contains 64bit memory addressing */ + while (root->parent) + root = root->parent; + + pci_bus_for_each_resource(root, root_res, i) { + if (root_res && root_res->flags & (IORESOURCE_MEM | IORESOURCE_MEM_64) && + root_res->start > 0x100000000ull) + break; + } + + /* pci_resize_resource will fail anyways */ + if (!root_res) { + drm_info(&i915->drm, "Can't resize LMEM BAR - platform support is missing\n"); + return; + } + + /* First disable PCI memory decoding references */ + pci_read_config_dword(pdev, PCI_COMMAND, &pci_cmd); + pci_write_config_dword(pdev, PCI_COMMAND, + pci_cmd & ~PCI_COMMAND_MEMORY); + + _resize_bar(i915, LMEM_BAR_NUM, rebar_size); + + pci_assign_unassigned_bus_resources(pdev->bus); + pci_write_config_dword(pdev, PCI_COMMAND, pci_cmd); +} + static int region_lmem_release(struct intel_memory_region *mem) { @@ -112,12 +209,6 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) flat_ccs_base = intel_gt_mcr_read_any(gt, XEHP_FLAT_CCS_BASE_ADDR); flat_ccs_base = (flat_ccs_base >> XEHP_CCS_BASE_SHIFT) * SZ_64K; - /* FIXME: Remove this when we have small-bar enabled */ - if (pci_resource_len(pdev, 2) < lmem_size) { - drm_err(&i915->drm, "System requires small-BAR support, which is currently unsupported on this kernel\n"); - return ERR_PTR(-EINVAL); - } - if (GEM_WARN_ON(lmem_size < flat_ccs_base)) return ERR_PTR(-EIO); @@ -134,6 +225,8 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) lmem_size = intel_uncore_read64(&i915->uncore, GEN12_GSMBASE); } + i915_resize_lmem_bar(i915, lmem_size); + if (i915->params.lmem_size > 0) { lmem_size = min_t(resource_size_t, lmem_size, mul_u32_u32(i915->params.lmem_size, SZ_1M)); @@ -170,6 +263,10 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) drm_info(&i915->drm, "Local memory available: %pa\n", &lmem_size); + if (io_size < lmem_size) + drm_info(&i915->drm, "Using a reduced BAR size of %lluMiB. Consider enabling 'Resizable BAR' or similar, if available in the BIOS.\n", + (u64)io_size >> 20); + return mem; err_region_put: diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index a5338c3fde7a..c68d36fb5bbd 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -300,9 +300,9 @@ static int gen6_hw_domain_reset(struct intel_gt *gt, u32 hw_domain_mask) return err; } -static int gen6_reset_engines(struct intel_gt *gt, - intel_engine_mask_t engine_mask, - unsigned int retry) +static int __gen6_reset_engines(struct intel_gt *gt, + intel_engine_mask_t engine_mask, + unsigned int retry) { struct intel_engine_cs *engine; u32 hw_mask; @@ -321,6 +321,20 @@ static int gen6_reset_engines(struct intel_gt *gt, return gen6_hw_domain_reset(gt, hw_mask); } +static int gen6_reset_engines(struct intel_gt *gt, + intel_engine_mask_t engine_mask, + unsigned int retry) +{ + unsigned long flags; + int ret; + + spin_lock_irqsave(>->uncore->lock, flags); + ret = __gen6_reset_engines(gt, engine_mask, retry); + spin_unlock_irqrestore(>->uncore->lock, flags); + + return ret; +} + static struct intel_engine_cs *find_sfc_paired_vecs_engine(struct intel_engine_cs *engine) { int vecs_id; @@ -487,9 +501,9 @@ static void gen11_unlock_sfc(struct intel_engine_cs *engine) rmw_clear_fw(uncore, sfc_lock.lock_reg, sfc_lock.lock_bit); } -static int gen11_reset_engines(struct intel_gt *gt, - intel_engine_mask_t engine_mask, - unsigned int retry) +static int __gen11_reset_engines(struct intel_gt *gt, + intel_engine_mask_t engine_mask, + unsigned int retry) { struct intel_engine_cs *engine; intel_engine_mask_t tmp; @@ -583,8 +597,11 @@ static int gen8_reset_engines(struct intel_gt *gt, struct intel_engine_cs *engine; const bool reset_non_ready = retry >= 1; intel_engine_mask_t tmp; + unsigned long flags; int ret; + spin_lock_irqsave(>->uncore->lock, flags); + for_each_engine_masked(engine, gt, engine_mask, tmp) { ret = gen8_engine_reset_prepare(engine); if (ret && !reset_non_ready) @@ -612,17 +629,19 @@ static int gen8_reset_engines(struct intel_gt *gt, * This is best effort, so ignore any error from the initial reset. */ if (IS_DG2(gt->i915) && engine_mask == ALL_ENGINES) - gen11_reset_engines(gt, gt->info.engine_mask, 0); + __gen11_reset_engines(gt, gt->info.engine_mask, 0); if (GRAPHICS_VER(gt->i915) >= 11) - ret = gen11_reset_engines(gt, engine_mask, retry); + ret = __gen11_reset_engines(gt, engine_mask, retry); else - ret = gen6_reset_engines(gt, engine_mask, retry); + ret = __gen6_reset_engines(gt, engine_mask, retry); skip_reset: for_each_engine_masked(engine, gt, engine_mask, tmp) gen8_engine_reset_cancel(engine); + spin_unlock_irqrestore(>->uncore->lock, flags); + return ret; } diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index 3213c593a55f..e8111fce56d0 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -689,6 +689,9 @@ static void dg2_ctx_workarounds_init(struct intel_engine_cs *engine, if (IS_DG2_GRAPHICS_STEP(engine->i915, G10, STEP_B0, STEP_FOREVER) || IS_DG2_G11(engine->i915) || IS_DG2_G12(engine->i915)) wa_masked_field_set(wal, VF_PREEMPTION, PREEMPTION_VERTEX_COUNT, 0x4000); + + /* Wa_15010599737:dg2 */ + wa_masked_en(wal, CHICKEN_RASTER_1, DIS_SF_ROUND_NEAREST_EVEN); } static void fakewa_disable_nestedbb_mode(struct intel_engine_cs *engine, @@ -2687,6 +2690,9 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li * performance guide section. */ wa_write(wal, XEHPC_L3SCRUB, SCRUB_CL_DWNGRADE_SHARED | SCRUB_RATE_4B_PER_CLK); + + /* Wa_16016694945 */ + wa_masked_en(wal, XEHPC_LNCFMISCCFGREG0, XEHPC_OVRLSCCC); } if (IS_XEHPSDV(i915)) { diff --git a/drivers/gpu/drm/i915/gt/selftest_lrc.c b/drivers/gpu/drm/i915/gt/selftest_lrc.c index 8b2c11dbe354..1109088fe8f6 100644 --- a/drivers/gpu/drm/i915/gt/selftest_lrc.c +++ b/drivers/gpu/drm/i915/gt/selftest_lrc.c @@ -176,8 +176,8 @@ static int live_lrc_layout(void *arg) continue; hw = shmem_pin_map(engine->default_state); - if (IS_ERR(hw)) { - err = PTR_ERR(hw); + if (!hw) { + err = -ENOMEM; break; } hw += LRC_STATE_OFFSET / sizeof(*hw); @@ -365,8 +365,8 @@ static int live_lrc_fixed(void *arg) continue; hw = shmem_pin_map(engine->default_state); - if (IS_ERR(hw)) { - err = PTR_ERR(hw); + if (!hw) { + err = -ENOMEM; break; } hw += LRC_STATE_OFFSET / sizeof(*hw); diff --git a/drivers/gpu/drm/i915/gt/selftest_slpc.c b/drivers/gpu/drm/i915/gt/selftest_slpc.c index b768cea5943d..ac29691e0b1a 100644 --- a/drivers/gpu/drm/i915/gt/selftest_slpc.c +++ b/drivers/gpu/drm/i915/gt/selftest_slpc.c @@ -8,6 +8,11 @@ #define delay_for_h2g() usleep_range(H2G_DELAY, H2G_DELAY + 10000) #define FREQUENCY_REQ_UNIT DIV_ROUND_CLOSEST(GT_FREQUENCY_MULTIPLIER, \ GEN9_FREQ_SCALER) +enum test_type { + VARY_MIN, + VARY_MAX, + MAX_GRANTED +}; static int slpc_set_min_freq(struct intel_guc_slpc *slpc, u32 freq) { @@ -36,147 +41,114 @@ static int slpc_set_max_freq(struct intel_guc_slpc *slpc, u32 freq) return ret; } -static int live_slpc_clamp_min(void *arg) +static int vary_max_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, + u32 *max_act_freq) { - struct drm_i915_private *i915 = arg; - struct intel_gt *gt = to_gt(i915); - struct intel_guc_slpc *slpc = >->uc.guc.slpc; - struct intel_rps *rps = >->rps; - struct intel_engine_cs *engine; - enum intel_engine_id id; - struct igt_spinner spin; - u32 slpc_min_freq, slpc_max_freq; + u32 step, max_freq, req_freq; + u32 act_freq; int err = 0; - if (!intel_uc_uses_guc_slpc(>->uc)) - return 0; + /* Go from max to min in 5 steps */ + step = (slpc->rp0_freq - slpc->min_freq) / NUM_STEPS; + *max_act_freq = slpc->min_freq; + for (max_freq = slpc->rp0_freq; max_freq > slpc->min_freq; + max_freq -= step) { + err = slpc_set_max_freq(slpc, max_freq); + if (err) + break; - if (igt_spinner_init(&spin, gt)) - return -ENOMEM; + req_freq = intel_rps_read_punit_req_frequency(rps); - if (intel_guc_slpc_get_max_freq(slpc, &slpc_max_freq)) { - pr_err("Could not get SLPC max freq\n"); - return -EIO; - } + /* GuC requests freq in multiples of 50/3 MHz */ + if (req_freq > (max_freq + FREQUENCY_REQ_UNIT)) { + pr_err("SWReq is %d, should be at most %d\n", req_freq, + max_freq + FREQUENCY_REQ_UNIT); + err = -EINVAL; + } - if (intel_guc_slpc_get_min_freq(slpc, &slpc_min_freq)) { - pr_err("Could not get SLPC min freq\n"); - return -EIO; - } + act_freq = intel_rps_read_actual_frequency(rps); + if (act_freq > *max_act_freq) + *max_act_freq = act_freq; - if (slpc_min_freq == slpc_max_freq) { - pr_err("Min/Max are fused to the same value\n"); - return -EINVAL; + if (err) + break; } - intel_gt_pm_wait_for_idle(gt); - intel_gt_pm_get(gt); - for_each_engine(engine, gt, id) { - struct i915_request *rq; - u32 step, min_freq, req_freq; - u32 act_freq, max_act_freq; + return err; +} - if (!intel_engine_can_store_dword(engine)) - continue; +static int vary_min_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, + u32 *max_act_freq) +{ + u32 step, min_freq, req_freq; + u32 act_freq; + int err = 0; - /* Go from min to max in 5 steps */ - step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS; - max_act_freq = slpc_min_freq; - for (min_freq = slpc_min_freq; min_freq < slpc_max_freq; - min_freq += step) { - err = slpc_set_min_freq(slpc, min_freq); - if (err) - break; - - st_engine_heartbeat_disable(engine); - - rq = igt_spinner_create_request(&spin, - engine->kernel_context, - MI_NOOP); - if (IS_ERR(rq)) { - err = PTR_ERR(rq); - st_engine_heartbeat_enable(engine); - break; - } + /* Go from min to max in 5 steps */ + step = (slpc->rp0_freq - slpc->min_freq) / NUM_STEPS; + *max_act_freq = slpc->min_freq; + for (min_freq = slpc->min_freq; min_freq < slpc->rp0_freq; + min_freq += step) { + err = slpc_set_min_freq(slpc, min_freq); + if (err) + break; - i915_request_add(rq); + req_freq = intel_rps_read_punit_req_frequency(rps); - if (!igt_wait_for_spinner(&spin, rq)) { - pr_err("%s: Spinner did not start\n", - engine->name); - igt_spinner_end(&spin); - st_engine_heartbeat_enable(engine); - intel_gt_set_wedged(engine->gt); - err = -EIO; - break; - } + /* GuC requests freq in multiples of 50/3 MHz */ + if (req_freq < (min_freq - FREQUENCY_REQ_UNIT)) { + pr_err("SWReq is %d, should be at least %d\n", req_freq, + min_freq - FREQUENCY_REQ_UNIT); + err = -EINVAL; + } - /* Wait for GuC to detect business and raise - * requested frequency if necessary. - */ - delay_for_h2g(); + act_freq = intel_rps_read_actual_frequency(rps); + if (act_freq > *max_act_freq) + *max_act_freq = act_freq; - req_freq = intel_rps_read_punit_req_frequency(rps); + if (err) + break; + } - /* GuC requests freq in multiples of 50/3 MHz */ - if (req_freq < (min_freq - FREQUENCY_REQ_UNIT)) { - pr_err("SWReq is %d, should be at least %d\n", req_freq, - min_freq - FREQUENCY_REQ_UNIT); - igt_spinner_end(&spin); - st_engine_heartbeat_enable(engine); - err = -EINVAL; - break; - } + return err; +} - act_freq = intel_rps_read_actual_frequency(rps); - if (act_freq > max_act_freq) - max_act_freq = act_freq; +static int max_granted_freq(struct intel_guc_slpc *slpc, struct intel_rps *rps, u32 *max_act_freq) +{ + struct intel_gt *gt = rps_to_gt(rps); + u32 perf_limit_reasons; + int err = 0; - igt_spinner_end(&spin); - st_engine_heartbeat_enable(engine); - } + err = slpc_set_min_freq(slpc, slpc->rp0_freq); + if (err) + return err; - pr_info("Max actual frequency for %s was %d\n", - engine->name, max_act_freq); + *max_act_freq = intel_rps_read_actual_frequency(rps); + if (*max_act_freq != slpc->rp0_freq) { + /* Check if there was some throttling by pcode */ + perf_limit_reasons = intel_uncore_read(gt->uncore, GT0_PERF_LIMIT_REASONS); - /* Actual frequency should rise above min */ - if (max_act_freq == slpc_min_freq) { - pr_err("Actual freq did not rise above min\n"); + /* If not, this is an error */ + if (!(perf_limit_reasons & GT0_PERF_LIMIT_REASONS_MASK)) { + pr_err("Pcode did not grant max freq\n"); err = -EINVAL; + } else { + pr_info("Pcode throttled frequency 0x%x\n", perf_limit_reasons); } - - if (err) - break; } - /* Restore min/max frequencies */ - slpc_set_max_freq(slpc, slpc_max_freq); - slpc_set_min_freq(slpc, slpc_min_freq); - - if (igt_flush_test(gt->i915)) - err = -EIO; - - intel_gt_pm_put(gt); - igt_spinner_fini(&spin); - intel_gt_pm_wait_for_idle(gt); - return err; } -static int live_slpc_clamp_max(void *arg) +static int run_test(struct intel_gt *gt, int test_type) { - struct drm_i915_private *i915 = arg; - struct intel_gt *gt = to_gt(i915); - struct intel_guc_slpc *slpc; - struct intel_rps *rps; + struct intel_guc_slpc *slpc = >->uc.guc.slpc; + struct intel_rps *rps = >->rps; struct intel_engine_cs *engine; enum intel_engine_id id; struct igt_spinner spin; - int err = 0; u32 slpc_min_freq, slpc_max_freq; - - slpc = >->uc.guc.slpc; - rps = >->rps; + int err = 0; if (!intel_uc_uses_guc_slpc(>->uc)) return 0; @@ -194,7 +166,7 @@ static int live_slpc_clamp_max(void *arg) return -EIO; } - if (slpc_min_freq == slpc_max_freq) { + if (slpc->min_freq == slpc->rp0_freq) { pr_err("Min/Max are fused to the same value\n"); return -EINVAL; } @@ -203,93 +175,82 @@ static int live_slpc_clamp_max(void *arg) intel_gt_pm_get(gt); for_each_engine(engine, gt, id) { struct i915_request *rq; - u32 max_freq, req_freq; - u32 act_freq, max_act_freq; - u32 step; + u32 max_act_freq; if (!intel_engine_can_store_dword(engine)) continue; - /* Go from max to min in 5 steps */ - step = (slpc_max_freq - slpc_min_freq) / NUM_STEPS; - max_act_freq = slpc_min_freq; - for (max_freq = slpc_max_freq; max_freq > slpc_min_freq; - max_freq -= step) { - err = slpc_set_max_freq(slpc, max_freq); - if (err) - break; - - st_engine_heartbeat_disable(engine); - - rq = igt_spinner_create_request(&spin, - engine->kernel_context, - MI_NOOP); - if (IS_ERR(rq)) { - st_engine_heartbeat_enable(engine); - err = PTR_ERR(rq); - break; - } + st_engine_heartbeat_disable(engine); - i915_request_add(rq); + rq = igt_spinner_create_request(&spin, + engine->kernel_context, + MI_NOOP); + if (IS_ERR(rq)) { + err = PTR_ERR(rq); + st_engine_heartbeat_enable(engine); + break; + } - if (!igt_wait_for_spinner(&spin, rq)) { - pr_err("%s: SLPC spinner did not start\n", - engine->name); - igt_spinner_end(&spin); - st_engine_heartbeat_enable(engine); - intel_gt_set_wedged(engine->gt); - err = -EIO; - break; - } + i915_request_add(rq); - delay_for_h2g(); + if (!igt_wait_for_spinner(&spin, rq)) { + pr_err("%s: Spinner did not start\n", + engine->name); + igt_spinner_end(&spin); + st_engine_heartbeat_enable(engine); + intel_gt_set_wedged(engine->gt); + err = -EIO; + break; + } - /* Verify that SWREQ indeed was set to specific value */ - req_freq = intel_rps_read_punit_req_frequency(rps); + switch (test_type) { + case VARY_MIN: + err = vary_min_freq(slpc, rps, &max_act_freq); + break; - /* GuC requests freq in multiples of 50/3 MHz */ - if (req_freq > (max_freq + FREQUENCY_REQ_UNIT)) { - pr_err("SWReq is %d, should be at most %d\n", req_freq, - max_freq + FREQUENCY_REQ_UNIT); + case VARY_MAX: + err = vary_max_freq(slpc, rps, &max_act_freq); + break; + + case MAX_GRANTED: + /* Media engines have a different RP0 */ + if (engine->class == VIDEO_DECODE_CLASS || + engine->class == VIDEO_ENHANCEMENT_CLASS) { igt_spinner_end(&spin); st_engine_heartbeat_enable(engine); - err = -EINVAL; - break; + err = 0; + continue; } - act_freq = intel_rps_read_actual_frequency(rps); - if (act_freq > max_act_freq) - max_act_freq = act_freq; - - st_engine_heartbeat_enable(engine); - igt_spinner_end(&spin); - - if (err) - break; + err = max_granted_freq(slpc, rps, &max_act_freq); + break; } pr_info("Max actual frequency for %s was %d\n", engine->name, max_act_freq); /* Actual frequency should rise above min */ - if (max_act_freq == slpc_min_freq) { + if (max_act_freq <= slpc_min_freq) { pr_err("Actual freq did not rise above min\n"); + pr_err("Perf Limit Reasons: 0x%x\n", + intel_uncore_read(gt->uncore, GT0_PERF_LIMIT_REASONS)); err = -EINVAL; } - if (igt_flush_test(gt->i915)) { - err = -EIO; - break; - } + igt_spinner_end(&spin); + st_engine_heartbeat_enable(engine); if (err) break; } - /* Restore min/max freq */ + /* Restore min/max frequencies */ slpc_set_max_freq(slpc, slpc_max_freq); slpc_set_min_freq(slpc, slpc_min_freq); + if (igt_flush_test(gt->i915)) + err = -EIO; + intel_gt_pm_put(gt); igt_spinner_fini(&spin); intel_gt_pm_wait_for_idle(gt); @@ -297,11 +258,37 @@ static int live_slpc_clamp_max(void *arg) return err; } +static int live_slpc_vary_min(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_gt *gt = to_gt(i915); + + return run_test(gt, VARY_MIN); +} + +static int live_slpc_vary_max(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_gt *gt = to_gt(i915); + + return run_test(gt, VARY_MAX); +} + +/* check if pcode can grant RP0 */ +static int live_slpc_max_granted(void *arg) +{ + struct drm_i915_private *i915 = arg; + struct intel_gt *gt = to_gt(i915); + + return run_test(gt, MAX_GRANTED); +} + int intel_slpc_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { - SUBTEST(live_slpc_clamp_max), - SUBTEST(live_slpc_clamp_min), + SUBTEST(live_slpc_vary_max), + SUBTEST(live_slpc_vary_min), + SUBTEST(live_slpc_max_granted), }; if (intel_gt_is_wedged(to_gt(i915))) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h index 4ef9990ed7f8..29ef8afc8c2e 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h @@ -122,6 +122,9 @@ enum intel_guc_action { INTEL_GUC_ACTION_SCHED_CONTEXT_MODE_DONE = 0x1002, INTEL_GUC_ACTION_SCHED_ENGINE_MODE_SET = 0x1003, INTEL_GUC_ACTION_SCHED_ENGINE_MODE_DONE = 0x1004, + INTEL_GUC_ACTION_V69_SET_CONTEXT_PRIORITY = 0x1005, + INTEL_GUC_ACTION_V69_SET_CONTEXT_EXECUTION_QUANTUM = 0x1006, + INTEL_GUC_ACTION_V69_SET_CONTEXT_PREEMPTION_TIMEOUT = 0x1007, INTEL_GUC_ACTION_CONTEXT_RESET_NOTIFICATION = 0x1008, INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009, INTEL_GUC_ACTION_HOST2GUC_UPDATE_CONTEXT_POLICIES = 0x100B, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index d0d99f178f2d..a7acffbf15d1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -170,6 +170,11 @@ struct intel_guc { /** @ads_engine_usage_size: size of engine usage in the ADS */ u32 ads_engine_usage_size; + /** @lrc_desc_pool_v69: object allocated to hold the GuC LRC descriptor pool */ + struct i915_vma *lrc_desc_pool_v69; + /** @lrc_desc_pool_vaddr_v69: contents of the GuC LRC descriptor pool */ + void *lrc_desc_pool_vaddr_v69; + /** * @context_lookup: used to resolve intel_context from guc_id, if a * context is present in this structure it is registered with the GuC diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 97a32e610c30..75257bd20ff0 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -9,6 +9,7 @@ #include "gt/intel_engine_regs.h" #include "gt/intel_gt.h" +#include "gt/intel_gt_mcr.h" #include "gt/intel_gt_regs.h" #include "gt/intel_lrc.h" #include "guc_capture_fwif.h" @@ -281,8 +282,7 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, const struct __guc_mmio_reg_descr_group *lists) { struct intel_gt *gt = guc_to_gt(guc); - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; - int slice, subslice, i, num_steer_regs, num_tot_regs = 0; + int slice, subslice, iter, i, num_steer_regs, num_tot_regs = 0; const struct __guc_mmio_reg_descr_group *list; struct __guc_mmio_reg_descr_group *extlists; struct __guc_mmio_reg_descr *extarray; @@ -298,7 +298,7 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, num_steer_regs = ARRAY_SIZE(xe_extregs); sseu = >->info.sseu; - for_each_instdone_slice_subslice(i915, sseu, slice, subslice) + for_each_ss_steering(iter, gt, slice, subslice) num_tot_regs += num_steer_regs; if (!num_tot_regs) @@ -315,7 +315,7 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, } extarray = extlists[0].extlist; - for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { + for_each_ss_steering(iter, gt, slice, subslice) { for (i = 0; i < num_steer_regs; ++i) { __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice); ++extarray; @@ -359,9 +359,8 @@ guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc, num_steer_regs += ARRAY_SIZE(xehpg_extregs); sseu = >->info.sseu; - for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { + for_each_ss_steering(iter, gt, slice, subslice) num_tot_regs += num_steer_regs; - } if (!num_tot_regs) return; @@ -377,7 +376,7 @@ guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc, } extarray = extlists[0].extlist; - for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { + for_each_ss_steering(iter, gt, slice, subslice) { for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) { __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice); ++extarray; @@ -1261,7 +1260,8 @@ static int __guc_capture_flushlog_complete(struct intel_guc *guc) GUC_CAPTURE_LOG_BUFFER }; - return intel_guc_send(guc, action, ARRAY_SIZE(action)); + return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0); + } static void __guc_capture_process_output(struct intel_guc *guc) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index b3c9a9327f76..323b055e5db9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -204,6 +204,20 @@ struct guc_wq_item { u32 fence_id; } __packed; +struct guc_process_desc_v69 { + u32 stage_id; + u64 db_base_addr; + u32 head; + u32 tail; + u32 error_offset; + u64 wq_base_addr; + u32 wq_size_bytes; + u32 wq_status; + u32 engine_presence; + u32 priority; + u32 reserved[36]; +} __packed; + struct guc_sched_wq_desc { u32 head; u32 tail; @@ -228,6 +242,37 @@ struct guc_ctxt_registration_info { }; #define CONTEXT_REGISTRATION_FLAG_KMD BIT(0) +/* Preempt to idle on quantum expiry */ +#define CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE_V69 BIT(0) + +/* + * GuC Context registration descriptor. + * FIXME: This is only required to exist during context registration. + * The current 1:1 between guc_lrc_desc and LRCs for the lifetime of the LRC + * is not required. + */ +struct guc_lrc_desc_v69 { + u32 hw_context_desc; + u32 slpm_perf_mode_hint; /* SPLC v1 only */ + u32 slpm_freq_hint; + u32 engine_submit_mask; /* In logical space */ + u8 engine_class; + u8 reserved0[3]; + u32 priority; + u32 process_desc; + u32 wq_addr; + u32 wq_size; + u32 context_flags; /* CONTEXT_REGISTRATION_* */ + /* Time for one workload to execute. (in micro seconds) */ + u32 execution_quantum; + /* Time to wait for a preemption request to complete before issuing a + * reset. (in micro seconds). + */ + u32 preemption_timeout; + u32 policy_flags; /* CONTEXT_POLICY_* */ + u32 reserved1[19]; +} __packed; + /* 32-bit KLV structure as used by policy updates and others */ struct guc_klv_generic_dw_t { u32 kl; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 02311ad90264..25b2d7ce6640 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -31,7 +31,7 @@ static int guc_action_flush_log_complete(struct intel_guc *guc) GUC_DEBUG_LOG_BUFFER }; - return intel_guc_send(guc, action, ARRAY_SIZE(action)); + return intel_guc_send_nb(guc, action, ARRAY_SIZE(action), 0); } static int guc_action_flush_log(struct intel_guc *guc) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 40f726c61e95..76916aed897a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -414,12 +414,15 @@ struct sync_semaphore { }; struct parent_scratch { - struct guc_sched_wq_desc wq_desc; + union guc_descs { + struct guc_sched_wq_desc wq_desc; + struct guc_process_desc_v69 pdesc; + } descs; struct sync_semaphore go; struct sync_semaphore join[MAX_ENGINE_INSTANCE + 1]; - u8 unused[WQ_OFFSET - sizeof(struct guc_sched_wq_desc) - + u8 unused[WQ_OFFSET - sizeof(union guc_descs) - sizeof(struct sync_semaphore) * (MAX_ENGINE_INSTANCE + 2)]; u32 wq[WQ_SIZE / sizeof(u32)]; @@ -456,17 +459,23 @@ __get_parent_scratch(struct intel_context *ce) LRC_STATE_OFFSET) / sizeof(u32))); } +static struct guc_process_desc_v69 * +__get_process_desc_v69(struct intel_context *ce) +{ + struct parent_scratch *ps = __get_parent_scratch(ce); + + return &ps->descs.pdesc; +} + static struct guc_sched_wq_desc * -__get_wq_desc(struct intel_context *ce) +__get_wq_desc_v70(struct intel_context *ce) { struct parent_scratch *ps = __get_parent_scratch(ce); - return &ps->wq_desc; + return &ps->descs.wq_desc; } -static u32 *get_wq_pointer(struct guc_sched_wq_desc *wq_desc, - struct intel_context *ce, - u32 wqi_size) +static u32 *get_wq_pointer(struct intel_context *ce, u32 wqi_size) { /* * Check for space in work queue. Caching a value of head pointer in @@ -476,7 +485,7 @@ static u32 *get_wq_pointer(struct guc_sched_wq_desc *wq_desc, #define AVAILABLE_SPACE \ CIRC_SPACE(ce->parallel.guc.wqi_tail, ce->parallel.guc.wqi_head, WQ_SIZE) if (wqi_size > AVAILABLE_SPACE) { - ce->parallel.guc.wqi_head = READ_ONCE(wq_desc->head); + ce->parallel.guc.wqi_head = READ_ONCE(*ce->parallel.guc.wq_head); if (wqi_size > AVAILABLE_SPACE) return NULL; @@ -495,11 +504,55 @@ static inline struct intel_context *__get_context(struct intel_guc *guc, u32 id) return ce; } +static struct guc_lrc_desc_v69 *__get_lrc_desc_v69(struct intel_guc *guc, u32 index) +{ + struct guc_lrc_desc_v69 *base = guc->lrc_desc_pool_vaddr_v69; + + if (!base) + return NULL; + + GEM_BUG_ON(index >= GUC_MAX_CONTEXT_ID); + + return &base[index]; +} + +static int guc_lrc_desc_pool_create_v69(struct intel_guc *guc) +{ + u32 size; + int ret; + + size = PAGE_ALIGN(sizeof(struct guc_lrc_desc_v69) * + GUC_MAX_CONTEXT_ID); + ret = intel_guc_allocate_and_map_vma(guc, size, &guc->lrc_desc_pool_v69, + (void **)&guc->lrc_desc_pool_vaddr_v69); + if (ret) + return ret; + + return 0; +} + +static void guc_lrc_desc_pool_destroy_v69(struct intel_guc *guc) +{ + if (!guc->lrc_desc_pool_vaddr_v69) + return; + + guc->lrc_desc_pool_vaddr_v69 = NULL; + i915_vma_unpin_and_release(&guc->lrc_desc_pool_v69, I915_VMA_RELEASE_MAP); +} + static inline bool guc_submission_initialized(struct intel_guc *guc) { return guc->submission_initialized; } +static inline void _reset_lrc_desc_v69(struct intel_guc *guc, u32 id) +{ + struct guc_lrc_desc_v69 *desc = __get_lrc_desc_v69(guc, id); + + if (desc) + memset(desc, 0, sizeof(*desc)); +} + static inline bool ctx_id_mapped(struct intel_guc *guc, u32 id) { return __get_context(guc, id); @@ -526,6 +579,8 @@ static inline void clr_ctx_id_mapping(struct intel_guc *guc, u32 id) if (unlikely(!guc_submission_initialized(guc))) return; + _reset_lrc_desc_v69(guc, id); + /* * xarray API doesn't have xa_erase_irqsave wrapper, so calling * the lower level functions directly. @@ -611,7 +666,7 @@ int intel_guc_wait_for_idle(struct intel_guc *guc, long timeout) true, timeout); } -static int guc_context_policy_init(struct intel_context *ce, bool loop); +static int guc_context_policy_init_v70(struct intel_context *ce, bool loop); static int try_context_registration(struct intel_context *ce, bool loop); static int __guc_add_request(struct intel_guc *guc, struct i915_request *rq) @@ -639,7 +694,7 @@ static int __guc_add_request(struct intel_guc *guc, struct i915_request *rq) GEM_BUG_ON(context_guc_id_invalid(ce)); if (context_policy_required(ce)) { - err = guc_context_policy_init(ce, false); + err = guc_context_policy_init_v70(ce, false); if (err) return err; } @@ -737,9 +792,7 @@ static u32 wq_space_until_wrap(struct intel_context *ce) return (WQ_SIZE - ce->parallel.guc.wqi_tail); } -static void write_wqi(struct guc_sched_wq_desc *wq_desc, - struct intel_context *ce, - u32 wqi_size) +static void write_wqi(struct intel_context *ce, u32 wqi_size) { BUILD_BUG_ON(!is_power_of_2(WQ_SIZE)); @@ -750,13 +803,12 @@ static void write_wqi(struct guc_sched_wq_desc *wq_desc, ce->parallel.guc.wqi_tail = (ce->parallel.guc.wqi_tail + wqi_size) & (WQ_SIZE - 1); - WRITE_ONCE(wq_desc->tail, ce->parallel.guc.wqi_tail); + WRITE_ONCE(*ce->parallel.guc.wq_tail, ce->parallel.guc.wqi_tail); } static int guc_wq_noop_append(struct intel_context *ce) { - struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce); - u32 *wqi = get_wq_pointer(wq_desc, ce, wq_space_until_wrap(ce)); + u32 *wqi = get_wq_pointer(ce, wq_space_until_wrap(ce)); u32 len_dw = wq_space_until_wrap(ce) / sizeof(u32) - 1; if (!wqi) @@ -775,7 +827,6 @@ static int __guc_wq_item_append(struct i915_request *rq) { struct intel_context *ce = request_to_scheduling_context(rq); struct intel_context *child; - struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce); unsigned int wqi_size = (ce->parallel.number_children + 4) * sizeof(u32); u32 *wqi; @@ -795,7 +846,7 @@ static int __guc_wq_item_append(struct i915_request *rq) return ret; } - wqi = get_wq_pointer(wq_desc, ce, wqi_size); + wqi = get_wq_pointer(ce, wqi_size); if (!wqi) return -EBUSY; @@ -810,7 +861,7 @@ static int __guc_wq_item_append(struct i915_request *rq) for_each_child(ce, child) *wqi++ = child->ring->tail / sizeof(u64); - write_wqi(wq_desc, ce, wqi_size); + write_wqi(ce, wqi_size); return 0; } @@ -1812,20 +1863,34 @@ static void reset_fail_worker_func(struct work_struct *w); int intel_guc_submission_init(struct intel_guc *guc) { struct intel_gt *gt = guc_to_gt(guc); + int ret; if (guc->submission_initialized) return 0; + if (guc->fw.major_ver_found < 70) { + ret = guc_lrc_desc_pool_create_v69(guc); + if (ret) + return ret; + } + guc->submission_state.guc_ids_bitmap = bitmap_zalloc(NUMBER_MULTI_LRC_GUC_ID(guc), GFP_KERNEL); - if (!guc->submission_state.guc_ids_bitmap) - return -ENOMEM; + if (!guc->submission_state.guc_ids_bitmap) { + ret = -ENOMEM; + goto destroy_pool; + } guc->timestamp.ping_delay = (POLL_TIME_CLKS / gt->clock_frequency + 1) * HZ; guc->timestamp.shift = gpm_timestamp_shift(gt); guc->submission_initialized = true; return 0; + +destroy_pool: + guc_lrc_desc_pool_destroy_v69(guc); + + return ret; } void intel_guc_submission_fini(struct intel_guc *guc) @@ -1834,6 +1899,7 @@ void intel_guc_submission_fini(struct intel_guc *guc) return; guc_flush_destroyed_contexts(guc); + guc_lrc_desc_pool_destroy_v69(guc); i915_sched_engine_put(guc->sched_engine); bitmap_free(guc->submission_state.guc_ids_bitmap); guc->submission_initialized = false; @@ -2091,10 +2157,34 @@ static void unpin_guc_id(struct intel_guc *guc, struct intel_context *ce) spin_unlock_irqrestore(&guc->submission_state.lock, flags); } -static int __guc_action_register_multi_lrc(struct intel_guc *guc, - struct intel_context *ce, - struct guc_ctxt_registration_info *info, - bool loop) +static int __guc_action_register_multi_lrc_v69(struct intel_guc *guc, + struct intel_context *ce, + u32 guc_id, + u32 offset, + bool loop) +{ + struct intel_context *child; + u32 action[4 + MAX_ENGINE_INSTANCE]; + int len = 0; + + GEM_BUG_ON(ce->parallel.number_children > MAX_ENGINE_INSTANCE); + + action[len++] = INTEL_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC; + action[len++] = guc_id; + action[len++] = ce->parallel.number_children + 1; + action[len++] = offset; + for_each_child(ce, child) { + offset += sizeof(struct guc_lrc_desc_v69); + action[len++] = offset; + } + + return guc_submission_send_busy_loop(guc, action, len, 0, loop); +} + +static int __guc_action_register_multi_lrc_v70(struct intel_guc *guc, + struct intel_context *ce, + struct guc_ctxt_registration_info *info, + bool loop) { struct intel_context *child; u32 action[13 + (MAX_ENGINE_INSTANCE * 2)]; @@ -2134,9 +2224,24 @@ static int __guc_action_register_multi_lrc(struct intel_guc *guc, return guc_submission_send_busy_loop(guc, action, len, 0, loop); } -static int __guc_action_register_context(struct intel_guc *guc, - struct guc_ctxt_registration_info *info, - bool loop) +static int __guc_action_register_context_v69(struct intel_guc *guc, + u32 guc_id, + u32 offset, + bool loop) +{ + u32 action[] = { + INTEL_GUC_ACTION_REGISTER_CONTEXT, + guc_id, + offset, + }; + + return guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action), + 0, loop); +} + +static int __guc_action_register_context_v70(struct intel_guc *guc, + struct guc_ctxt_registration_info *info, + bool loop) { u32 action[] = { INTEL_GUC_ACTION_REGISTER_CONTEXT, @@ -2157,24 +2262,52 @@ static int __guc_action_register_context(struct intel_guc *guc, 0, loop); } -static void prepare_context_registration_info(struct intel_context *ce, - struct guc_ctxt_registration_info *info); +static void prepare_context_registration_info_v69(struct intel_context *ce); +static void prepare_context_registration_info_v70(struct intel_context *ce, + struct guc_ctxt_registration_info *info); -static int register_context(struct intel_context *ce, bool loop) +static int +register_context_v69(struct intel_guc *guc, struct intel_context *ce, bool loop) +{ + u32 offset = intel_guc_ggtt_offset(guc, guc->lrc_desc_pool_v69) + + ce->guc_id.id * sizeof(struct guc_lrc_desc_v69); + + prepare_context_registration_info_v69(ce); + + if (intel_context_is_parent(ce)) + return __guc_action_register_multi_lrc_v69(guc, ce, ce->guc_id.id, + offset, loop); + else + return __guc_action_register_context_v69(guc, ce->guc_id.id, + offset, loop); +} + +static int +register_context_v70(struct intel_guc *guc, struct intel_context *ce, bool loop) { struct guc_ctxt_registration_info info; + + prepare_context_registration_info_v70(ce, &info); + + if (intel_context_is_parent(ce)) + return __guc_action_register_multi_lrc_v70(guc, ce, &info, loop); + else + return __guc_action_register_context_v70(guc, &info, loop); +} + +static int register_context(struct intel_context *ce, bool loop) +{ struct intel_guc *guc = ce_to_guc(ce); int ret; GEM_BUG_ON(intel_context_is_child(ce)); trace_intel_context_register(ce); - prepare_context_registration_info(ce, &info); - - if (intel_context_is_parent(ce)) - ret = __guc_action_register_multi_lrc(guc, ce, &info, loop); + if (guc->fw.major_ver_found >= 70) + ret = register_context_v70(guc, ce, loop); else - ret = __guc_action_register_context(guc, &info, loop); + ret = register_context_v69(guc, ce, loop); + if (likely(!ret)) { unsigned long flags; @@ -2182,7 +2315,8 @@ static int register_context(struct intel_context *ce, bool loop) set_context_registered(ce); spin_unlock_irqrestore(&ce->guc_state.lock, flags); - guc_context_policy_init(ce, loop); + if (guc->fw.major_ver_found >= 70) + guc_context_policy_init_v70(ce, loop); } return ret; @@ -2279,7 +2413,7 @@ static int __guc_context_set_context_policies(struct intel_guc *guc, 0, loop); } -static int guc_context_policy_init(struct intel_context *ce, bool loop) +static int guc_context_policy_init_v70(struct intel_context *ce, bool loop) { struct intel_engine_cs *engine = ce->engine; struct intel_guc *guc = &engine->gt->uc.guc; @@ -2338,6 +2472,19 @@ static int guc_context_policy_init(struct intel_context *ce, bool loop) return ret; } +static void guc_context_policy_init_v69(struct intel_engine_cs *engine, + struct guc_lrc_desc_v69 *desc) +{ + desc->policy_flags = 0; + + if (engine->flags & I915_ENGINE_WANT_FORCED_PREEMPTION) + desc->policy_flags |= CONTEXT_POLICY_FLAG_PREEMPT_TO_IDLE_V69; + + /* NB: For both of these, zero means disabled. */ + desc->execution_quantum = engine->props.timeslice_duration_ms * 1000; + desc->preemption_timeout = engine->props.preempt_timeout_ms * 1000; +} + static u32 map_guc_prio_to_lrc_desc_prio(u8 prio) { /* @@ -2358,8 +2505,75 @@ static u32 map_guc_prio_to_lrc_desc_prio(u8 prio) } } -static void prepare_context_registration_info(struct intel_context *ce, - struct guc_ctxt_registration_info *info) +static void prepare_context_registration_info_v69(struct intel_context *ce) +{ + struct intel_engine_cs *engine = ce->engine; + struct intel_guc *guc = &engine->gt->uc.guc; + u32 ctx_id = ce->guc_id.id; + struct guc_lrc_desc_v69 *desc; + struct intel_context *child; + + GEM_BUG_ON(!engine->mask); + + /* + * Ensure LRC + CT vmas are is same region as write barrier is done + * based on CT vma region. + */ + GEM_BUG_ON(i915_gem_object_is_lmem(guc->ct.vma->obj) != + i915_gem_object_is_lmem(ce->ring->vma->obj)); + + desc = __get_lrc_desc_v69(guc, ctx_id); + desc->engine_class = engine_class_to_guc_class(engine->class); + desc->engine_submit_mask = engine->logical_mask; + desc->hw_context_desc = ce->lrc.lrca; + desc->priority = ce->guc_state.prio; + desc->context_flags = CONTEXT_REGISTRATION_FLAG_KMD; + guc_context_policy_init_v69(engine, desc); + + /* + * If context is a parent, we need to register a process descriptor + * describing a work queue and register all child contexts. + */ + if (intel_context_is_parent(ce)) { + struct guc_process_desc_v69 *pdesc; + + ce->parallel.guc.wqi_tail = 0; + ce->parallel.guc.wqi_head = 0; + + desc->process_desc = i915_ggtt_offset(ce->state) + + __get_parent_scratch_offset(ce); + desc->wq_addr = i915_ggtt_offset(ce->state) + + __get_wq_offset(ce); + desc->wq_size = WQ_SIZE; + + pdesc = __get_process_desc_v69(ce); + memset(pdesc, 0, sizeof(*(pdesc))); + pdesc->stage_id = ce->guc_id.id; + pdesc->wq_base_addr = desc->wq_addr; + pdesc->wq_size_bytes = desc->wq_size; + pdesc->wq_status = WQ_STATUS_ACTIVE; + + ce->parallel.guc.wq_head = &pdesc->head; + ce->parallel.guc.wq_tail = &pdesc->tail; + ce->parallel.guc.wq_status = &pdesc->wq_status; + + for_each_child(ce, child) { + desc = __get_lrc_desc_v69(guc, child->guc_id.id); + + desc->engine_class = + engine_class_to_guc_class(engine->class); + desc->hw_context_desc = child->lrc.lrca; + desc->priority = ce->guc_state.prio; + desc->context_flags = CONTEXT_REGISTRATION_FLAG_KMD; + guc_context_policy_init_v69(engine, desc); + } + + clear_children_join_go_memory(ce); + } +} + +static void prepare_context_registration_info_v70(struct intel_context *ce, + struct guc_ctxt_registration_info *info) { struct intel_engine_cs *engine = ce->engine; struct intel_guc *guc = &engine->gt->uc.guc; @@ -2409,10 +2623,14 @@ static void prepare_context_registration_info(struct intel_context *ce, info->wq_base_hi = upper_32_bits(wq_base_offset); info->wq_size = WQ_SIZE; - wq_desc = __get_wq_desc(ce); + wq_desc = __get_wq_desc_v70(ce); memset(wq_desc, 0, sizeof(*wq_desc)); wq_desc->wq_status = WQ_STATUS_ACTIVE; + ce->parallel.guc.wq_head = &wq_desc->head; + ce->parallel.guc.wq_tail = &wq_desc->tail; + ce->parallel.guc.wq_status = &wq_desc->wq_status; + clear_children_join_go_memory(ce); } } @@ -2727,11 +2945,21 @@ static void __guc_context_set_preemption_timeout(struct intel_guc *guc, u16 guc_id, u32 preemption_timeout) { - struct context_policy policy; + if (guc->fw.major_ver_found >= 70) { + struct context_policy policy; - __guc_context_policy_start_klv(&policy, guc_id); - __guc_context_policy_add_preemption_timeout(&policy, preemption_timeout); - __guc_context_set_context_policies(guc, &policy, true); + __guc_context_policy_start_klv(&policy, guc_id); + __guc_context_policy_add_preemption_timeout(&policy, preemption_timeout); + __guc_context_set_context_policies(guc, &policy, true); + } else { + u32 action[] = { + INTEL_GUC_ACTION_V69_SET_CONTEXT_PREEMPTION_TIMEOUT, + guc_id, + preemption_timeout + }; + + intel_guc_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true); + } } static void @@ -2982,11 +3210,21 @@ static int guc_context_alloc(struct intel_context *ce) static void __guc_context_set_prio(struct intel_guc *guc, struct intel_context *ce) { - struct context_policy policy; + if (guc->fw.major_ver_found >= 70) { + struct context_policy policy; - __guc_context_policy_start_klv(&policy, ce->guc_id.id); - __guc_context_policy_add_priority(&policy, ce->guc_state.prio); - __guc_context_set_context_policies(guc, &policy, true); + __guc_context_policy_start_klv(&policy, ce->guc_id.id); + __guc_context_policy_add_priority(&policy, ce->guc_state.prio); + __guc_context_set_context_policies(guc, &policy, true); + } else { + u32 action[] = { + INTEL_GUC_ACTION_V69_SET_CONTEXT_PRIORITY, + ce->guc_id.id, + ce->guc_state.prio, + }; + + guc_submission_send_busy_loop(guc, action, ARRAY_SIZE(action), 0, true); + } } static void guc_context_set_prio(struct intel_guc *guc, @@ -4496,17 +4734,19 @@ void intel_guc_submission_print_context_info(struct intel_guc *guc, guc_log_context_priority(p, ce); if (intel_context_is_parent(ce)) { - struct guc_sched_wq_desc *wq_desc = __get_wq_desc(ce); struct intel_context *child; drm_printf(p, "\t\tNumber children: %u\n", ce->parallel.number_children); - drm_printf(p, "\t\tWQI Head: %u\n", - READ_ONCE(wq_desc->head)); - drm_printf(p, "\t\tWQI Tail: %u\n", - READ_ONCE(wq_desc->tail)); - drm_printf(p, "\t\tWQI Status: %u\n\n", - READ_ONCE(wq_desc->wq_status)); + + if (ce->parallel.guc.wq_status) { + drm_printf(p, "\t\tWQI Head: %u\n", + READ_ONCE(*ce->parallel.guc.wq_head)); + drm_printf(p, "\t\tWQI Tail: %u\n", + READ_ONCE(*ce->parallel.guc.wq_tail)); + drm_printf(p, "\t\tWQI Status: %u\n\n", + READ_ONCE(*ce->parallel.guc.wq_status)); + } if (ce->engine->emit_bb_start == emit_bb_start_parent_no_preempt_mid_batch) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index c06e83872c34..56a0d80f88ba 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -70,6 +70,10 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, fw_def(BROXTON, 0, guc_def(bxt, 70, 1, 1)) \ fw_def(SKYLAKE, 0, guc_def(skl, 70, 1, 1)) +#define INTEL_GUC_FIRMWARE_DEFS_FALLBACK(fw_def, guc_def) \ + fw_def(ALDERLAKE_P, 0, guc_def(adlp, 69, 0, 3)) \ + fw_def(ALDERLAKE_S, 0, guc_def(tgl, 69, 0, 3)) + #define INTEL_HUC_FIRMWARE_DEFS(fw_def, huc_def) \ fw_def(ALDERLAKE_P, 0, huc_def(tgl, 7, 9, 3)) \ fw_def(ALDERLAKE_S, 0, huc_def(tgl, 7, 9, 3)) \ @@ -105,6 +109,7 @@ void intel_uc_fw_change_status(struct intel_uc_fw *uc_fw, MODULE_FIRMWARE(uc_); INTEL_GUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH) +INTEL_GUC_FIRMWARE_DEFS_FALLBACK(INTEL_UC_MODULE_FW, MAKE_GUC_FW_PATH) INTEL_HUC_FIRMWARE_DEFS(INTEL_UC_MODULE_FW, MAKE_HUC_FW_PATH) /* The below structs and macros are used to iterate across the list of blobs */ @@ -149,6 +154,9 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) static const struct uc_fw_platform_requirement blobs_guc[] = { INTEL_GUC_FIRMWARE_DEFS(MAKE_FW_LIST, GUC_FW_BLOB) }; + static const struct uc_fw_platform_requirement blobs_guc_fallback[] = { + INTEL_GUC_FIRMWARE_DEFS_FALLBACK(MAKE_FW_LIST, GUC_FW_BLOB) + }; static const struct uc_fw_platform_requirement blobs_huc[] = { INTEL_HUC_FIRMWARE_DEFS(MAKE_FW_LIST, HUC_FW_BLOB) }; @@ -162,6 +170,15 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) u8 rev = INTEL_REVID(i915); int i; + /* + * The only difference between the ADL GuC FWs is the HWConfig support. + * ADL-N does not support HWConfig, so we should use the same binary as + * ADL-S, otherwise the GuC might attempt to fetch a config table that + * does not exist. + */ + if (IS_ADLP_N(i915)) + p = INTEL_ALDERLAKE_S; + GEM_BUG_ON(uc_fw->type >= ARRAY_SIZE(blobs_all)); fw_blobs = blobs_all[uc_fw->type].blobs; fw_count = blobs_all[uc_fw->type].count; @@ -170,12 +187,29 @@ __uc_fw_auto_select(struct drm_i915_private *i915, struct intel_uc_fw *uc_fw) if (p == fw_blobs[i].p && rev >= fw_blobs[i].rev) { const struct uc_fw_blob *blob = &fw_blobs[i].blob; uc_fw->path = blob->path; + uc_fw->wanted_path = blob->path; uc_fw->major_ver_wanted = blob->major; uc_fw->minor_ver_wanted = blob->minor; break; } } + if (uc_fw->type == INTEL_UC_FW_TYPE_GUC) { + const struct uc_fw_platform_requirement *blobs = blobs_guc_fallback; + u32 count = ARRAY_SIZE(blobs_guc_fallback); + + for (i = 0; i < count && p <= blobs[i].p; i++) { + if (p == blobs[i].p && rev >= blobs[i].rev) { + const struct uc_fw_blob *blob = &blobs[i].blob; + + uc_fw->fallback.path = blob->path; + uc_fw->fallback.major_ver = blob->major; + uc_fw->fallback.minor_ver = blob->minor; + break; + } + } + } + /* make sure the list is ordered as expected */ if (IS_ENABLED(CONFIG_DRM_I915_SELFTEST)) { for (i = 1; i < fw_count; i++) { @@ -403,7 +437,24 @@ int intel_uc_fw_fetch(struct intel_uc_fw *uc_fw) __force_fw_fetch_failures(uc_fw, -EINVAL); __force_fw_fetch_failures(uc_fw, -ESTALE); - err = request_firmware(&fw, uc_fw->path, dev); + err = firmware_request_nowarn(&fw, uc_fw->path, dev); + if (err && !intel_uc_fw_is_overridden(uc_fw) && uc_fw->fallback.path) { + err = firmware_request_nowarn(&fw, uc_fw->fallback.path, dev); + if (!err) { + drm_notice(&i915->drm, + "%s firmware %s is recommended, but only %s was found\n", + intel_uc_fw_type_repr(uc_fw->type), + uc_fw->wanted_path, + uc_fw->fallback.path); + drm_info(&i915->drm, + "Consider updating your linux-firmware pkg or downloading from %s\n", + INTEL_UC_FIRMWARE_URL); + + uc_fw->path = uc_fw->fallback.path; + uc_fw->major_ver_wanted = uc_fw->fallback.major_ver; + uc_fw->minor_ver_wanted = uc_fw->fallback.minor_ver; + } + } if (err) goto fail; @@ -451,8 +502,8 @@ fail: INTEL_UC_FIRMWARE_MISSING : INTEL_UC_FIRMWARE_ERROR); - drm_notice(&i915->drm, "%s firmware %s: fetch failed with error %d\n", - intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err); + i915_probe_error(i915, "%s firmware %s: fetch failed with error %d\n", + intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err); drm_info(&i915->drm, "%s firmware(s) can be downloaded from %s\n", intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL); @@ -813,7 +864,13 @@ size_t intel_uc_fw_copy_rsa(struct intel_uc_fw *uc_fw, void *dst, u32 max_len) void intel_uc_fw_dump(const struct intel_uc_fw *uc_fw, struct drm_printer *p) { drm_printf(p, "%s firmware: %s\n", - intel_uc_fw_type_repr(uc_fw->type), uc_fw->path); + intel_uc_fw_type_repr(uc_fw->type), uc_fw->wanted_path); + if (uc_fw->fallback.path) { + drm_printf(p, "%s firmware fallback: %s\n", + intel_uc_fw_type_repr(uc_fw->type), uc_fw->fallback.path); + drm_printf(p, "fallback selected: %s\n", + str_yes_no(uc_fw->path == uc_fw->fallback.path)); + } drm_printf(p, "\tstatus: %s\n", intel_uc_fw_status_repr(uc_fw->status)); drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n", diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h index 4f169035f504..7aa2644400b9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.h @@ -74,6 +74,7 @@ struct intel_uc_fw { const enum intel_uc_fw_status status; enum intel_uc_fw_status __status; /* no accidental overwrites */ }; + const char *wanted_path; const char *path; bool user_overridden; size_t size; @@ -98,6 +99,12 @@ struct intel_uc_fw { u16 major_ver_found; u16 minor_ver_found; + struct { + const char *path; + u16 major_ver; + u16 minor_ver; + } fallback; + u32 rsa_size; u32 ucode_size; diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 0ba2a3455d99..de13f102d4fd 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -3117,9 +3117,9 @@ void intel_gvt_update_reg_whitelist(struct intel_vgpu *vgpu) continue; vaddr = shmem_pin_map(engine->default_state); - if (IS_ERR(vaddr)) { - gvt_err("failed to map %s->default state, err:%zd\n", - engine->name, PTR_ERR(vaddr)); + if (!vaddr) { + gvt_err("failed to map %s->default state\n", + engine->name); return; } diff --git a/drivers/gpu/drm/i915/i915_active.c b/drivers/gpu/drm/i915/i915_active.c index ee2b3a375362..7412abf166a8 100644 --- a/drivers/gpu/drm/i915/i915_active.c +++ b/drivers/gpu/drm/i915/i915_active.c @@ -974,7 +974,7 @@ void i915_active_acquire_barrier(struct i915_active *ref) GEM_BUG_ON(!intel_engine_pm_is_awake(engine)); llist_add(barrier_to_ll(node), &engine->barrier_tasks); - intel_engine_pm_put_delay(engine, 1); + intel_engine_pm_put_delay(engine, 2); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c22f29c3faa0..d25647be25d1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1005,7 +1005,12 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define IS_XEHPSDV(dev_priv) IS_PLATFORM(dev_priv, INTEL_XEHPSDV) #define IS_DG2(dev_priv) IS_PLATFORM(dev_priv, INTEL_DG2) #define IS_PONTEVECCHIO(dev_priv) IS_PLATFORM(dev_priv, INTEL_PONTEVECCHIO) +#define IS_METEORLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_METEORLAKE) +#define IS_METEORLAKE_M(dev_priv) \ + IS_SUBPLATFORM(dev_priv, INTEL_METEORLAKE, INTEL_SUBPLATFORM_M) +#define IS_METEORLAKE_P(dev_priv) \ + IS_SUBPLATFORM(dev_priv, INTEL_METEORLAKE, INTEL_SUBPLATFORM_P) #define IS_DG2_G10(dev_priv) \ IS_SUBPLATFORM(dev_priv, INTEL_DG2, INTEL_SUBPLATFORM_G10) #define IS_DG2_G11(dev_priv) \ diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index f9b1969ed7ed..32e92651ef7c 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -46,6 +46,7 @@ #include "gem/i915_gem_lmem.h" #include "gt/intel_engine_regs.h" #include "gt/intel_gt.h" +#include "gt/intel_gt_mcr.h" #include "gt/intel_gt_pm.h" #include "gt/intel_gt_regs.h" #include "gt/uc/intel_guc_capture.h" @@ -436,7 +437,6 @@ static void err_compression_marker(struct drm_i915_error_state_buf *m) static void error_print_instdone(struct drm_i915_error_state_buf *m, const struct intel_engine_coredump *ee) { - const struct sseu_dev_info *sseu = &ee->engine->gt->info.sseu; int slice; int subslice; int iter; @@ -453,33 +453,21 @@ static void error_print_instdone(struct drm_i915_error_state_buf *m, if (GRAPHICS_VER(m->i915) <= 6) return; - if (GRAPHICS_VER_FULL(m->i915) >= IP_VER(12, 50)) { - for_each_instdone_gslice_dss_xehp(m->i915, sseu, iter, slice, subslice) - err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", - slice, subslice, - ee->instdone.sampler[slice][subslice]); - - for_each_instdone_gslice_dss_xehp(m->i915, sseu, iter, slice, subslice) - err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n", - slice, subslice, - ee->instdone.row[slice][subslice]); - } else { - for_each_instdone_slice_subslice(m->i915, sseu, slice, subslice) - err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", - slice, subslice, - ee->instdone.sampler[slice][subslice]); + for_each_ss_steering(iter, ee->engine->gt, slice, subslice) + err_printf(m, " SAMPLER_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, + ee->instdone.sampler[slice][subslice]); - for_each_instdone_slice_subslice(m->i915, sseu, slice, subslice) - err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n", - slice, subslice, - ee->instdone.row[slice][subslice]); - } + for_each_ss_steering(iter, ee->engine->gt, slice, subslice) + err_printf(m, " ROW_INSTDONE[%d][%d]: 0x%08x\n", + slice, subslice, + ee->instdone.row[slice][subslice]); if (GRAPHICS_VER(m->i915) < 12) return; if (GRAPHICS_VER_FULL(m->i915) >= IP_VER(12, 55)) { - for_each_instdone_gslice_dss_xehp(m->i915, sseu, iter, slice, subslice) + for_each_ss_steering(iter, ee->engine->gt, slice, subslice) err_printf(m, " GEOM_SVGUNIT_INSTDONE[%d][%d]: 0x%08x\n", slice, subslice, ee->instdone.geom_svg[slice][subslice]); @@ -1129,11 +1117,15 @@ i915_vma_coredump_create(const struct intel_gt *gt, dma_addr_t dma; for_each_sgt_daddr(dma, iter, vma_res->bi.pages) { + dma_addr_t offset = dma - mem->region.start; void __iomem *s; - s = io_mapping_map_wc(&mem->iomap, - dma - mem->region.start, - PAGE_SIZE); + if (offset + PAGE_SIZE > mem->io_size) { + ret = -EINVAL; + break; + } + + s = io_mapping_map_wc(&mem->iomap, offset, PAGE_SIZE); ret = compress_page(compress, (void __force *)s, dst, true); diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 701fbc98afa0..6fc475a5db61 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -204,6 +204,8 @@ i915_param_named_unsafe(request_timeout_ms, uint, 0600, i915_param_named_unsafe(lmem_size, uint, 0400, "Set the lmem size(in MiB) for each region. (default: 0, all memory)"); +i915_param_named_unsafe(lmem_bar_size, uint, 0400, + "Set the lmem bar size(in MiB)."); static __always_inline void _print_param(struct drm_printer *p, const char *name, diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index b5e7ea45d191..2733cb6cfe09 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -74,6 +74,7 @@ struct drm_printer; param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE, 0400) \ param(unsigned int, request_timeout_ms, CONFIG_DRM_I915_REQUEST_TIMEOUT, CONFIG_DRM_I915_REQUEST_TIMEOUT ? 0600 : 0) \ param(unsigned int, lmem_size, 0, 0400) \ + param(unsigned int, lmem_bar_size, 0, 0400) \ /* leave bools at the end to not create holes */ \ param(bool, enable_hangcheck, true, 0600) \ param(bool, load_detect_test, false, 0600) \ diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 5edc8fbf1dff..aacc10f2e73f 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1075,7 +1075,6 @@ static const struct intel_device_info dg2_info = { .require_force_probe = 1, }; -__maybe_unused static const struct intel_device_info ats_m_info = { DG2_FEATURES, .display = { 0 }, @@ -1108,6 +1107,31 @@ static const struct intel_device_info pvc_info = { .require_force_probe = 1, }; +#define XE_LPDP_FEATURES \ + XE_LPD_FEATURES, \ + .display.ver = 14, \ + .display.has_cdclk_crawl = 1 + +__maybe_unused +static const struct intel_device_info mtl_info = { + XE_HP_FEATURES, + XE_LPDP_FEATURES, + /* + * Real graphics IP version will be obtained from hardware GMD_ID + * register. Value provided here is just for sanity checking. + */ + .graphics.ver = 12, + .graphics.rel = 70, + .media.ver = 13, + PLATFORM(INTEL_METEORLAKE), + .display.has_modular_fia = 1, + .has_flat_ccs = 0, + .has_snoop = 1, + .memory_regions = REGION_SMEM | REGION_STOLEN_LMEM, + .platform_engine_mask = BIT(RCS0) | BIT(BCS0) | BIT(CCS0), + .require_force_probe = 1, +}; + #undef PLATFORM /* @@ -1189,6 +1213,8 @@ static const struct pci_device_id pciidlist[] = { INTEL_RPLS_IDS(&adl_s_info), INTEL_RPLP_IDS(&adl_p_info), INTEL_DG2_IDS(&dg2_info), + INTEL_ATS_M_IDS(&ats_m_info), + INTEL_MTL_IDS(&mtl_info), {0, 0, 0} }; MODULE_DEVICE_TABLE(pci, pciidlist); diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 1577ab6754db..f3c23fe9ad9c 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -885,8 +885,9 @@ static int gen8_oa_read(struct i915_perf_stream *stream, if (ret) return ret; - DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n", - stream->period_exponent); + drm_dbg(&stream->perf->i915->drm, + "OA buffer overflow (exponent = %d): force restart\n", + stream->period_exponent); stream->perf->ops.oa_disable(stream); stream->perf->ops.oa_enable(stream); @@ -1108,8 +1109,9 @@ static int gen7_oa_read(struct i915_perf_stream *stream, if (ret) return ret; - DRM_DEBUG("OA buffer overflow (exponent = %d): force restart\n", - stream->period_exponent); + drm_dbg(&stream->perf->i915->drm, + "OA buffer overflow (exponent = %d): force restart\n", + stream->period_exponent); stream->perf->ops.oa_disable(stream); stream->perf->ops.oa_enable(stream); @@ -2863,7 +2865,8 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, int ret; if (!props->engine) { - DRM_DEBUG("OA engine not specified\n"); + drm_dbg(&stream->perf->i915->drm, + "OA engine not specified\n"); return -EINVAL; } @@ -2873,18 +2876,21 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, * IDs */ if (!perf->metrics_kobj) { - DRM_DEBUG("OA metrics weren't advertised via sysfs\n"); + drm_dbg(&stream->perf->i915->drm, + "OA metrics weren't advertised via sysfs\n"); return -EINVAL; } if (!(props->sample_flags & SAMPLE_OA_REPORT) && (GRAPHICS_VER(perf->i915) < 12 || !stream->ctx)) { - DRM_DEBUG("Only OA report sampling supported\n"); + drm_dbg(&stream->perf->i915->drm, + "Only OA report sampling supported\n"); return -EINVAL; } if (!perf->ops.enable_metric_set) { - DRM_DEBUG("OA unit not supported\n"); + drm_dbg(&stream->perf->i915->drm, + "OA unit not supported\n"); return -ENODEV; } @@ -2894,12 +2900,14 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, * we currently only allow exclusive access */ if (perf->exclusive_stream) { - DRM_DEBUG("OA unit already in use\n"); + drm_dbg(&stream->perf->i915->drm, + "OA unit already in use\n"); return -EBUSY; } if (!props->oa_format) { - DRM_DEBUG("OA report format not specified\n"); + drm_dbg(&stream->perf->i915->drm, + "OA report format not specified\n"); return -EINVAL; } @@ -2929,20 +2937,23 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, if (stream->ctx) { ret = oa_get_render_ctx_id(stream); if (ret) { - DRM_DEBUG("Invalid context id to filter with\n"); + drm_dbg(&stream->perf->i915->drm, + "Invalid context id to filter with\n"); return ret; } } ret = alloc_noa_wait(stream); if (ret) { - DRM_DEBUG("Unable to allocate NOA wait batch buffer\n"); + drm_dbg(&stream->perf->i915->drm, + "Unable to allocate NOA wait batch buffer\n"); goto err_noa_wait_alloc; } stream->oa_config = i915_perf_get_oa_config(perf, props->metrics_set); if (!stream->oa_config) { - DRM_DEBUG("Invalid OA config id=%i\n", props->metrics_set); + drm_dbg(&stream->perf->i915->drm, + "Invalid OA config id=%i\n", props->metrics_set); ret = -EINVAL; goto err_config; } @@ -2973,11 +2984,13 @@ static int i915_oa_stream_init(struct i915_perf_stream *stream, ret = i915_perf_stream_enable_sync(stream); if (ret) { - DRM_DEBUG("Unable to enable metric set\n"); + drm_dbg(&stream->perf->i915->drm, + "Unable to enable metric set\n"); goto err_enable; } - DRM_DEBUG("opening stream oa config uuid=%s\n", + drm_dbg(&stream->perf->i915->drm, + "opening stream oa config uuid=%s\n", stream->oa_config->uuid); hrtimer_init(&stream->poll_check_timer, @@ -3429,7 +3442,8 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf, specific_ctx = i915_gem_context_lookup(file_priv, ctx_handle); if (IS_ERR(specific_ctx)) { - DRM_DEBUG("Failed to look up context with ID %u for opening perf stream\n", + drm_dbg(&perf->i915->drm, + "Failed to look up context with ID %u for opening perf stream\n", ctx_handle); ret = PTR_ERR(specific_ctx); goto err; @@ -3463,7 +3477,8 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf, if (props->hold_preemption) { if (!props->single_context) { - DRM_DEBUG("preemption disable with no context\n"); + drm_dbg(&perf->i915->drm, + "preemption disable with no context\n"); ret = -EINVAL; goto err; } @@ -3485,7 +3500,8 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf, */ if (privileged_op && i915_perf_stream_paranoid && !perfmon_capable()) { - DRM_DEBUG("Insufficient privileges to open i915 perf stream\n"); + drm_dbg(&perf->i915->drm, + "Insufficient privileges to open i915 perf stream\n"); ret = -EACCES; goto err_ctx; } @@ -3592,7 +3608,8 @@ static int read_properties_unlocked(struct i915_perf *perf, props->poll_oa_period = DEFAULT_POLL_PERIOD_NS; if (!n_props) { - DRM_DEBUG("No i915 perf properties given\n"); + drm_dbg(&perf->i915->drm, + "No i915 perf properties given\n"); return -EINVAL; } @@ -3601,7 +3618,8 @@ static int read_properties_unlocked(struct i915_perf *perf, I915_ENGINE_CLASS_RENDER, 0); if (!props->engine) { - DRM_DEBUG("No RENDER-capable engines\n"); + drm_dbg(&perf->i915->drm, + "No RENDER-capable engines\n"); return -EINVAL; } @@ -3612,7 +3630,8 @@ static int read_properties_unlocked(struct i915_perf *perf, * from userspace. */ if (n_props >= DRM_I915_PERF_PROP_MAX) { - DRM_DEBUG("More i915 perf properties specified than exist\n"); + drm_dbg(&perf->i915->drm, + "More i915 perf properties specified than exist\n"); return -EINVAL; } @@ -3629,7 +3648,8 @@ static int read_properties_unlocked(struct i915_perf *perf, return ret; if (id == 0 || id >= DRM_I915_PERF_PROP_MAX) { - DRM_DEBUG("Unknown i915 perf property ID\n"); + drm_dbg(&perf->i915->drm, + "Unknown i915 perf property ID\n"); return -EINVAL; } @@ -3644,19 +3664,22 @@ static int read_properties_unlocked(struct i915_perf *perf, break; case DRM_I915_PERF_PROP_OA_METRICS_SET: if (value == 0) { - DRM_DEBUG("Unknown OA metric set ID\n"); + drm_dbg(&perf->i915->drm, + "Unknown OA metric set ID\n"); return -EINVAL; } props->metrics_set = value; break; case DRM_I915_PERF_PROP_OA_FORMAT: if (value == 0 || value >= I915_OA_FORMAT_MAX) { - DRM_DEBUG("Out-of-range OA report format %llu\n", + drm_dbg(&perf->i915->drm, + "Out-of-range OA report format %llu\n", value); return -EINVAL; } if (!oa_format_valid(perf, value)) { - DRM_DEBUG("Unsupported OA report format %llu\n", + drm_dbg(&perf->i915->drm, + "Unsupported OA report format %llu\n", value); return -EINVAL; } @@ -3664,7 +3687,8 @@ static int read_properties_unlocked(struct i915_perf *perf, break; case DRM_I915_PERF_PROP_OA_EXPONENT: if (value > OA_EXPONENT_MAX) { - DRM_DEBUG("OA timer exponent too high (> %u)\n", + drm_dbg(&perf->i915->drm, + "OA timer exponent too high (> %u)\n", OA_EXPONENT_MAX); return -EINVAL; } @@ -3692,7 +3716,8 @@ static int read_properties_unlocked(struct i915_perf *perf, oa_freq_hz = 0; if (oa_freq_hz > i915_oa_max_sample_rate && !perfmon_capable()) { - DRM_DEBUG("OA exponent would exceed the max sampling frequency (sysctl dev.i915.oa_max_sample_rate) %uHz without CAP_PERFMON or CAP_SYS_ADMIN privileges\n", + drm_dbg(&perf->i915->drm, + "OA exponent would exceed the max sampling frequency (sysctl dev.i915.oa_max_sample_rate) %uHz without CAP_PERFMON or CAP_SYS_ADMIN privileges\n", i915_oa_max_sample_rate); return -EACCES; } @@ -3706,16 +3731,25 @@ static int read_properties_unlocked(struct i915_perf *perf, case DRM_I915_PERF_PROP_GLOBAL_SSEU: { struct drm_i915_gem_context_param_sseu user_sseu; + if (GRAPHICS_VER_FULL(perf->i915) >= IP_VER(12, 50)) { + drm_dbg(&perf->i915->drm, + "SSEU config not supported on gfx %x\n", + GRAPHICS_VER_FULL(perf->i915)); + return -ENODEV; + } + if (copy_from_user(&user_sseu, u64_to_user_ptr(value), sizeof(user_sseu))) { - DRM_DEBUG("Unable to copy global sseu parameter\n"); + drm_dbg(&perf->i915->drm, + "Unable to copy global sseu parameter\n"); return -EFAULT; } ret = get_sseu_config(&props->sseu, props->engine, &user_sseu); if (ret) { - DRM_DEBUG("Invalid SSEU configuration\n"); + drm_dbg(&perf->i915->drm, + "Invalid SSEU configuration\n"); return ret; } props->has_sseu = true; @@ -3723,7 +3757,8 @@ static int read_properties_unlocked(struct i915_perf *perf, } case DRM_I915_PERF_PROP_POLL_OA_PERIOD: if (value < 100000 /* 100us */) { - DRM_DEBUG("OA availability timer too small (%lluns < 100us)\n", + drm_dbg(&perf->i915->drm, + "OA availability timer too small (%lluns < 100us)\n", value); return -EINVAL; } @@ -3774,7 +3809,8 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data, int ret; if (!perf->i915) { - DRM_DEBUG("i915 perf interface not available for this system\n"); + drm_dbg(&perf->i915->drm, + "i915 perf interface not available for this system\n"); return -ENOTSUPP; } @@ -3782,7 +3818,8 @@ int i915_perf_open_ioctl(struct drm_device *dev, void *data, I915_PERF_FLAG_FD_NONBLOCK | I915_PERF_FLAG_DISABLED; if (param->flags & ~known_open_flags) { - DRM_DEBUG("Unknown drm_i915_perf_open_param flag\n"); + drm_dbg(&perf->i915->drm, + "Unknown drm_i915_perf_open_param flag\n"); return -EINVAL; } @@ -4028,7 +4065,8 @@ static struct i915_oa_reg *alloc_oa_regs(struct i915_perf *perf, goto addr_err; if (!is_valid(perf, addr)) { - DRM_DEBUG("Invalid oa_reg address: %X\n", addr); + drm_dbg(&perf->i915->drm, + "Invalid oa_reg address: %X\n", addr); err = -EINVAL; goto addr_err; } @@ -4102,30 +4140,35 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, int err, id; if (!perf->i915) { - DRM_DEBUG("i915 perf interface not available for this system\n"); + drm_dbg(&perf->i915->drm, + "i915 perf interface not available for this system\n"); return -ENOTSUPP; } if (!perf->metrics_kobj) { - DRM_DEBUG("OA metrics weren't advertised via sysfs\n"); + drm_dbg(&perf->i915->drm, + "OA metrics weren't advertised via sysfs\n"); return -EINVAL; } if (i915_perf_stream_paranoid && !perfmon_capable()) { - DRM_DEBUG("Insufficient privileges to add i915 OA config\n"); + drm_dbg(&perf->i915->drm, + "Insufficient privileges to add i915 OA config\n"); return -EACCES; } if ((!args->mux_regs_ptr || !args->n_mux_regs) && (!args->boolean_regs_ptr || !args->n_boolean_regs) && (!args->flex_regs_ptr || !args->n_flex_regs)) { - DRM_DEBUG("No OA registers given\n"); + drm_dbg(&perf->i915->drm, + "No OA registers given\n"); return -EINVAL; } oa_config = kzalloc(sizeof(*oa_config), GFP_KERNEL); if (!oa_config) { - DRM_DEBUG("Failed to allocate memory for the OA config\n"); + drm_dbg(&perf->i915->drm, + "Failed to allocate memory for the OA config\n"); return -ENOMEM; } @@ -4133,7 +4176,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, kref_init(&oa_config->ref); if (!uuid_is_valid(args->uuid)) { - DRM_DEBUG("Invalid uuid format for OA config\n"); + drm_dbg(&perf->i915->drm, + "Invalid uuid format for OA config\n"); err = -EINVAL; goto reg_err; } @@ -4150,7 +4194,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, args->n_mux_regs); if (IS_ERR(regs)) { - DRM_DEBUG("Failed to create OA config for mux_regs\n"); + drm_dbg(&perf->i915->drm, + "Failed to create OA config for mux_regs\n"); err = PTR_ERR(regs); goto reg_err; } @@ -4163,7 +4208,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, args->n_boolean_regs); if (IS_ERR(regs)) { - DRM_DEBUG("Failed to create OA config for b_counter_regs\n"); + drm_dbg(&perf->i915->drm, + "Failed to create OA config for b_counter_regs\n"); err = PTR_ERR(regs); goto reg_err; } @@ -4182,7 +4228,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, args->n_flex_regs); if (IS_ERR(regs)) { - DRM_DEBUG("Failed to create OA config for flex_regs\n"); + drm_dbg(&perf->i915->drm, + "Failed to create OA config for flex_regs\n"); err = PTR_ERR(regs); goto reg_err; } @@ -4198,7 +4245,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, */ idr_for_each_entry(&perf->metrics_idr, tmp, id) { if (!strcmp(tmp->uuid, oa_config->uuid)) { - DRM_DEBUG("OA config already exists with this uuid\n"); + drm_dbg(&perf->i915->drm, + "OA config already exists with this uuid\n"); err = -EADDRINUSE; goto sysfs_err; } @@ -4206,7 +4254,8 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, err = create_dynamic_oa_sysfs_entry(perf, oa_config); if (err) { - DRM_DEBUG("Failed to create sysfs entry for OA config\n"); + drm_dbg(&perf->i915->drm, + "Failed to create sysfs entry for OA config\n"); goto sysfs_err; } @@ -4215,14 +4264,16 @@ int i915_perf_add_config_ioctl(struct drm_device *dev, void *data, oa_config, 2, 0, GFP_KERNEL); if (oa_config->id < 0) { - DRM_DEBUG("Failed to create sysfs entry for OA config\n"); + drm_dbg(&perf->i915->drm, + "Failed to create sysfs entry for OA config\n"); err = oa_config->id; goto sysfs_err; } mutex_unlock(&perf->metrics_lock); - DRM_DEBUG("Added config %s id=%i\n", oa_config->uuid, oa_config->id); + drm_dbg(&perf->i915->drm, + "Added config %s id=%i\n", oa_config->uuid, oa_config->id); return oa_config->id; @@ -4230,7 +4281,8 @@ sysfs_err: mutex_unlock(&perf->metrics_lock); reg_err: i915_oa_config_put(oa_config); - DRM_DEBUG("Failed to add new OA config\n"); + drm_dbg(&perf->i915->drm, + "Failed to add new OA config\n"); return err; } @@ -4254,12 +4306,14 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data, int ret; if (!perf->i915) { - DRM_DEBUG("i915 perf interface not available for this system\n"); + drm_dbg(&perf->i915->drm, + "i915 perf interface not available for this system\n"); return -ENOTSUPP; } if (i915_perf_stream_paranoid && !perfmon_capable()) { - DRM_DEBUG("Insufficient privileges to remove i915 OA config\n"); + drm_dbg(&perf->i915->drm, + "Insufficient privileges to remove i915 OA config\n"); return -EACCES; } @@ -4269,7 +4323,8 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data, oa_config = idr_find(&perf->metrics_idr, *arg); if (!oa_config) { - DRM_DEBUG("Failed to remove unknown OA config\n"); + drm_dbg(&perf->i915->drm, + "Failed to remove unknown OA config\n"); ret = -ENOENT; goto err_unlock; } @@ -4282,7 +4337,8 @@ int i915_perf_remove_config_ioctl(struct drm_device *dev, void *data, mutex_unlock(&perf->metrics_lock); - DRM_DEBUG("Removed config %s id=%i\n", oa_config->uuid, oa_config->id); + drm_dbg(&perf->i915->drm, + "Removed config %s id=%i\n", oa_config->uuid, oa_config->id); i915_oa_config_put(oa_config); diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index 0094f67c63f2..6ec9c9fb7b0d 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -498,7 +498,21 @@ static int query_memregion_info(struct drm_i915_private *i915, info.region.memory_class = mr->type; info.region.memory_instance = mr->instance; info.probed_size = mr->total; - info.unallocated_size = mr->avail; + + if (mr->type == INTEL_MEMORY_LOCAL) + info.probed_cpu_visible_size = mr->io_size; + else + info.probed_cpu_visible_size = mr->total; + + if (perfmon_capable()) { + intel_memory_region_avail(mr, + &info.unallocated_size, + &info.unallocated_cpu_visible_size); + } else { + info.unallocated_size = info.probed_size; + info.unallocated_cpu_visible_size = + info.probed_cpu_visible_size; + } if (__copy_to_user(info_ptr, &info, sizeof(info))) return -EFAULT; diff --git a/drivers/gpu/drm/i915/i915_scatterlist.c b/drivers/gpu/drm/i915/i915_scatterlist.c index 159571b9bd24..dcc081874ec8 100644 --- a/drivers/gpu/drm/i915/i915_scatterlist.c +++ b/drivers/gpu/drm/i915/i915_scatterlist.c @@ -68,6 +68,7 @@ void i915_refct_sgt_init(struct i915_refct_sgt *rsgt, size_t size) * drm_mm_node * @node: The drm_mm_node. * @region_start: An offset to add to the dma addresses of the sg list. + * @page_alignment: Required page alignment for each sg entry. Power of two. * * Create a struct sg_table, initializing it from a struct drm_mm_node, * taking a maximum segment length into account, splitting into segments @@ -77,22 +78,25 @@ void i915_refct_sgt_init(struct i915_refct_sgt *rsgt, size_t size) * error code cast to an error pointer on failure. */ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node, - u64 region_start) + u64 region_start, + u32 page_alignment) { - const u64 max_segment = SZ_1G; /* Do we have a limit on this? */ - u64 segment_pages = max_segment >> PAGE_SHIFT; + const u32 max_segment = round_down(UINT_MAX, page_alignment); + const u32 segment_pages = max_segment >> PAGE_SHIFT; u64 block_size, offset, prev_end; struct i915_refct_sgt *rsgt; struct sg_table *st; struct scatterlist *sg; + GEM_BUG_ON(!max_segment); + rsgt = kmalloc(sizeof(*rsgt), GFP_KERNEL); if (!rsgt) return ERR_PTR(-ENOMEM); i915_refct_sgt_init(rsgt, node->size << PAGE_SHIFT); st = &rsgt->table; - if (sg_alloc_table(st, DIV_ROUND_UP(node->size, segment_pages), + if (sg_alloc_table(st, DIV_ROUND_UP_ULL(node->size, segment_pages), GFP_KERNEL)) { i915_refct_sgt_put(rsgt); return ERR_PTR(-ENOMEM); @@ -112,12 +116,14 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node, sg = __sg_next(sg); sg_dma_address(sg) = region_start + offset; + GEM_BUG_ON(!IS_ALIGNED(sg_dma_address(sg), + page_alignment)); sg_dma_len(sg) = 0; sg->length = 0; st->nents++; } - len = min(block_size, max_segment - sg->length); + len = min_t(u64, block_size, max_segment - sg->length); sg->length += len; sg_dma_len(sg) += len; @@ -138,6 +144,7 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node, * i915_buddy_block list * @res: The struct i915_ttm_buddy_resource. * @region_start: An offset to add to the dma addresses of the sg list. + * @page_alignment: Required page alignment for each sg entry. Power of two. * * Create a struct sg_table, initializing it from struct i915_buddy_block list, * taking a maximum segment length into account, splitting into segments @@ -147,11 +154,12 @@ struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node, * error code cast to an error pointer on failure. */ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res, - u64 region_start) + u64 region_start, + u32 page_alignment) { struct i915_ttm_buddy_resource *bman_res = to_ttm_buddy_resource(res); const u64 size = res->num_pages << PAGE_SHIFT; - const u64 max_segment = rounddown(UINT_MAX, PAGE_SIZE); + const u32 max_segment = round_down(UINT_MAX, page_alignment); struct drm_buddy *mm = bman_res->mm; struct list_head *blocks = &bman_res->blocks; struct drm_buddy_block *block; @@ -161,6 +169,7 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res, resource_size_t prev_end; GEM_BUG_ON(list_empty(blocks)); + GEM_BUG_ON(!max_segment); rsgt = kmalloc(sizeof(*rsgt), GFP_KERNEL); if (!rsgt) @@ -191,12 +200,14 @@ struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res, sg = __sg_next(sg); sg_dma_address(sg) = region_start + offset; + GEM_BUG_ON(!IS_ALIGNED(sg_dma_address(sg), + page_alignment)); sg_dma_len(sg) = 0; sg->length = 0; st->nents++; } - len = min(block_size, max_segment - sg->length); + len = min_t(u64, block_size, max_segment - sg->length); sg->length += len; sg_dma_len(sg) += len; diff --git a/drivers/gpu/drm/i915/i915_scatterlist.h b/drivers/gpu/drm/i915/i915_scatterlist.h index 12c6a1684081..9ddb3e743a3e 100644 --- a/drivers/gpu/drm/i915/i915_scatterlist.h +++ b/drivers/gpu/drm/i915/i915_scatterlist.h @@ -213,9 +213,11 @@ static inline void __i915_refct_sgt_init(struct i915_refct_sgt *rsgt, void i915_refct_sgt_init(struct i915_refct_sgt *rsgt, size_t size); struct i915_refct_sgt *i915_rsgt_from_mm_node(const struct drm_mm_node *node, - u64 region_start); + u64 region_start, + u32 page_alignment); struct i915_refct_sgt *i915_rsgt_from_buddy_resource(struct ttm_resource *res, - u64 region_start); + u64 region_start, + u32 page_alignment); #endif diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c index a5109548abc0..427de1aaab36 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -104,18 +104,15 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, min_page_size, &bman_res->blocks, bman_res->flags); - mutex_unlock(&bman->lock); if (unlikely(err)) goto err_free_blocks; if (place->flags & TTM_PL_FLAG_CONTIGUOUS) { u64 original_size = (u64)bman_res->base.num_pages << PAGE_SHIFT; - mutex_lock(&bman->lock); drm_buddy_block_trim(mm, original_size, &bman_res->blocks); - mutex_unlock(&bman->lock); } if (lpfn <= bman->visible_size) { @@ -137,11 +134,10 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, } } - if (bman_res->used_visible_size) { - mutex_lock(&bman->lock); + if (bman_res->used_visible_size) bman->visible_avail -= bman_res->used_visible_size; - mutex_unlock(&bman->lock); - } + + mutex_unlock(&bman->lock); if (place->lpfn - place->fpfn == n_pages) bman_res->base.start = place->fpfn; @@ -154,7 +150,6 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, return 0; err_free_blocks: - mutex_lock(&bman->lock); drm_buddy_free_list(mm, &bman_res->blocks); mutex_unlock(&bman->lock); err_free_res: @@ -365,6 +360,26 @@ u64 i915_ttm_buddy_man_visible_size(struct ttm_resource_manager *man) return bman->visible_size; } +/** + * i915_ttm_buddy_man_avail - Query the avail tracking for the manager. + * + * @man: The buddy allocator ttm manager + * @avail: The total available memory in pages for the entire manager. + * @visible_avail: The total available memory in pages for the CPU visible + * portion. Note that this will always give the same value as @avail on + * configurations that don't have a small BAR. + */ +void i915_ttm_buddy_man_avail(struct ttm_resource_manager *man, + u64 *avail, u64 *visible_avail) +{ + struct i915_ttm_buddy_manager *bman = to_buddy_manager(man); + + mutex_lock(&bman->lock); + *avail = bman->mm.avail >> PAGE_SHIFT; + *visible_avail = bman->visible_avail; + mutex_unlock(&bman->lock); +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) void i915_ttm_buddy_man_force_visible_size(struct ttm_resource_manager *man, u64 size) diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h index 52d9586d242c..d64620712830 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.h @@ -61,6 +61,9 @@ int i915_ttm_buddy_man_reserve(struct ttm_resource_manager *man, u64 i915_ttm_buddy_man_visible_size(struct ttm_resource_manager *man); +void i915_ttm_buddy_man_avail(struct ttm_resource_manager *man, + u64 *avail, u64 *avail_visible); + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) void i915_ttm_buddy_man_force_visible_size(struct ttm_resource_manager *man, u64 size); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 5d5828b9a242..ef3b04c7e153 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -310,7 +310,7 @@ struct i915_vma_work { struct i915_address_space *vm; struct i915_vm_pt_stash stash; struct i915_vma_resource *vma_res; - struct drm_i915_gem_object *pinned; + struct drm_i915_gem_object *obj; struct i915_sw_dma_fence_cb cb; enum i915_cache_level cache_level; unsigned int flags; @@ -321,17 +321,25 @@ static void __vma_bind(struct dma_fence_work *work) struct i915_vma_work *vw = container_of(work, typeof(*vw), base); struct i915_vma_resource *vma_res = vw->vma_res; + /* + * We are about the bind the object, which must mean we have already + * signaled the work to potentially clear/move the pages underneath. If + * something went wrong at that stage then the object should have + * unknown_state set, in which case we need to skip the bind. + */ + if (i915_gem_object_has_unknown_state(vw->obj)) + return; + vma_res->ops->bind_vma(vma_res->vm, &vw->stash, vma_res, vw->cache_level, vw->flags); - } static void __vma_release(struct dma_fence_work *work) { struct i915_vma_work *vw = container_of(work, typeof(*vw), base); - if (vw->pinned) - i915_gem_object_put(vw->pinned); + if (vw->obj) + i915_gem_object_put(vw->obj); i915_vm_free_pt_stash(vw->vm, &vw->stash); if (vw->vma_res) @@ -517,14 +525,7 @@ int i915_vma_bind(struct i915_vma *vma, } work->base.dma.error = 0; /* enable the queue_work() */ - - /* - * If we don't have the refcounted pages list, keep a reference - * on the object to avoid waiting for the async bind to - * complete in the object destruction path. - */ - if (!work->vma_res->bi.pages_rsgt) - work->pinned = i915_gem_object_get(vma->obj); + work->obj = i915_gem_object_get(vma->obj); } else { ret = i915_gem_object_wait_moving_fence(vma->obj, true); if (ret) { @@ -1645,10 +1646,10 @@ static void force_unbind(struct i915_vma *vma) GEM_BUG_ON(drm_mm_node_allocated(&vma->node)); } -static void release_references(struct i915_vma *vma, bool vm_ddestroy) +static void release_references(struct i915_vma *vma, struct intel_gt *gt, + bool vm_ddestroy) { struct drm_i915_gem_object *obj = vma->obj; - struct intel_gt *gt = vma->vm->gt; GEM_BUG_ON(i915_vma_is_active(vma)); @@ -1703,11 +1704,12 @@ void i915_vma_destroy_locked(struct i915_vma *vma) force_unbind(vma); list_del_init(&vma->vm_link); - release_references(vma, false); + release_references(vma, vma->vm->gt, false); } void i915_vma_destroy(struct i915_vma *vma) { + struct intel_gt *gt; bool vm_ddestroy; mutex_lock(&vma->vm->mutex); @@ -1715,8 +1717,11 @@ void i915_vma_destroy(struct i915_vma *vma) list_del_init(&vma->vm_link); vm_ddestroy = vma->vm_ddestroy; vma->vm_ddestroy = false; + + /* vma->vm may be freed when releasing vma->vm->mutex. */ + gt = vma->vm->gt; mutex_unlock(&vma->vm->mutex); - release_references(vma, vm_ddestroy); + release_references(vma, gt, vm_ddestroy); } void i915_vma_parked(struct intel_gt *gt) diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 7eb893666595..d98fbbd589aa 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -73,6 +73,7 @@ static const char * const platform_names[] = { PLATFORM_NAME(XEHPSDV), PLATFORM_NAME(DG2), PLATFORM_NAME(PONTEVECCHIO), + PLATFORM_NAME(METEORLAKE), }; #undef PLATFORM_NAME @@ -189,16 +190,26 @@ static const u16 subplatform_rpl_ids[] = { static const u16 subplatform_g10_ids[] = { INTEL_DG2_G10_IDS(0), + INTEL_ATS_M150_IDS(0), }; static const u16 subplatform_g11_ids[] = { INTEL_DG2_G11_IDS(0), + INTEL_ATS_M75_IDS(0), }; static const u16 subplatform_g12_ids[] = { INTEL_DG2_G12_IDS(0), }; +static const u16 subplatform_m_ids[] = { + INTEL_MTL_M_IDS(0), +}; + +static const u16 subplatform_p_ids[] = { + INTEL_MTL_P_IDS(0), +}; + static bool find_devid(u16 id, const u16 *p, unsigned int num) { for (; num; num--, p++) { @@ -253,6 +264,12 @@ void intel_device_info_subplatform_init(struct drm_i915_private *i915) } else if (find_devid(devid, subplatform_g12_ids, ARRAY_SIZE(subplatform_g12_ids))) { mask = BIT(INTEL_SUBPLATFORM_G12); + } else if (find_devid(devid, subplatform_m_ids, + ARRAY_SIZE(subplatform_m_ids))) { + mask = BIT(INTEL_SUBPLATFORM_M); + } else if (find_devid(devid, subplatform_p_ids, + ARRAY_SIZE(subplatform_p_ids))) { + mask = BIT(INTEL_SUBPLATFORM_P); } GEM_BUG_ON(mask & ~INTEL_SUBPLATFORM_MASK); diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 1c150cd7dceb..23bf230aa104 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -89,6 +89,7 @@ enum intel_platform { INTEL_XEHPSDV, INTEL_DG2, INTEL_PONTEVECCHIO, + INTEL_METEORLAKE, INTEL_MAX_PLATFORMS }; @@ -126,6 +127,10 @@ enum intel_platform { */ #define INTEL_SUBPLATFORM_N 1 +/* MTL */ +#define INTEL_SUBPLATFORM_M 0 +#define INTEL_SUBPLATFORM_P 1 + enum intel_ppgtt_type { INTEL_PPGTT_NONE = I915_GEM_PPGTT_NONE, INTEL_PPGTT_ALIASING = I915_GEM_PPGTT_ALIASING, diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index e38d2db1c3e3..9a4a7fb55582 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -198,8 +198,7 @@ void intel_memory_region_debug(struct intel_memory_region *mr, if (mr->region_private) ttm_resource_manager_debug(mr->region_private, printer); else - drm_printf(printer, "total:%pa, available:%pa bytes\n", - &mr->total, &mr->avail); + drm_printf(printer, "total:%pa bytes\n", &mr->total); } static int intel_memory_region_memtest(struct intel_memory_region *mem, @@ -242,7 +241,6 @@ intel_memory_region_create(struct drm_i915_private *i915, mem->min_page_size = min_page_size; mem->ops = ops; mem->total = size; - mem->avail = mem->total; mem->type = type; mem->instance = instance; @@ -279,6 +277,20 @@ void intel_memory_region_set_name(struct intel_memory_region *mem, va_end(ap); } +void intel_memory_region_avail(struct intel_memory_region *mr, + u64 *avail, u64 *visible_avail) +{ + if (mr->type == INTEL_MEMORY_LOCAL) { + i915_ttm_buddy_man_avail(mr->region_private, + avail, visible_avail); + *avail <<= PAGE_SHIFT; + *visible_avail <<= PAGE_SHIFT; + } else { + *avail = mr->total; + *visible_avail = mr->total; + } +} + void intel_memory_region_destroy(struct intel_memory_region *mem) { int ret = 0; diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h index 3d8378c1b447..2953ed5c3248 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.h +++ b/drivers/gpu/drm/i915/intel_memory_region.h @@ -75,7 +75,6 @@ struct intel_memory_region { resource_size_t io_size; resource_size_t min_page_size; resource_size_t total; - resource_size_t avail; u16 type; u16 instance; @@ -127,6 +126,9 @@ int intel_memory_region_reserve(struct intel_memory_region *mem, void intel_memory_region_debug(struct intel_memory_region *mr, struct drm_printer *printer); +void intel_memory_region_avail(struct intel_memory_region *mr, + u64 *avail, u64 *visible_avail); + struct intel_memory_region * i915_gem_ttm_system_setup(struct drm_i915_private *i915, u16 type, u16 instance); diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c index 62ff77445b01..575d67bc6ffe 100644 --- a/drivers/gpu/drm/i915/intel_region_ttm.c +++ b/drivers/gpu/drm/i915/intel_region_ttm.c @@ -152,6 +152,7 @@ int intel_region_ttm_fini(struct intel_memory_region *mem) * Convert an opaque TTM resource manager resource to a refcounted sg_table. * @mem: The memory region. * @res: The resource manager resource obtained from the TTM resource manager. + * @page_alignment: Required page alignment for each sg entry. Power of two. * * The gem backends typically use sg-tables for operations on the underlying * io_memory. So provide a way for the backends to translate the @@ -161,16 +162,19 @@ int intel_region_ttm_fini(struct intel_memory_region *mem) */ struct i915_refct_sgt * intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem, - struct ttm_resource *res) + struct ttm_resource *res, + u32 page_alignment) { if (mem->is_range_manager) { struct ttm_range_mgr_node *range_node = to_ttm_range_mgr_node(res); return i915_rsgt_from_mm_node(&range_node->mm_nodes[0], - mem->region.start); + mem->region.start, + page_alignment); } else { - return i915_rsgt_from_buddy_resource(res, mem->region.start); + return i915_rsgt_from_buddy_resource(res, mem->region.start, + page_alignment); } } diff --git a/drivers/gpu/drm/i915/intel_region_ttm.h b/drivers/gpu/drm/i915/intel_region_ttm.h index cf9d86dcf409..5bb8d8b582ae 100644 --- a/drivers/gpu/drm/i915/intel_region_ttm.h +++ b/drivers/gpu/drm/i915/intel_region_ttm.h @@ -24,7 +24,8 @@ int intel_region_ttm_fini(struct intel_memory_region *mem); struct i915_refct_sgt * intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem, - struct ttm_resource *res); + struct ttm_resource *res, + u32 page_alignment); void intel_region_ttm_resource_free(struct intel_memory_region *mem, struct ttm_resource *res); diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 8633bec18fa7..ab9f17fc85bc 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -742,7 +742,7 @@ static int pot_hole(struct i915_address_space *vm, u64 addr; for (addr = round_up(hole_start + min_alignment, step) - min_alignment; - addr <= round_down(hole_end - (2 * min_alignment), step) - min_alignment; + hole_end > addr && hole_end - addr >= 2 * min_alignment; addr += step) { err = i915_vma_pin(vma, 0, 0, addr | flags); if (err) { diff --git a/drivers/gpu/drm/i915/selftests/intel_memory_region.c b/drivers/gpu/drm/i915/selftests/intel_memory_region.c index 73eb53edb8de..3b18e5905c86 100644 --- a/drivers/gpu/drm/i915/selftests/intel_memory_region.c +++ b/drivers/gpu/drm/i915/selftests/intel_memory_region.c @@ -451,7 +451,6 @@ out_put: static int igt_mock_max_segment(void *arg) { - const unsigned int max_segment = rounddown(UINT_MAX, PAGE_SIZE); struct intel_memory_region *mem = arg; struct drm_i915_private *i915 = mem->i915; struct i915_ttm_buddy_resource *res; @@ -460,7 +459,10 @@ static int igt_mock_max_segment(void *arg) struct drm_buddy *mm; struct list_head *blocks; struct scatterlist *sg; + I915_RND_STATE(prng); LIST_HEAD(objects); + unsigned int max_segment; + unsigned int ps; u64 size; int err = 0; @@ -472,7 +474,13 @@ static int igt_mock_max_segment(void *arg) */ size = SZ_8G; - mem = mock_region_create(i915, 0, size, PAGE_SIZE, 0, 0); + ps = PAGE_SIZE; + if (i915_prandom_u64_state(&prng) & 1) + ps = SZ_64K; /* For something like DG2 */ + + max_segment = round_down(UINT_MAX, ps); + + mem = mock_region_create(i915, 0, size, ps, 0, 0); if (IS_ERR(mem)) return PTR_ERR(mem); @@ -498,12 +506,21 @@ static int igt_mock_max_segment(void *arg) } for (sg = obj->mm.pages->sgl; sg; sg = sg_next(sg)) { + dma_addr_t daddr = sg_dma_address(sg); + if (sg->length > max_segment) { pr_err("%s: Created an oversized scatterlist entry, %u > %u\n", __func__, sg->length, max_segment); err = -EINVAL; goto out_close; } + + if (!IS_ALIGNED(daddr, ps)) { + pr_err("%s: Created an unaligned scatterlist entry, addr=%pa, ps=%u\n", + __func__, &daddr, ps); + err = -EINVAL; + goto out_close; + } } out_close: diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c index 670557ce1024..bac21fe84ca5 100644 --- a/drivers/gpu/drm/i915/selftests/mock_region.c +++ b/drivers/gpu/drm/i915/selftests/mock_region.c @@ -33,7 +33,8 @@ static int mock_region_get_pages(struct drm_i915_gem_object *obj) return PTR_ERR(obj->mm.res); obj->mm.rsgt = intel_region_ttm_resource_to_rsgt(obj->mm.region, - obj->mm.res); + obj->mm.res, + obj->mm.region->min_page_size); if (IS_ERR(obj->mm.rsgt)) { err = PTR_ERR(obj->mm.rsgt); goto err_free_resource; diff --git a/drivers/gpu/drm/imx/dcss/dcss-dev.c b/drivers/gpu/drm/imx/dcss/dcss-dev.c index c849533ca83e..3f5750cc2673 100644 --- a/drivers/gpu/drm/imx/dcss/dcss-dev.c +++ b/drivers/gpu/drm/imx/dcss/dcss-dev.c @@ -207,6 +207,7 @@ struct dcss_dev *dcss_dev_create(struct device *dev, bool hdmi_output) ret = dcss_submodules_init(dcss); if (ret) { + of_node_put(dcss->of_port); dev_err(dev, "submodules initialization failed\n"); goto clks_err; } @@ -237,6 +238,8 @@ void dcss_dev_destroy(struct dcss_dev *dcss) dcss_clocks_disable(dcss); } + of_node_put(dcss->of_port); + pm_runtime_disable(dcss->dev); dcss_submodules_stop(dcss); diff --git a/drivers/gpu/drm/lima/lima_devfreq.c b/drivers/gpu/drm/lima/lima_devfreq.c index 8989e215dfc9..011be7ff51e1 100644 --- a/drivers/gpu/drm/lima/lima_devfreq.c +++ b/drivers/gpu/drm/lima/lima_devfreq.c @@ -111,6 +111,12 @@ int lima_devfreq_init(struct lima_device *ldev) struct dev_pm_opp *opp; unsigned long cur_freq; int ret; + const char *regulator_names[] = { "mali", NULL }; + const char *clk_names[] = { "core", NULL }; + struct dev_pm_opp_config config = { + .regulator_names = regulator_names, + .clk_names = clk_names, + }; if (!device_property_present(dev, "operating-points-v2")) /* Optional, continue without devfreq */ @@ -118,11 +124,7 @@ int lima_devfreq_init(struct lima_device *ldev) spin_lock_init(&ldevfreq->lock); - ret = devm_pm_opp_set_clkname(dev, "core"); - if (ret) - return ret; - - ret = devm_pm_opp_set_regulators(dev, (const char *[]){ "mali" }, 1); + ret = devm_pm_opp_set_config(dev, &config); if (ret) { /* Continue if the optional regulator is missing */ if (ret != -ENODEV) diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c index 259f3e6bec90..bb7e109534de 100644 --- a/drivers/gpu/drm/meson/meson_viu.c +++ b/drivers/gpu/drm/meson/meson_viu.c @@ -469,17 +469,17 @@ void meson_viu_init(struct meson_drm *priv) priv->io_base + _REG(VD2_IF0_LUMA_FIFO_SIZE)); if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { - writel_relaxed(VIU_OSD_BLEND_REORDER(0, 1) | - VIU_OSD_BLEND_REORDER(1, 0) | - VIU_OSD_BLEND_REORDER(2, 0) | - VIU_OSD_BLEND_REORDER(3, 0) | - VIU_OSD_BLEND_DIN_EN(1) | - VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 | - VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 | - VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 | - VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) | - VIU_OSD_BLEND_HOLD_LINES(4), - priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); + u32 val = (u32)VIU_OSD_BLEND_REORDER(0, 1) | + (u32)VIU_OSD_BLEND_REORDER(1, 0) | + (u32)VIU_OSD_BLEND_REORDER(2, 0) | + (u32)VIU_OSD_BLEND_REORDER(3, 0) | + (u32)VIU_OSD_BLEND_DIN_EN(1) | + (u32)VIU_OSD_BLEND1_DIN3_BYPASS_TO_DOUT1 | + (u32)VIU_OSD_BLEND1_DOUT_BYPASS_TO_BLEND2 | + (u32)VIU_OSD_BLEND_DIN0_BYPASS_TO_DOUT0 | + (u32)VIU_OSD_BLEND_BLEN2_PREMULT_EN(1) | + (u32)VIU_OSD_BLEND_HOLD_LINES(4); + writel_relaxed(val, priv->io_base + _REG(VIU_OSD_BLEND_CTRL)); writel_relaxed(OSD_BLEND_PATH_SEL_ENABLE, priv->io_base + _REG(OSD1_BLEND_SRC_CTRL)); diff --git a/drivers/gpu/drm/nouveau/dispnv50/base507c.c b/drivers/gpu/drm/nouveau/dispnv50/base507c.c index 788db043a342..cad5a646983a 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/base507c.c +++ b/drivers/gpu/drm/nouveau/dispnv50/base507c.c @@ -21,8 +21,7 @@ */ #include "base.h" -#include <nvif/cl507c.h> -#include <nvif/event.h> +#include <nvif/if0014.h> #include <nvif/push507c.h> #include <nvif/timer.h> @@ -306,8 +305,8 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format, struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data, struct nv50_wndw **pwndw) { - struct nv50_disp_base_channel_dma_v0 args = { - .head = head, + struct nvif_disp_chan_v0 args = { + .id = head, }; struct nouveau_display *disp = nouveau_display(drm->dev); struct nv50_disp *disp50 = nv50_disp(drm->dev); @@ -328,16 +327,6 @@ base507c_new_(const struct nv50_wndw_func *func, const u32 *format, return ret; } - ret = nvif_notify_ctor(&wndw->wndw.base.user, "kmsBaseNtfy", - wndw->notify.func, false, - NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT, - &(struct nvif_notify_uevent_req) {}, - sizeof(struct nvif_notify_uevent_req), - sizeof(struct nvif_notify_uevent_rep), - &wndw->notify); - if (ret) - return ret; - wndw->ntfy = NV50_DISP_BASE_NTFY(wndw->id); wndw->sema = NV50_DISP_BASE_SEM0(wndw->id); wndw->data = 0x00000000; diff --git a/drivers/gpu/drm/nouveau/dispnv50/core507d.c b/drivers/gpu/drm/nouveau/dispnv50/core507d.c index 1a1d806e0b01..e5bb5ca950c8 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/core507d.c +++ b/drivers/gpu/drm/nouveau/dispnv50/core507d.c @@ -22,7 +22,7 @@ #include "core.h" #include "head.h" -#include <nvif/cl507d.h> +#include <nvif/if0014.h> #include <nvif/push507c.h> #include <nvif/timer.h> @@ -157,7 +157,7 @@ int core507d_new_(const struct nv50_core_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_core **pcore) { - struct nv50_disp_core_channel_dma_v0 args = {}; + struct nvif_disp_chan_v0 args = {}; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_core *core; int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c index 00e19fd959ea..cd2c79e4b7af 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/curs507a.c +++ b/drivers/gpu/drm/nouveau/dispnv50/curs507a.c @@ -23,7 +23,7 @@ #include "core.h" #include "head.h" -#include <nvif/cl507a.h> +#include <nvif/if0014.h> #include <nvif/timer.h> #include <nvhw/class/cl507a.h> @@ -150,8 +150,8 @@ curs507a_new_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data, struct nv50_wndw **pwndw) { - struct nv50_disp_cursor_v0 args = { - .head = head, + struct nvif_disp_chan_v0 args = { + .id = head, }; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_wndw *wndw; diff --git a/drivers/gpu/drm/nouveau/dispnv50/disp.c b/drivers/gpu/drm/nouveau/dispnv50/disp.c index ade2988e85f3..a53d685a77eb 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv50/disp.c @@ -48,8 +48,8 @@ #include <nvif/class.h> #include <nvif/cl0002.h> #include <nvif/cl5070.h> -#include <nvif/cl507d.h> #include <nvif/event.h> +#include <nvif/if0014.h> #include <nvif/timer.h> #include <nvhw/class/cl507c.h> @@ -231,7 +231,7 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, struct nv50_dmac *dmac) { struct nouveau_cli *cli = (void *)device->object.client; - struct nv50_disp_core_channel_dma_v0 *args = data; + struct nvif_disp_chan_v0 *args = data; u8 type = NVIF_MEM_COHERENT; int ret; @@ -529,24 +529,15 @@ static enum drm_connector_status nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); - struct nv50_disp *disp = nv50_disp(encoder->dev); - struct { - struct nv50_disp_mthd_v1 base; - struct nv50_disp_dac_load_v0 load; - } args = { - .base.version = 1, - .base.method = NV50_DISP_MTHD_V1_DAC_LOAD, - .base.hasht = nv_encoder->dcb->hasht, - .base.hashm = nv_encoder->dcb->hashm, - }; + u32 loadval; int ret; - args.load.data = nouveau_drm(encoder->dev)->vbios.dactestval; - if (args.load.data == 0) - args.load.data = 340; + loadval = nouveau_drm(encoder->dev)->vbios.dactestval; + if (loadval == 0) + loadval = 340; - ret = nvif_mthd(&disp->disp->object, 0, &args, sizeof(args)); - if (ret || !args.load.load) + ret = nvif_outp_load_detect(&nv_encoder->outp, loadval); + if (ret <= 0) return connector_status_disconnected; return connector_status_connected; @@ -563,6 +554,10 @@ nv50_dac_help = { static void nv50_dac_destroy(struct drm_encoder *encoder) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + nvif_outp_dtor(&nv_encoder->outp); + drm_encoder_cleanup(encoder); kfree(encoder); } @@ -576,6 +571,7 @@ static int nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) { struct nouveau_drm *drm = nouveau_drm(connector->dev); + struct nv50_disp *disp = nv50_disp(connector->dev); struct nvkm_i2c *i2c = nvxx_i2c(&drm->client.device); struct nvkm_i2c_bus *bus; struct nouveau_encoder *nv_encoder; @@ -599,7 +595,7 @@ nv50_dac_create(struct drm_connector *connector, struct dcb_output *dcbe) drm_encoder_helper_add(encoder, &nv50_dac_help); drm_connector_attach_encoder(connector, encoder); - return 0; + return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp); } /* @@ -1822,6 +1818,9 @@ static void nv50_sor_destroy(struct drm_encoder *encoder) { struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + nvif_outp_dtor(&nv_encoder->outp); + nv50_mstm_del(&nv_encoder->dp.mstm); drm_encoder_cleanup(encoder); @@ -1918,7 +1917,7 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_output *dcbe) nv_encoder->i2c = &bus->i2c; } - return 0; + return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp); } /****************************************************************************** @@ -1999,6 +1998,10 @@ nv50_pior_help = { static void nv50_pior_destroy(struct drm_encoder *encoder) { + struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); + + nvif_outp_dtor(&nv_encoder->outp); + drm_encoder_cleanup(encoder); kfree(encoder); } @@ -2056,7 +2059,7 @@ nv50_pior_create(struct drm_connector *connector, struct dcb_output *dcbe) disp->core->func->pior->get_caps(disp, nv_encoder, ffs(dcbe->or) - 1); nv50_outp_dump_caps(drm, nv_encoder); - return 0; + return nvif_outp_ctor(disp->disp, nv_encoder->base.base.name, dcbe->id, &nv_encoder->outp); } /****************************************************************************** diff --git a/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c b/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c index a6c3a9b95bdb..752318cf3cf1 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c +++ b/drivers/gpu/drm/nouveau/dispnv50/oimm507b.c @@ -21,14 +21,14 @@ */ #include "oimm.h" -#include <nvif/cl507b.h> +#include <nvif/if0014.h> static int oimm507b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { - struct nv50_disp_overlay_v0 args = { - .head = wndw->id, + struct nvif_disp_chan_v0 args = { + .id = wndw->id, }; struct nv50_disp *disp = nv50_disp(drm->dev); int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c index afd6c7271de1..d4af69e903ad 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/ovly507e.c @@ -26,8 +26,7 @@ #include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> -#include <nvif/cl507e.h> -#include <nvif/event.h> +#include <nvif/if0014.h> #include <nvif/push507c.h> #include <nvhw/class/cl507e.h> @@ -147,8 +146,8 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, struct nouveau_drm *drm, int head, s32 oclass, u32 interlock_data, struct nv50_wndw **pwndw) { - struct nv50_disp_overlay_channel_dma_v0 args = { - .head = head, + struct nvif_disp_chan_v0 args = { + .id = head, }; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_wndw *wndw; @@ -169,16 +168,6 @@ ovly507e_new_(const struct nv50_wndw_func *func, const u32 *format, return ret; } - ret = nvif_notify_ctor(&wndw->wndw.base.user, "kmsOvlyNtfy", - wndw->notify.func, false, - NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT, - &(struct nvif_notify_uevent_req) {}, - sizeof(struct nvif_notify_uevent_req), - sizeof(struct nvif_notify_uevent_rep), - &wndw->notify); - if (ret) - return ret; - wndw->ntfy = NV50_DISP_OVLY_NTFY(wndw->id); wndw->sema = NV50_DISP_OVLY_SEM0(wndw->id); wndw->data = 0x00000000; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c index b390029c69ec..ee76b091d4ef 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wimmc37b.c @@ -23,7 +23,7 @@ #include "atom.h" #include "wndw.h" -#include <nvif/clc37b.h> +#include <nvif/if0014.h> #include <nvif/pushc37b.h> #include <nvhw/class/clc37b.h> @@ -68,9 +68,8 @@ static int wimmc37b_init_(const struct nv50_wimm_func *func, struct nouveau_drm *drm, s32 oclass, struct nv50_wndw *wndw) { - struct nvc37b_window_imm_channel_dma_v0 args = { - .pushbuf = 0xb0007b00 | wndw->id, - .index = wndw->id, + struct nvif_disp_chan_v0 args = { + .id = wndw->id, }; struct nv50_disp *disp = nv50_disp(drm->dev); int ret; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index b21f49f0eae5..7a2cceaee6e9 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -644,7 +644,6 @@ nv50_wndw_destroy(struct drm_plane *plane) nv50_wndw_ctxdma_del(ctxdma); } - nvif_notify_dtor(&wndw->notify); nv50_dmac_destroy(&wndw->wimm); nv50_dmac_destroy(&wndw->wndw); @@ -688,12 +687,6 @@ nv50_wndw = { .format_mod_supported = nv50_plane_format_mod_supported, }; -static int -nv50_wndw_notify(struct nvif_notify *notify) -{ - return NVIF_NOTIFY_KEEP; -} - static const u64 nv50_cursor_format_modifiers[] = { DRM_FORMAT_MOD_LINEAR, DRM_FORMAT_MOD_INVALID, @@ -747,8 +740,6 @@ nv50_wndw_new_(const struct nv50_wndw_func *func, struct drm_device *dev, return ret; } - wndw->notify.func = nv50_wndw_notify; - if (wndw->func->blend_set) { ret = drm_plane_create_zpos_property(&wndw->plane, nv50_wndw_zpos_default(&wndw->plane), 0, 254); diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.h b/drivers/gpu/drm/nouveau/dispnv50/wndw.h index 96542ce666fc..591c852f326b 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.h +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.h @@ -5,8 +5,6 @@ #include "atom.h" #include "lut.h" -#include <nvif/notify.h> - struct nv50_wndw_ctxdma { struct list_head head; struct nvif_object object; @@ -30,7 +28,6 @@ struct nv50_wndw { struct nv50_dmac wndw; struct nv50_dmac wimm; - struct nvif_notify notify; u16 ntfy; u16 sema; u32 data; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c index 183d2c0e65b6..082a66d59506 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc37e.c @@ -26,7 +26,7 @@ #include <drm/drm_plane_helper.h> #include <nouveau_bo.h> -#include <nvif/clc37e.h> +#include <nvif/if0014.h> #include <nvif/pushc37b.h> #include <nvhw/class/clc37e.h> @@ -351,9 +351,8 @@ wndwc37e_new_(const struct nv50_wndw_func *func, struct nouveau_drm *drm, enum drm_plane_type type, int index, s32 oclass, u32 heads, struct nv50_wndw **pwndw) { - struct nvc37e_window_channel_dma_v0 args = { - .pushbuf = 0xb0007e00 | index, - .index = index, + struct nvif_disp_chan_v0 args = { + .id = index, }; struct nv50_disp *disp = nv50_disp(drm->dev); struct nv50_wndw *wndw; diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c index 37f6da8b3f2a..31167c398708 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndwc57e.c @@ -26,7 +26,6 @@ #include <drm/drm_plane_helper.h> #include <nouveau_bo.h> -#include <nvif/clc37e.h> #include <nvif/pushc37b.h> #include <nvhw/class/clc57e.h> diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h index 53800fb46582..56affb606adf 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl5070.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl5070.h @@ -30,7 +30,6 @@ struct nv50_disp_mthd_v1 { __u8 version; #define NV50_DISP_MTHD_V1_ACQUIRE 0x01 #define NV50_DISP_MTHD_V1_RELEASE 0x02 -#define NV50_DISP_MTHD_V1_DAC_LOAD 0x11 #define NV50_DISP_MTHD_V1_SOR_HDA_ELD 0x21 #define NV50_DISP_MTHD_V1_SOR_HDMI_PWR 0x22 #define NV50_DISP_MTHD_V1_SOR_LVDS_SCRIPT 0x23 @@ -50,13 +49,6 @@ struct nv50_disp_acquire_v0 { __u8 pad04[4]; }; -struct nv50_disp_dac_load_v0 { - __u8 version; - __u8 load; - __u8 pad02[2]; - __u32 data; -}; - struct nv50_disp_sor_hda_eld_v0 { __u8 version; __u8 pad01[7]; diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507a.h b/drivers/gpu/drm/nouveau/include/nvif/cl507a.h deleted file mode 100644 index 3b2a9809b8ce..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507a.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507A_H__ -#define __NVIF_CL507A_H__ - -struct nv50_disp_cursor_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; -}; - -#define NV50_DISP_CURSOR_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507b.h b/drivers/gpu/drm/nouveau/include/nvif/cl507b.h deleted file mode 100644 index 0f3d05581ea5..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507b.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507B_H__ -#define __NVIF_CL507B_H__ - -struct nv50_disp_overlay_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; -}; - -#define NV50_DISP_OVERLAY_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507c.h b/drivers/gpu/drm/nouveau/include/nvif/cl507c.h deleted file mode 100644 index 7da8813f4f5c..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507c.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507C_H__ -#define __NVIF_CL507C_H__ - -struct nv50_disp_base_channel_dma_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; - __u64 pushbuf; -}; - -#define NV50_DISP_BASE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507d.h b/drivers/gpu/drm/nouveau/include/nvif/cl507d.h deleted file mode 100644 index 4a56e42d8bc9..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507d.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507D_H__ -#define __NVIF_CL507D_H__ - -struct nv50_disp_core_channel_dma_v0 { - __u8 version; - __u8 pad01[7]; - __u64 pushbuf; -}; - -#define NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl507e.h b/drivers/gpu/drm/nouveau/include/nvif/cl507e.h deleted file mode 100644 index 633936cb6313..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/cl507e.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CL507E_H__ -#define __NVIF_CL507E_H__ - -struct nv50_disp_overlay_channel_dma_v0 { - __u8 version; - __u8 head; - __u8 pad02[6]; - __u64 pushbuf; -}; - -#define NV50_DISP_OVERLAY_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index a582c0cb0cb0..8641db649f48 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -32,6 +32,11 @@ #define NVIF_CLASS_VMM_GM200 /* ifb00d.h */ 0x8000b00d #define NVIF_CLASS_VMM_GP100 /* ifc00d.h */ 0x8000c00d +#define NVIF_CLASS_DISP /* if0010.h */ 0x80000010 +#define NVIF_CLASS_CONN /* if0011.h */ 0x80000011 +#define NVIF_CLASS_OUTP /* if0012.h */ 0x80000012 +#define NVIF_CLASS_DISP_CHAN /* if0014.h */ 0x80000014 + /* the below match nvidia-assigned (either in hw, or sw) class numbers */ #define NV_NULL_CLASS 0x00000030 @@ -73,21 +78,21 @@ #define TURING_CHANNEL_GPFIFO_A /* clc36f.h */ 0x0000c46f #define AMPERE_CHANNEL_GPFIFO_B /* clc36f.h */ 0x0000c76f -#define NV50_DISP /* cl5070.h */ 0x00005070 -#define G82_DISP /* cl5070.h */ 0x00008270 -#define GT200_DISP /* cl5070.h */ 0x00008370 -#define GT214_DISP /* cl5070.h */ 0x00008570 -#define GT206_DISP /* cl5070.h */ 0x00008870 -#define GF110_DISP /* cl5070.h */ 0x00009070 -#define GK104_DISP /* cl5070.h */ 0x00009170 -#define GK110_DISP /* cl5070.h */ 0x00009270 -#define GM107_DISP /* cl5070.h */ 0x00009470 -#define GM200_DISP /* cl5070.h */ 0x00009570 -#define GP100_DISP /* cl5070.h */ 0x00009770 -#define GP102_DISP /* cl5070.h */ 0x00009870 -#define GV100_DISP /* cl5070.h */ 0x0000c370 -#define TU102_DISP /* cl5070.h */ 0x0000c570 -#define GA102_DISP /* cl5070.h */ 0x0000c670 +#define NV50_DISP /* if0010.h */ 0x00005070 +#define G82_DISP /* if0010.h */ 0x00008270 +#define GT200_DISP /* if0010.h */ 0x00008370 +#define GT214_DISP /* if0010.h */ 0x00008570 +#define GT206_DISP /* if0010.h */ 0x00008870 +#define GF110_DISP /* if0010.h */ 0x00009070 +#define GK104_DISP /* if0010.h */ 0x00009170 +#define GK110_DISP /* if0010.h */ 0x00009270 +#define GM107_DISP /* if0010.h */ 0x00009470 +#define GM200_DISP /* if0010.h */ 0x00009570 +#define GP100_DISP /* if0010.h */ 0x00009770 +#define GP102_DISP /* if0010.h */ 0x00009870 +#define GV100_DISP /* if0010.h */ 0x0000c370 +#define TU102_DISP /* if0010.h */ 0x0000c570 +#define GA102_DISP /* if0010.h */ 0x0000c670 #define GV100_DISP_CAPS 0x0000c373 @@ -96,59 +101,59 @@ #define NV74_VP2 0x00007476 -#define NV50_DISP_CURSOR /* cl507a.h */ 0x0000507a -#define G82_DISP_CURSOR /* cl507a.h */ 0x0000827a -#define GT214_DISP_CURSOR /* cl507a.h */ 0x0000857a -#define GF110_DISP_CURSOR /* cl507a.h */ 0x0000907a -#define GK104_DISP_CURSOR /* cl507a.h */ 0x0000917a -#define GV100_DISP_CURSOR /* cl507a.h */ 0x0000c37a -#define TU102_DISP_CURSOR /* cl507a.h */ 0x0000c57a -#define GA102_DISP_CURSOR /* cl507a.h */ 0x0000c67a - -#define NV50_DISP_OVERLAY /* cl507b.h */ 0x0000507b -#define G82_DISP_OVERLAY /* cl507b.h */ 0x0000827b -#define GT214_DISP_OVERLAY /* cl507b.h */ 0x0000857b -#define GF110_DISP_OVERLAY /* cl507b.h */ 0x0000907b -#define GK104_DISP_OVERLAY /* cl507b.h */ 0x0000917b - -#define GV100_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c37b -#define TU102_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c57b -#define GA102_DISP_WINDOW_IMM_CHANNEL_DMA /* clc37b.h */ 0x0000c67b - -#define NV50_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000507c -#define G82_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000827c -#define GT200_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000837c -#define GT214_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000857c -#define GF110_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000907c -#define GK104_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000917c -#define GK110_DISP_BASE_CHANNEL_DMA /* cl507c.h */ 0x0000927c - -#define NV50_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000507d -#define G82_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000827d -#define GT200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000837d -#define GT214_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000857d -#define GT206_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000887d -#define GF110_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000907d -#define GK104_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000917d -#define GK110_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000927d -#define GM107_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000947d -#define GM200_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000957d -#define GP100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000977d -#define GP102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000987d -#define GV100_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c37d -#define TU102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c57d -#define GA102_DISP_CORE_CHANNEL_DMA /* cl507d.h */ 0x0000c67d - -#define NV50_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000507e -#define G82_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000827e -#define GT200_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000837e -#define GT214_DISP_OVERLAY_CHANNEL_DMA /* cl507e.h */ 0x0000857e -#define GF110_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000907e -#define GK104_DISP_OVERLAY_CONTROL_DMA /* cl507e.h */ 0x0000917e - -#define GV100_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c37e -#define TU102_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c57e -#define GA102_DISP_WINDOW_CHANNEL_DMA /* clc37e.h */ 0x0000c67e +#define NV50_DISP_CURSOR /* if0014.h */ 0x0000507a +#define G82_DISP_CURSOR /* if0014.h */ 0x0000827a +#define GT214_DISP_CURSOR /* if0014.h */ 0x0000857a +#define GF110_DISP_CURSOR /* if0014.h */ 0x0000907a +#define GK104_DISP_CURSOR /* if0014.h */ 0x0000917a +#define GV100_DISP_CURSOR /* if0014.h */ 0x0000c37a +#define TU102_DISP_CURSOR /* if0014.h */ 0x0000c57a +#define GA102_DISP_CURSOR /* if0014.h */ 0x0000c67a + +#define NV50_DISP_OVERLAY /* if0014.h */ 0x0000507b +#define G82_DISP_OVERLAY /* if0014.h */ 0x0000827b +#define GT214_DISP_OVERLAY /* if0014.h */ 0x0000857b +#define GF110_DISP_OVERLAY /* if0014.h */ 0x0000907b +#define GK104_DISP_OVERLAY /* if0014.h */ 0x0000917b + +#define GV100_DISP_WINDOW_IMM_CHANNEL_DMA /* if0014.h */ 0x0000c37b +#define TU102_DISP_WINDOW_IMM_CHANNEL_DMA /* if0014.h */ 0x0000c57b +#define GA102_DISP_WINDOW_IMM_CHANNEL_DMA /* if0014.h */ 0x0000c67b + +#define NV50_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000507c +#define G82_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000827c +#define GT200_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000837c +#define GT214_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000857c +#define GF110_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000907c +#define GK104_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000917c +#define GK110_DISP_BASE_CHANNEL_DMA /* if0014.h */ 0x0000927c + +#define NV50_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000507d +#define G82_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000827d +#define GT200_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000837d +#define GT214_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000857d +#define GT206_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000887d +#define GF110_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000907d +#define GK104_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000917d +#define GK110_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000927d +#define GM107_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000947d +#define GM200_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000957d +#define GP100_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000977d +#define GP102_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000987d +#define GV100_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000c37d +#define TU102_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000c57d +#define GA102_DISP_CORE_CHANNEL_DMA /* if0014.h */ 0x0000c67d + +#define NV50_DISP_OVERLAY_CHANNEL_DMA /* if0014.h */ 0x0000507e +#define G82_DISP_OVERLAY_CHANNEL_DMA /* if0014.h */ 0x0000827e +#define GT200_DISP_OVERLAY_CHANNEL_DMA /* if0014.h */ 0x0000837e +#define GT214_DISP_OVERLAY_CHANNEL_DMA /* if0014.h */ 0x0000857e +#define GF110_DISP_OVERLAY_CONTROL_DMA /* if0014.h */ 0x0000907e +#define GK104_DISP_OVERLAY_CONTROL_DMA /* if0014.h */ 0x0000917e + +#define GV100_DISP_WINDOW_CHANNEL_DMA /* if0014.h */ 0x0000c37e +#define TU102_DISP_WINDOW_CHANNEL_DMA /* if0014.h */ 0x0000c57e +#define GA102_DISP_WINDOW_CHANNEL_DMA /* if0014.h */ 0x0000c67e #define NV50_TESLA 0x00005097 #define G82_TESLA 0x00008297 diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc37b.h b/drivers/gpu/drm/nouveau/include/nvif/clc37b.h deleted file mode 100644 index 970a5ac4cb95..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/clc37b.h +++ /dev/null @@ -1,11 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CLC37B_H__ -#define __NVIF_CLC37B_H__ - -struct nvc37b_window_imm_channel_dma_v0 { - __u8 version; - __u8 index; - __u8 pad02[6]; - __u64 pushbuf; -}; -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/clc37e.h b/drivers/gpu/drm/nouveau/include/nvif/clc37e.h deleted file mode 100644 index 7ea23695e7e1..000000000000 --- a/drivers/gpu/drm/nouveau/include/nvif/clc37e.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NVIF_CLC37E_H__ -#define __NVIF_CLC37E_H__ - -struct nvc37e_window_channel_dma_v0 { - __u8 version; - __u8 index; - __u8 pad02[6]; - __u64 pushbuf; -}; - -#define NVC37E_WINDOW_CHANNEL_DMA_V0_NTFY_UEVENT 0x00 -#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/conn.h b/drivers/gpu/drm/nouveau/include/nvif/conn.h new file mode 100644 index 000000000000..f72a8f138f47 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/conn.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_CONN_H__ +#define __NVIF_CONN_H__ +#include <nvif/object.h> +struct nvif_disp; + +struct nvif_conn { + struct nvif_object object; +}; + +int nvif_conn_ctor(struct nvif_disp *, const char *name, int id, struct nvif_conn *); +void nvif_conn_dtor(struct nvif_conn *); + +#define NVIF_CONN_HPD_STATUS_UNSUPPORTED 0 /* negative if query fails */ +#define NVIF_CONN_HPD_STATUS_NOT_PRESENT 1 +#define NVIF_CONN_HPD_STATUS_PRESENT 2 +int nvif_conn_hpd_status(struct nvif_conn *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/disp.h b/drivers/gpu/drm/nouveau/include/nvif/disp.h index 07ac544f282f..742632ad3bea 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvif/disp.h @@ -5,6 +5,8 @@ struct nvif_device; struct nvif_disp { struct nvif_object object; + unsigned long conn_mask; + unsigned long outp_mask; }; int nvif_disp_ctor(struct nvif_device *, const char *name, s32 oclass, diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0010.h b/drivers/gpu/drm/nouveau/include/nvif/if0010.h new file mode 100644 index 000000000000..fc236ef28965 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0010.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0010_H__ +#define __NVIF_IF0010_H__ + +union nvif_disp_args { + struct nvif_disp_v0 { + __u8 version; + __u8 pad01[3]; + __u32 conn_mask; + __u32 outp_mask; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0011.h b/drivers/gpu/drm/nouveau/include/nvif/if0011.h new file mode 100644 index 000000000000..04ba6581f840 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0011.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0011_H__ +#define __NVIF_IF0011_H__ + +union nvif_conn_args { + struct nvif_conn_v0 { + __u8 version; + __u8 id; /* DCB connector table index. */ + __u8 pad02[6]; + } v0; +}; + +#define NVIF_CONN_V0_HPD_STATUS 0x00000000 + +union nvif_conn_hpd_status_args { + struct nvif_conn_hpd_status_v0 { + __u8 version; + __u8 support; + __u8 present; + __u8 pad03[5]; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0012.h b/drivers/gpu/drm/nouveau/include/nvif/if0012.h new file mode 100644 index 000000000000..243bd35d942f --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0012.h @@ -0,0 +1,23 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0012_H__ +#define __NVIF_IF0012_H__ + +union nvif_outp_args { + struct nvif_outp_v0 { + __u8 version; + __u8 id; /* DCB device index. */ + __u8 pad02[6]; + } v0; +}; + +#define NVIF_OUTP_V0_LOAD_DETECT 0x00 + +union nvif_outp_load_detect_args { + struct nvif_outp_load_detect_v0 { + __u8 version; + __u8 load; + __u8 pad02[2]; + __u32 data; /*TODO: move vbios loadval parsing into nvkm */ + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0014.h b/drivers/gpu/drm/nouveau/include/nvif/if0014.h new file mode 100644 index 000000000000..be0362805106 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0014.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_IF0014_H__ +#define __NVIF_IF0014_H__ + +union nvif_disp_chan_args { + struct nvif_disp_chan_v0 { + __u8 version; + __u8 id; + __u8 pad02[6]; + __u64 pushbuf; + } v0; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/outp.h b/drivers/gpu/drm/nouveau/include/nvif/outp.h new file mode 100644 index 000000000000..0d6aa07a9184 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/outp.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVIF_OUTP_H__ +#define __NVIF_OUTP_H__ +#include <nvif/object.h> +struct nvif_disp; + +struct nvif_outp { + struct nvif_object object; +}; + +int nvif_outp_ctor(struct nvif_disp *, const char *name, int id, struct nvif_outp *); +void nvif_outp_dtor(struct nvif_outp *); +int nvif_outp_load_detect(struct nvif_outp *, u32 loadval); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/printf.h b/drivers/gpu/drm/nouveau/include/nvif/printf.h index 6c299ec6be21..ec524b2faeae 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/printf.h +++ b/drivers/gpu/drm/nouveau/include/nvif/printf.h @@ -17,4 +17,13 @@ #endif #define NVIF_ERROR(o,f,a...) NVIF_PRINT(errorf, (o), f, ##a) +#define NVIF_ERRON(c,o,f,a...) do { \ + struct nvif_object *_object = (o); \ + int _cond = (c); \ + if (_cond) { \ + NVIF_ERROR(_object, f" (ret:%d)", ##a, _cond); \ + } else { \ + NVIF_DEBUG(_object, f, ##a); \ + } \ +} while(0) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h index d08d3337ba0d..8b5d8a434be8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/disp.h @@ -3,23 +3,56 @@ #define __NVKM_DISP_H__ #define nvkm_disp(p) container_of((p), struct nvkm_disp, engine) #include <core/engine.h> +#include <core/object.h> #include <core/event.h> struct nvkm_disp { const struct nvkm_disp_func *func; struct nvkm_engine engine; - struct list_head head; - struct list_head ior; - struct list_head outp; - struct list_head conn; + struct list_head heads; + struct list_head iors; + struct list_head outps; + struct list_head conns; struct nvkm_event hpd; struct nvkm_event vblank; struct { + struct workqueue_struct *wq; + struct work_struct work; + u32 pending; + struct mutex mutex; + } super; + +#define NVKM_DISP_EVENT_CHAN_AWAKEN BIT(0) + struct nvkm_event uevent; + + struct { + unsigned long mask; + int nr; + } wndw, head, dac; + + struct { + unsigned long mask; + int nr; + u32 lvdsconf; + } sor; + + struct { + unsigned long mask; + int nr; + u8 type[3]; + } pior; + + struct nvkm_gpuobj *inst; + struct nvkm_ramht *ramht; + + struct nvkm_disp_chan *chan[81]; + + struct { spinlock_t lock; - struct nvkm_oproxy *object; + struct nvkm_object object; } client; }; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h index a27a0f3fe7aa..73f9d9947e7e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bios/dcb.h @@ -54,6 +54,7 @@ struct dcb_output { } tmdsconf; }; bool i2c_upper_default; + int id; }; u16 dcb_table(struct nvkm_bios *, u8 *ver, u8 *hdr, u8 *ent, u8 *len); diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 41b78e9ecd4e..189903b65edc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -1801,6 +1801,8 @@ parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) ret = parse_dcb20_entry(dev, dcb, conn, conf, entry); else ret = parse_dcb15_entry(dev, dcb, conn, conf, entry); + entry->id = idx; + if (!ret) return 1; /* stop parsing */ diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 22b83a6577eb..43a9d1e1cf71 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -404,6 +404,7 @@ nouveau_connector_destroy(struct drm_connector *connector) drm_dp_cec_unregister_connector(&nv_connector->aux); kfree(nv_connector->aux.name); } + nvif_conn_dtor(&nv_connector->conn); kfree(connector); } @@ -1361,13 +1362,11 @@ nouveau_connector_create(struct drm_device *dev, snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x", dcbe->hasht, dcbe->hashm); nv_connector->aux.name = kstrdup(aux_name, GFP_KERNEL); - drm_dp_aux_init(&nv_connector->aux); - if (ret) { - NV_ERROR(drm, "Failed to init AUX adapter for sor-%04x-%04x: %d\n", - dcbe->hasht, dcbe->hashm, ret); + if (!nv_connector->aux.name) { kfree(nv_connector); - return ERR_PTR(ret); + return ERR_PTR(-ENOMEM); } + drm_dp_aux_init(&nv_connector->aux); fallthrough; default: funcs = &nouveau_connector_funcs; @@ -1388,6 +1387,15 @@ nouveau_connector_create(struct drm_device *dev, drm_connector_init(dev, connector, funcs, type); drm_connector_helper_add(connector, &nouveau_connector_helper_funcs); + if (nv_connector->dcb && (disp->disp.conn_mask & BIT(nv_connector->index))) { + ret = nvif_conn_ctor(&disp->disp, nv_connector->base.name, nv_connector->index, + &nv_connector->conn); + if (ret) { + kfree(nv_connector); + return ERR_PTR(ret); + } + } + connector->funcs->reset(connector); nouveau_conn_attach_properties(connector); diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.h b/drivers/gpu/drm/nouveau/nouveau_connector.h index b0773af5a98f..4bf0c703eee7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.h +++ b/drivers/gpu/drm/nouveau/nouveau_connector.h @@ -26,7 +26,7 @@ #ifndef __NOUVEAU_CONNECTOR_H__ #define __NOUVEAU_CONNECTOR_H__ - +#include <nvif/conn.h> #include <nvif/notify.h> #include <nvhw/class/cl507d.h> @@ -123,6 +123,7 @@ struct nouveau_connector { u8 index; u8 *dcb; + struct nvif_conn conn; struct nvif_notify hpd; struct drm_dp_aux aux; diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 2cd0932b3d68..a2f5df568ca5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -515,7 +515,7 @@ nouveau_display_hpd_work(struct work_struct *work) pm_runtime_mark_last_busy(drm->dev->dev); noop: - pm_runtime_put_sync(drm->dev->dev); + pm_runtime_put_autosuspend(dev->dev); } #ifdef CONFIG_ACPI @@ -537,7 +537,7 @@ nouveau_display_acpi_ntfy(struct notifier_block *nb, unsigned long val, * it's own hotplug events. */ pm_runtime_put_autosuspend(drm->dev->dev); - } else if (ret == 0) { + } else if (ret == 0 || ret == -EINPROGRESS) { /* We've started resuming the GPU already, so * it will handle scheduling a full reprobe * itself diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index c36f510d5d4c..20db8ea1a0ba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c @@ -107,7 +107,7 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, struct nv50_mstm *mstm = nv_encoder->dp.mstm; enum drm_connector_status status; u8 *dpcd = nv_encoder->dp.dpcd; - int ret = NOUVEAU_DP_NONE; + int ret = NOUVEAU_DP_NONE, hpd; /* If we've already read the DPCD on an eDP device, we don't need to * reread it as it won't change @@ -133,6 +133,16 @@ nouveau_dp_detect(struct nouveau_connector *nv_connector, } } + /* Check status of HPD pin before attempting an AUX transaction that + * would result in a number of (futile) retries on a connector which + * has no display plugged. + * + * TODO: look into checking this before probing I2C to detect DVI/HDMI + */ + hpd = nvif_conn_hpd_status(&nv_connector->conn); + if (hpd == NVIF_CONN_HPD_STATUS_NOT_PRESENT) + goto out; + status = nouveau_dp_probe_dpcd(nv_connector, nv_encoder); if (status == connector_status_disconnected) goto out; diff --git a/drivers/gpu/drm/nouveau/nouveau_encoder.h b/drivers/gpu/drm/nouveau/nouveau_encoder.h index c2f5f0cb70d5..b72e5783a00f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_encoder.h +++ b/drivers/gpu/drm/nouveau/nouveau_encoder.h @@ -26,7 +26,7 @@ #ifndef __NOUVEAU_ENCODER_H__ #define __NOUVEAU_ENCODER_H__ - +#include <nvif/outp.h> #include <subdev/bios/dcb.h> #include <drm/display/drm_dp_helper.h> @@ -46,6 +46,7 @@ struct nouveau_encoder { struct drm_encoder_slave base; struct dcb_output *dcb; + struct nvif_outp outp; int or; int link; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 5226323e55d3..3c7e0c9d6baf 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -467,7 +467,7 @@ nouveau_fbcon_set_suspend_work(struct work_struct *work) if (state == FBINFO_STATE_RUNNING) { nouveau_fbcon_hotplug_resume(drm->fbcon); pm_runtime_mark_last_busy(drm->dev->dev); - pm_runtime_put_sync(drm->dev->dev); + pm_runtime_put_autosuspend(drm->dev->dev); } } diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild index f194d354c1f5..6abc4bc42e35 100644 --- a/drivers/gpu/drm/nouveau/nvif/Kbuild +++ b/drivers/gpu/drm/nouveau/nvif/Kbuild @@ -1,6 +1,7 @@ # SPDX-License-Identifier: MIT nvif-y := nvif/object.o nvif-y += nvif/client.o +nvif-y += nvif/conn.o nvif-y += nvif/device.o nvif-y += nvif/disp.o nvif-y += nvif/driver.o @@ -8,6 +9,7 @@ nvif-y += nvif/fifo.o nvif-y += nvif/mem.o nvif-y += nvif/mmu.o nvif-y += nvif/notify.o +nvif-y += nvif/outp.o nvif-y += nvif/timer.o nvif-y += nvif/vmm.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootga102.c b/drivers/gpu/drm/nouveau/nvif/conn.c index 9af07c3cf9fc..4ce935d58c90 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootga102.c +++ b/drivers/gpu/drm/nouveau/nvif/conn.c @@ -19,34 +19,44 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "rootnv50.h" -#include "channv50.h" +#include <nvif/conn.h> +#include <nvif/disp.h> +#include <nvif/printf.h> #include <nvif/class.h> +#include <nvif/if0011.h> -static const struct nv50_disp_root_func -ga102_disp_root = { - .user = { - {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, - {{0,0,GA102_DISP_CURSOR }, gv100_disp_curs_new }, - {{0,0,GA102_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, - {{0,0,GA102_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, - {{0,0,GA102_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, - {} - }, -}; - -static int -ga102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) +int +nvif_conn_hpd_status(struct nvif_conn *conn) { - return nv50_disp_root_new_(&ga102_disp_root, disp, oclass, data, size, pobject); + struct nvif_conn_hpd_status_v0 args; + int ret; + + args.version = 0; + + ret = nvif_mthd(&conn->object, NVIF_CONN_V0_HPD_STATUS, &args, sizeof(args)); + NVIF_ERRON(ret, &conn->object, "[HPD_STATUS] support:%d present:%d", + args.support, args.present); + return ret ? ret : !!args.support + !!args.present; +} + +void +nvif_conn_dtor(struct nvif_conn *conn) +{ + nvif_object_dtor(&conn->object); } -const struct nvkm_disp_oclass -ga102_disp_root_oclass = { - .base.oclass = GA102_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = ga102_disp_root_new, -}; +int +nvif_conn_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_conn *conn) +{ + struct nvif_conn_v0 args; + int ret; + + args.version = 0; + args.id = id; + + ret = nvif_object_ctor(&disp->object, name ?: "nvifConn", id, NVIF_CLASS_CONN, + &args, sizeof(args), &conn->object); + NVIF_ERRON(ret, &disp->object, "[NEW conn id:%d]", id); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvif/disp.c b/drivers/gpu/drm/nouveau/nvif/disp.c index 529cb60d5efb..926b0c04b1e8 100644 --- a/drivers/gpu/drm/nouveau/nvif/disp.c +++ b/drivers/gpu/drm/nouveau/nvif/disp.c @@ -21,8 +21,10 @@ */ #include <nvif/disp.h> #include <nvif/device.h> +#include <nvif/printf.h> #include <nvif/class.h> +#include <nvif/if0010.h> void nvif_disp_dtor(struct nvif_disp *disp) @@ -31,33 +33,48 @@ nvif_disp_dtor(struct nvif_disp *disp) } int -nvif_disp_ctor(struct nvif_device *device, const char *name, s32 oclass, - struct nvif_disp *disp) +nvif_disp_ctor(struct nvif_device *device, const char *name, s32 oclass, struct nvif_disp *disp) { static const struct nvif_mclass disps[] = { - { GA102_DISP, -1 }, - { TU102_DISP, -1 }, - { GV100_DISP, -1 }, - { GP102_DISP, -1 }, - { GP100_DISP, -1 }, - { GM200_DISP, -1 }, - { GM107_DISP, -1 }, - { GK110_DISP, -1 }, - { GK104_DISP, -1 }, - { GF110_DISP, -1 }, - { GT214_DISP, -1 }, - { GT206_DISP, -1 }, - { GT200_DISP, -1 }, - { G82_DISP, -1 }, - { NV50_DISP, -1 }, - { NV04_DISP, -1 }, + { GA102_DISP, 0 }, + { TU102_DISP, 0 }, + { GV100_DISP, 0 }, + { GP102_DISP, 0 }, + { GP100_DISP, 0 }, + { GM200_DISP, 0 }, + { GM107_DISP, 0 }, + { GK110_DISP, 0 }, + { GK104_DISP, 0 }, + { GF110_DISP, 0 }, + { GT214_DISP, 0 }, + { GT206_DISP, 0 }, + { GT200_DISP, 0 }, + { G82_DISP, 0 }, + { NV50_DISP, 0 }, + { NV04_DISP, 0 }, {} }; - int cid = nvif_sclass(&device->object, disps, oclass); + struct nvif_disp_v0 args; + int cid, ret; + + cid = nvif_sclass(&device->object, disps, oclass); disp->object.client = NULL; - if (cid < 0) + if (cid < 0) { + NVIF_ERRON(cid, &device->object, "[NEW disp%04x] not supported", oclass); return cid; + } + + args.version = 0; + + ret = nvif_object_ctor(&device->object, name ?: "nvifDisp", 0, + disps[cid].oclass, &args, sizeof(args), &disp->object); + NVIF_ERRON(ret, &device->object, "[NEW disp%04x]", disps[cid].oclass); + if (ret) + return ret; - return nvif_object_ctor(&device->object, name ? name : "nvifDisp", 0, - disps[cid].oclass, NULL, 0, &disp->object); + NVIF_DEBUG(&disp->object, "[NEW] conn_mask:%08x outp_mask:%08x", + args.conn_mask, args.outp_mask); + disp->conn_mask = args.conn_mask; + disp->outp_mask = args.outp_mask; + return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c b/drivers/gpu/drm/nouveau/nvif/outp.c index ef579eb00238..7bfe91a8d6f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg94.c +++ b/drivers/gpu/drm/nouveau/nvif/outp.c @@ -1,5 +1,5 @@ /* - * Copyright 2012 Red Hat Inc. + * Copyright 2021 Red Hat Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -18,38 +18,45 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs */ -#include "rootnv50.h" -#include "channv50.h" +#include <nvif/outp.h> +#include <nvif/disp.h> +#include <nvif/printf.h> #include <nvif/class.h> +#include <nvif/if0012.h> + +int +nvif_outp_load_detect(struct nvif_outp *outp, u32 loadval) +{ + struct nvif_outp_load_detect_v0 args; + int ret; + + args.version = 0; + args.data = loadval; + + ret = nvif_mthd(&outp->object, NVIF_OUTP_V0_LOAD_DETECT, &args, sizeof(args)); + NVIF_ERRON(ret, &outp->object, "[LOAD_DETECT data:%08x] load:%02x", args.data, args.load); + return ret < 0 ? ret : args.load; +} -static const struct nv50_disp_root_func -g94_disp_root = { - .user = { - {{0,0, G82_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0, G82_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, - {{0,0,GT206_DISP_CORE_CHANNEL_DMA }, g94_disp_core_new }, - {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, gt200_disp_ovly_new }, - {} - }, -}; - -static int -g94_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) +void +nvif_outp_dtor(struct nvif_outp *outp) { - return nv50_disp_root_new_(&g94_disp_root, disp, oclass, - data, size, pobject); + nvif_object_dtor(&outp->object); } -const struct nvkm_disp_oclass -g94_disp_root_oclass = { - .base.oclass = GT206_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = g94_disp_root_new, -}; +int +nvif_outp_ctor(struct nvif_disp *disp, const char *name, int id, struct nvif_outp *outp) +{ + struct nvif_outp_v0 args; + int ret; + + args.version = 0; + args.id = id; + + ret = nvif_object_ctor(&disp->object, name ?: "nvifOutp", id, NVIF_CLASS_OUTP, + &args, sizeof(args), &outp->object); + NVIF_ERRON(ret, &disp->object, "[NEW outp id:%d]", id); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild index b03f043efe26..600072a904be 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/Kbuild @@ -1,5 +1,14 @@ # SPDX-License-Identifier: MIT nvkm-y += nvkm/engine/disp/base.o +nvkm-y += nvkm/engine/disp/chan.o +nvkm-y += nvkm/engine/disp/conn.o +nvkm-y += nvkm/engine/disp/dp.o +nvkm-y += nvkm/engine/disp/hdmi.o +nvkm-y += nvkm/engine/disp/head.o +nvkm-y += nvkm/engine/disp/ior.o +nvkm-y += nvkm/engine/disp/outp.o +nvkm-y += nvkm/engine/disp/vga.o + nvkm-y += nvkm/engine/disp/nv04.o nvkm-y += nvkm/engine/disp/nv50.o nvkm-y += nvkm/engine/disp/g84.o @@ -18,110 +27,10 @@ nvkm-y += nvkm/engine/disp/gp102.o nvkm-y += nvkm/engine/disp/gv100.o nvkm-y += nvkm/engine/disp/tu102.o nvkm-y += nvkm/engine/disp/ga102.o -nvkm-y += nvkm/engine/disp/vga.o - -nvkm-y += nvkm/engine/disp/head.o -nvkm-y += nvkm/engine/disp/headnv04.o -nvkm-y += nvkm/engine/disp/headnv50.o -nvkm-y += nvkm/engine/disp/headgf119.o -nvkm-y += nvkm/engine/disp/headgv100.o - -nvkm-y += nvkm/engine/disp/ior.o -nvkm-y += nvkm/engine/disp/dacnv50.o -nvkm-y += nvkm/engine/disp/dacgf119.o -nvkm-y += nvkm/engine/disp/piornv50.o -nvkm-y += nvkm/engine/disp/sornv50.o -nvkm-y += nvkm/engine/disp/sorg84.o -nvkm-y += nvkm/engine/disp/sorg94.o -nvkm-y += nvkm/engine/disp/sormcp77.o -nvkm-y += nvkm/engine/disp/sorgt215.o -nvkm-y += nvkm/engine/disp/sormcp89.o -nvkm-y += nvkm/engine/disp/sorgf119.o -nvkm-y += nvkm/engine/disp/sorgk104.o -nvkm-y += nvkm/engine/disp/sorgm107.o -nvkm-y += nvkm/engine/disp/sorgm200.o -nvkm-y += nvkm/engine/disp/sorgp100.o -nvkm-y += nvkm/engine/disp/sorgv100.o -nvkm-y += nvkm/engine/disp/sortu102.o -nvkm-y += nvkm/engine/disp/sorga102.o - -nvkm-y += nvkm/engine/disp/outp.o -nvkm-y += nvkm/engine/disp/dp.o - -nvkm-y += nvkm/engine/disp/hdagt215.o -nvkm-y += nvkm/engine/disp/hdagf119.o -nvkm-y += nvkm/engine/disp/hdagv100.o - -nvkm-y += nvkm/engine/disp/hdmi.o -nvkm-y += nvkm/engine/disp/hdmig84.o -nvkm-y += nvkm/engine/disp/hdmigt215.o -nvkm-y += nvkm/engine/disp/hdmigf119.o -nvkm-y += nvkm/engine/disp/hdmigk104.o -nvkm-y += nvkm/engine/disp/hdmigm200.o -nvkm-y += nvkm/engine/disp/hdmigv100.o - -nvkm-y += nvkm/engine/disp/conn.o nvkm-y += nvkm/engine/disp/rootnv04.o nvkm-y += nvkm/engine/disp/rootnv50.o -nvkm-y += nvkm/engine/disp/rootg84.o -nvkm-y += nvkm/engine/disp/rootg94.o -nvkm-y += nvkm/engine/disp/rootgt200.o -nvkm-y += nvkm/engine/disp/rootgt215.o -nvkm-y += nvkm/engine/disp/rootgf119.o -nvkm-y += nvkm/engine/disp/rootgk104.o -nvkm-y += nvkm/engine/disp/rootgk110.o -nvkm-y += nvkm/engine/disp/rootgm107.o -nvkm-y += nvkm/engine/disp/rootgm200.o -nvkm-y += nvkm/engine/disp/rootgp100.o -nvkm-y += nvkm/engine/disp/rootgp102.o -nvkm-y += nvkm/engine/disp/rootgv100.o -nvkm-y += nvkm/engine/disp/roottu102.o -nvkm-y += nvkm/engine/disp/rootga102.o - -nvkm-y += nvkm/engine/disp/capsgv100.o - -nvkm-y += nvkm/engine/disp/channv50.o -nvkm-y += nvkm/engine/disp/changf119.o -nvkm-y += nvkm/engine/disp/changv100.o - -nvkm-y += nvkm/engine/disp/dmacnv50.o -nvkm-y += nvkm/engine/disp/dmacgf119.o -nvkm-y += nvkm/engine/disp/dmacgp102.o -nvkm-y += nvkm/engine/disp/dmacgv100.o - -nvkm-y += nvkm/engine/disp/basenv50.o -nvkm-y += nvkm/engine/disp/baseg84.o -nvkm-y += nvkm/engine/disp/basegf119.o -nvkm-y += nvkm/engine/disp/basegp102.o - -nvkm-y += nvkm/engine/disp/corenv50.o -nvkm-y += nvkm/engine/disp/coreg84.o -nvkm-y += nvkm/engine/disp/coreg94.o -nvkm-y += nvkm/engine/disp/coregf119.o -nvkm-y += nvkm/engine/disp/coregk104.o -nvkm-y += nvkm/engine/disp/coregp102.o -nvkm-y += nvkm/engine/disp/coregv100.o - -nvkm-y += nvkm/engine/disp/ovlynv50.o -nvkm-y += nvkm/engine/disp/ovlyg84.o -nvkm-y += nvkm/engine/disp/ovlygt200.o -nvkm-y += nvkm/engine/disp/ovlygf119.o -nvkm-y += nvkm/engine/disp/ovlygk104.o -nvkm-y += nvkm/engine/disp/ovlygp102.o - -nvkm-y += nvkm/engine/disp/wimmgv100.o - -nvkm-y += nvkm/engine/disp/wndwgv100.o - -nvkm-y += nvkm/engine/disp/piocnv50.o -nvkm-y += nvkm/engine/disp/piocgf119.o - -nvkm-y += nvkm/engine/disp/cursnv50.o -nvkm-y += nvkm/engine/disp/cursgf119.o -nvkm-y += nvkm/engine/disp/cursgp102.o -nvkm-y += nvkm/engine/disp/cursgv100.o -nvkm-y += nvkm/engine/disp/oimmnv50.o -nvkm-y += nvkm/engine/disp/oimmgf119.o -nvkm-y += nvkm/engine/disp/oimmgp102.o +nvkm-y += nvkm/engine/disp/udisp.o +nvkm-y += nvkm/engine/disp/uconn.o +nvkm-y += nvkm/engine/disp/uoutp.o diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c index 5daa77755276..65c99d948b68 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/base.c @@ -30,7 +30,7 @@ #include <core/client.h> #include <core/notify.h> -#include <core/oproxy.h> +#include <core/ramht.h> #include <subdev/bios.h> #include <subdev/bios/dcb.h> @@ -108,7 +108,7 @@ nvkm_disp_hpd_ctor(struct nvkm_object *object, void *data, u32 size, if (!(ret = nvif_unpack(ret, &data, &size, req->v0, 0, 0, false))) { notify->size = sizeof(struct nvif_notify_conn_rep_v0); - list_for_each_entry(outp, &disp->outp, head) { + list_for_each_entry(outp, &disp->outps, head) { if (ret = -ENXIO, outp->conn->index == req->v0.conn) { if (ret = -ENODEV, outp->conn->hpd.event) { notify->types = req->v0.mask; @@ -145,45 +145,12 @@ nvkm_disp_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **event) return -EINVAL; } -static void -nvkm_disp_class_del(struct nvkm_oproxy *oproxy) -{ - struct nvkm_disp *disp = nvkm_disp(oproxy->base.engine); - spin_lock(&disp->client.lock); - if (disp->client.object == oproxy) - disp->client.object = NULL; - spin_unlock(&disp->client.lock); -} - -static const struct nvkm_oproxy_func -nvkm_disp_class = { - .dtor[1] = nvkm_disp_class_del, -}; - static int nvkm_disp_class_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, void *data, u32 size, struct nvkm_object **pobject) { - const struct nvkm_disp_oclass *sclass = oclass->engn; - struct nvkm_disp *disp = nvkm_disp(oclass->engine); - struct nvkm_oproxy *oproxy; - int ret; - - ret = nvkm_oproxy_new_(&nvkm_disp_class, oclass, &oproxy); - if (ret) - return ret; - *pobject = &oproxy->base; - - spin_lock(&disp->client.lock); - if (disp->client.object) { - spin_unlock(&disp->client.lock); - return -EBUSY; - } - disp->client.object = oproxy; - spin_unlock(&disp->client.lock); - - return sclass->ctor(disp, oclass, data, size, &oproxy->object); + return nvkm_udisp_new(oclass, data, size, pobject); } static const struct nvkm_device_oclass @@ -197,9 +164,7 @@ nvkm_disp_class_get(struct nvkm_oclass *oclass, int index, { struct nvkm_disp *disp = nvkm_disp(oclass->engine); if (index == 0) { - const struct nvkm_disp_oclass *root = disp->func->root(disp); - oclass->base = root->base; - oclass->engn = root; + oclass->base = disp->func->root; *class = &nvkm_disp_sclass; return 0; } @@ -223,11 +188,11 @@ nvkm_disp_fini(struct nvkm_engine *engine, bool suspend) if (disp->func->fini) disp->func->fini(disp); - list_for_each_entry(outp, &disp->outp, head) { + list_for_each_entry(outp, &disp->outps, head) { nvkm_outp_fini(outp); } - list_for_each_entry(conn, &disp->conn, head) { + list_for_each_entry(conn, &disp->conns, head) { nvkm_conn_fini(conn); } @@ -242,11 +207,11 @@ nvkm_disp_init(struct nvkm_engine *engine) struct nvkm_outp *outp; struct nvkm_ior *ior; - list_for_each_entry(conn, &disp->conn, head) { + list_for_each_entry(conn, &disp->conns, head) { nvkm_conn_init(conn); } - list_for_each_entry(outp, &disp->outp, head) { + list_for_each_entry(outp, &disp->outps, head) { nvkm_outp_init(outp); } @@ -259,7 +224,7 @@ nvkm_disp_init(struct nvkm_engine *engine) /* Set 'normal' (ie. when it's attached to a head) state for * each output resource to 'fully enabled'. */ - list_for_each_entry(ior, &disp->ior, head) { + list_for_each_entry(ior, &disp->iors, head) { ior->func->power(ior, true, true, true, true, true); } @@ -326,12 +291,12 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) continue; } - list_add_tail(&outp->head, &disp->outp); + list_add_tail(&outp->head, &disp->outps); hpd = max(hpd, (u8)(dcbE.connector + 1)); } /* Create connector objects based on available output paths. */ - list_for_each_entry_safe(outp, outt, &disp->outp, head) { + list_for_each_entry_safe(outp, outt, &disp->outps, head) { /* VBIOS data *should* give us the most useful information. */ data = nvbios_connEp(bios, outp->info.connector, &ver, &hdr, &connE); @@ -345,7 +310,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) */ int ccb_index = outp->info.i2c_index; if (ccb_index != 0xf) { - list_for_each_entry(pair, &disp->outp, head) { + list_for_each_entry(pair, &disp->outps, head) { if (pair->info.i2c_index == ccb_index) { outp->conn = pair->conn; break; @@ -365,7 +330,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) } /* Check that we haven't already created this connector. */ - list_for_each_entry(conn, &disp->conn, head) { + list_for_each_entry(conn, &disp->conns, head) { if (conn->index == outp->info.connector) { outp->conn = conn; break; @@ -387,7 +352,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) continue; } - list_add_tail(&outp->conn->head, &disp->conn); + list_add_tail(&outp->conn->head, &disp->conns); } ret = nvkm_event_init(&nvkm_disp_hpd_func, 3, hpd, &disp->hpd); @@ -403,7 +368,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) /* Enforce identity-mapped SOR assignment for panels, which have * certain bits (ie. backlight controls) wired to a specific SOR. */ - list_for_each_entry(outp, &disp->outp, head) { + list_for_each_entry(outp, &disp->outps, head) { if (outp->conn->info.type == DCB_CONNECTOR_LVDS || outp->conn->info.type == DCB_CONNECTOR_eDP) { ior = nvkm_ior_find(disp, SOR, ffs(outp->info.or) - 1); @@ -414,7 +379,7 @@ nvkm_disp_oneinit(struct nvkm_engine *engine) } i = 0; - list_for_each_entry(head, &disp->head, head) + list_for_each_entry(head, &disp->heads, head) i = max(i, head->id + 1); return nvkm_event_init(&nvkm_disp_vblank_func, 1, i, &disp->vblank); @@ -426,35 +391,42 @@ nvkm_disp_dtor(struct nvkm_engine *engine) struct nvkm_disp *disp = nvkm_disp(engine); struct nvkm_conn *conn; struct nvkm_outp *outp; + struct nvkm_ior *ior; + struct nvkm_head *head; void *data = disp; - if (disp->func->dtor) - data = disp->func->dtor(disp); + nvkm_ramht_del(&disp->ramht); + nvkm_gpuobj_del(&disp->inst); + + nvkm_event_fini(&disp->uevent); + + if (disp->super.wq) { + destroy_workqueue(disp->super.wq); + mutex_destroy(&disp->super.mutex); + } nvkm_event_fini(&disp->vblank); nvkm_event_fini(&disp->hpd); - while (!list_empty(&disp->conn)) { - conn = list_first_entry(&disp->conn, typeof(*conn), head); + while (!list_empty(&disp->conns)) { + conn = list_first_entry(&disp->conns, typeof(*conn), head); list_del(&conn->head); nvkm_conn_del(&conn); } - while (!list_empty(&disp->outp)) { - outp = list_first_entry(&disp->outp, typeof(*outp), head); + while (!list_empty(&disp->outps)) { + outp = list_first_entry(&disp->outps, typeof(*outp), head); list_del(&outp->head); nvkm_outp_del(&outp); } - while (!list_empty(&disp->ior)) { - struct nvkm_ior *ior = - list_first_entry(&disp->ior, typeof(*ior), head); + while (!list_empty(&disp->iors)) { + ior = list_first_entry(&disp->iors, typeof(*ior), head); nvkm_ior_del(&ior); } - while (!list_empty(&disp->head)) { - struct nvkm_head *head = - list_first_entry(&disp->head, typeof(*head), head); + while (!list_empty(&disp->heads)) { + head = list_first_entry(&disp->heads, typeof(*head), head); nvkm_head_del(&head); } @@ -472,23 +444,34 @@ nvkm_disp = { }; int -nvkm_disp_ctor(const struct nvkm_disp_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_disp *disp) -{ - disp->func = func; - INIT_LIST_HEAD(&disp->head); - INIT_LIST_HEAD(&disp->ior); - INIT_LIST_HEAD(&disp->outp); - INIT_LIST_HEAD(&disp->conn); - spin_lock_init(&disp->client.lock); - return nvkm_engine_ctor(&nvkm_disp, device, type, inst, true, &disp->engine); -} - -int nvkm_disp_new_(const struct nvkm_disp_func *func, struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - if (!(*pdisp = kzalloc(sizeof(**pdisp), GFP_KERNEL))) + struct nvkm_disp *disp; + int ret; + + if (!(disp = *pdisp = kzalloc(sizeof(**pdisp), GFP_KERNEL))) return -ENOMEM; - return nvkm_disp_ctor(func, device, type, inst, *pdisp); + + disp->func = func; + INIT_LIST_HEAD(&disp->heads); + INIT_LIST_HEAD(&disp->iors); + INIT_LIST_HEAD(&disp->outps); + INIT_LIST_HEAD(&disp->conns); + spin_lock_init(&disp->client.lock); + + ret = nvkm_engine_ctor(&nvkm_disp, device, type, inst, true, &disp->engine); + if (ret) + return ret; + + if (func->super) { + disp->super.wq = create_singlethread_workqueue("nvkm-disp"); + if (!disp->super.wq) + return -ENOMEM; + + INIT_WORK(&disp->super.work, func->super); + mutex_init(&disp->super.mutex); + } + + return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), &disp->uevent); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c deleted file mode 100644 index 01253f4a9946..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/baseg84.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g84_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0008c4 }, - { 0x0088, 0x0008d0 }, - { 0x008c, 0x0008dc }, - { 0x0090, 0x0008e4 }, - { 0x0094, 0x610884 }, - { 0x00a0, 0x6108a0 }, - { 0x00a4, 0x610878 }, - { 0x00c0, 0x61086c }, - { 0x00c4, 0x610800 }, - { 0x00c8, 0x61080c }, - { 0x00cc, 0x610818 }, - { 0x00e0, 0x610858 }, - { 0x00e4, 0x610860 }, - { 0x00e8, 0x6108ac }, - { 0x00ec, 0x6108b4 }, - { 0x00fc, 0x610824 }, - { 0x0100, 0x610894 }, - { 0x0104, 0x61082c }, - { 0x0110, 0x6108bc }, - { 0x0114, 0x61088c }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -g84_disp_base_mthd = { - .name = "Base", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &g84_disp_base_mthd_base }, - { "Image", 2, &nv50_disp_base_mthd_image }, - {} - } -}; - -int -g84_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&nv50_disp_dmac_func, &g84_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c deleted file mode 100644 index 389e19dfc514..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegf119.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gf119_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x661080 }, - { 0x0084, 0x661084 }, - { 0x0088, 0x661088 }, - { 0x008c, 0x66108c }, - { 0x0090, 0x661090 }, - { 0x0094, 0x661094 }, - { 0x00a0, 0x6610a0 }, - { 0x00a4, 0x6610a4 }, - { 0x00c0, 0x6610c0 }, - { 0x00c4, 0x6610c4 }, - { 0x00c8, 0x6610c8 }, - { 0x00cc, 0x6610cc }, - { 0x00e0, 0x6610e0 }, - { 0x00e4, 0x6610e4 }, - { 0x00e8, 0x6610e8 }, - { 0x00ec, 0x6610ec }, - { 0x00fc, 0x6610fc }, - { 0x0100, 0x661100 }, - { 0x0104, 0x661104 }, - { 0x0108, 0x661108 }, - { 0x010c, 0x66110c }, - { 0x0110, 0x661110 }, - { 0x0114, 0x661114 }, - { 0x0118, 0x661118 }, - { 0x011c, 0x66111c }, - { 0x0130, 0x661130 }, - { 0x0134, 0x661134 }, - { 0x0138, 0x661138 }, - { 0x013c, 0x66113c }, - { 0x0140, 0x661140 }, - { 0x0144, 0x661144 }, - { 0x0148, 0x661148 }, - { 0x014c, 0x66114c }, - { 0x0150, 0x661150 }, - { 0x0154, 0x661154 }, - { 0x0158, 0x661158 }, - { 0x015c, 0x66115c }, - { 0x0160, 0x661160 }, - { 0x0164, 0x661164 }, - { 0x0168, 0x661168 }, - { 0x016c, 0x66116c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gf119_disp_base_mthd_image = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0400, 0x661400 }, - { 0x0404, 0x661404 }, - { 0x0408, 0x661408 }, - { 0x040c, 0x66140c }, - { 0x0410, 0x661410 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gf119_disp_base_mthd = { - .name = "Base", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_base_mthd_base }, - { "Image", 2, &gf119_disp_base_mthd_image }, - {} - } -}; - -int -gf119_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&gf119_disp_dmac_func, &gf119_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c deleted file mode 100644 index 0cb23d673aa0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basegp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&gp102_disp_dmac_func, &gf119_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c deleted file mode 100644 index 19eb7dde01f2..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/basenv50.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507c.h> -#include <nvif/unpack.h> - -int -nv50_disp_base_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_base_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create disp base channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp base channel dma vers %d " - "pushbuf %016llx head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (!nvkm_head_find(&disp->base, args->v0.head)) - return -EINVAL; - push = args->v0.pushbuf; - head = args->v0.head; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + head, - head, push, oclass, pobject); -} - -static const struct nv50_disp_mthd_list -nv50_disp_base_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0008c4 }, - { 0x0088, 0x0008d0 }, - { 0x008c, 0x0008dc }, - { 0x0090, 0x0008e4 }, - { 0x0094, 0x610884 }, - { 0x00a0, 0x6108a0 }, - { 0x00a4, 0x610878 }, - { 0x00c0, 0x61086c }, - { 0x00e0, 0x610858 }, - { 0x00e4, 0x610860 }, - { 0x00e8, 0x6108ac }, - { 0x00ec, 0x6108b4 }, - { 0x0100, 0x610894 }, - { 0x0110, 0x6108bc }, - { 0x0114, 0x61088c }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_base_mthd_image = { - .mthd = 0x0400, - .addr = 0x000000, - .data = { - { 0x0800, 0x6108f0 }, - { 0x0804, 0x6108fc }, - { 0x0808, 0x61090c }, - { 0x080c, 0x610914 }, - { 0x0810, 0x610904 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_base_mthd = { - .name = "Base", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_base_mthd_base }, - { "Image", 2, &nv50_disp_base_mthd_image }, - {} - } -}; - -int -nv50_disp_base_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_base_new_(&nv50_disp_dmac_func, &nv50_disp_base_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c deleted file mode 100644 index 5026e530f4bb..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/capsgv100.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#define gv100_disp_caps(p) container_of((p), struct gv100_disp_caps, object) -#include "rootnv50.h" - -struct gv100_disp_caps { - struct nvkm_object object; - struct nv50_disp *disp; -}; - -static int -gv100_disp_caps_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct gv100_disp_caps *caps = gv100_disp_caps(object); - struct nvkm_device *device = caps->disp->base.engine.subdev.device; - *type = NVKM_OBJECT_MAP_IO; - *addr = 0x640000 + device->func->resource_addr(device, 0); - *size = 0x1000; - return 0; -} - -static const struct nvkm_object_func -gv100_disp_caps = { - .map = gv100_disp_caps_map, -}; - -int -gv100_disp_caps_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - struct gv100_disp_caps *caps; - - if (!(caps = kzalloc(sizeof(*caps), GFP_KERNEL))) - return -ENOMEM; - *pobject = &caps->object; - - nvkm_object_ctor(&gv100_disp_caps, oclass, &caps->object); - caps->disp = disp; - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c new file mode 100644 index 000000000000..d5e18daed79f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.c @@ -0,0 +1,275 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "chan.h" + +#include <core/oproxy.h> +#include <core/ramht.h> + +#include <nvif/if0014.h> + +static int +nvkm_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + u64 size, base = chan->func->user(chan, &size); + + *data = nvkm_rd32(device, base + addr); + return 0; +} + +static int +nvkm_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + u64 size, base = chan->func->user(chan, &size); + + nvkm_wr32(device, base + addr, data); + return 0; +} + +static int +nvkm_disp_chan_ntfy(struct nvkm_object *object, u32 type, struct nvkm_event **pevent) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_disp *disp = chan->disp; + + switch (type) { + case 0: + *pevent = &disp->uevent; + return 0; + default: + break; + } + + return -EINVAL; +} + +static int +nvkm_disp_chan_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u64 base = device->func->resource_addr(device, 0); + + *type = NVKM_OBJECT_MAP_IO; + *addr = base + chan->func->user(chan, size); + return 0; +} + +struct nvkm_disp_chan_object { + struct nvkm_oproxy oproxy; + struct nvkm_disp *disp; + int hash; +}; + +static void +nvkm_disp_chan_child_del_(struct nvkm_oproxy *base) +{ + struct nvkm_disp_chan_object *object = container_of(base, typeof(*object), oproxy); + + nvkm_ramht_remove(object->disp->ramht, object->hash); +} + +static const struct nvkm_oproxy_func +nvkm_disp_chan_child_func_ = { + .dtor[0] = nvkm_disp_chan_child_del_, +}; + +static int +nvkm_disp_chan_child_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(oclass->parent); + struct nvkm_disp *disp = chan->disp; + struct nvkm_device *device = disp->engine.subdev.device; + const struct nvkm_device_oclass *sclass = oclass->priv; + struct nvkm_disp_chan_object *object; + int ret; + + if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) + return -ENOMEM; + nvkm_oproxy_ctor(&nvkm_disp_chan_child_func_, oclass, &object->oproxy); + object->disp = disp; + *pobject = &object->oproxy.base; + + ret = sclass->ctor(device, oclass, argv, argc, &object->oproxy.object); + if (ret) + return ret; + + object->hash = chan->func->bind(chan, object->oproxy.object, oclass->handle); + if (object->hash < 0) + return object->hash; + + return 0; +} + +static int +nvkm_disp_chan_child_get(struct nvkm_object *object, int index, struct nvkm_oclass *sclass) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_device *device = chan->disp->engine.subdev.device; + const struct nvkm_device_oclass *oclass = NULL; + + if (chan->func->bind) + sclass->engine = nvkm_device_engine(device, NVKM_ENGINE_DMAOBJ, 0); + else + sclass->engine = NULL; + + if (sclass->engine && sclass->engine->func->base.sclass) { + sclass->engine->func->base.sclass(sclass, index, &oclass); + if (oclass) { + sclass->ctor = nvkm_disp_chan_child_new; + sclass->priv = oclass; + return 0; + } + } + + return -EINVAL; +} + +static int +nvkm_disp_chan_fini(struct nvkm_object *object, bool suspend) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + + chan->func->fini(chan); + chan->func->intr(chan, false); + return 0; +} + +static int +nvkm_disp_chan_init(struct nvkm_object *object) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + + chan->func->intr(chan, true); + return chan->func->init(chan); +} + +static void * +nvkm_disp_chan_dtor(struct nvkm_object *object) +{ + struct nvkm_disp_chan *chan = nvkm_disp_chan(object); + struct nvkm_disp *disp = chan->disp; + + spin_lock(&disp->client.lock); + if (disp->chan[chan->chid.user] == chan) + disp->chan[chan->chid.user] = NULL; + spin_unlock(&disp->client.lock); + + nvkm_memory_unref(&chan->memory); + return chan; +} + +static const struct nvkm_object_func +nvkm_disp_chan = { + .dtor = nvkm_disp_chan_dtor, + .init = nvkm_disp_chan_init, + .fini = nvkm_disp_chan_fini, + .rd32 = nvkm_disp_chan_rd32, + .wr32 = nvkm_disp_chan_wr32, + .ntfy = nvkm_disp_chan_ntfy, + .map = nvkm_disp_chan_map, + .sclass = nvkm_disp_chan_child_get, +}; + +static int +nvkm_disp_chan_new_(struct nvkm_disp *disp, int nr, const struct nvkm_oclass *oclass, + void *argv, u32 argc, struct nvkm_object **pobject) +{ + const struct nvkm_disp_chan_user *user = NULL; + struct nvkm_disp_chan *chan; + union nvif_disp_chan_args *args = argv; + int ret, i; + + for (i = 0; disp->func->user[i].ctor; i++) { + if (disp->func->user[i].base.oclass == oclass->base.oclass) { + user = disp->func->user[i].chan; + break; + } + } + + if (WARN_ON(!user)) + return -EINVAL; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + if (args->v0.id >= nr || !args->v0.pushbuf != !user->func->push) + return -EINVAL; + + if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) + return -ENOMEM; + *pobject = &chan->object; + + nvkm_object_ctor(&nvkm_disp_chan, oclass, &chan->object); + chan->func = user->func; + chan->mthd = user->mthd; + chan->disp = disp; + chan->chid.ctrl = user->ctrl + args->v0.id; + chan->chid.user = user->user + args->v0.id; + chan->head = args->v0.id; + + if (chan->func->push) { + ret = chan->func->push(chan, args->v0.pushbuf); + if (ret) + return ret; + } + + spin_lock(&disp->client.lock); + if (disp->chan[chan->chid.user]) { + spin_unlock(&disp->client.lock); + return -EBUSY; + } + disp->chan[chan->chid.user] = chan; + spin_unlock(&disp->client.lock); + return 0; +} + +int +nvkm_disp_wndw_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + + return nvkm_disp_chan_new_(disp, disp->wndw.nr, oclass, argv, argc, pobject); +} + +int +nvkm_disp_chan_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + + return nvkm_disp_chan_new_(disp, disp->head.nr, oclass, argv, argc, pobject); +} + +int +nvkm_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + + return nvkm_disp_chan_new_(disp, 1, oclass, argv, argc, pobject); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h new file mode 100644 index 000000000000..398336ffb685 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/chan.h @@ -0,0 +1,135 @@ +/* SPDX-License-Identifier: MIT */ +#ifndef __NVKM_DISP_CHAN_H__ +#define __NVKM_DISP_CHAN_H__ +#define nvkm_disp_chan(p) container_of((p), struct nvkm_disp_chan, object) +#include <core/object.h> +#include "priv.h" + +struct nvkm_disp_chan { + const struct nvkm_disp_chan_func *func; + const struct nvkm_disp_chan_mthd *mthd; + struct nvkm_disp *disp; + + struct { + int ctrl; + int user; + } chid; + int head; + + struct nvkm_object object; + + struct nvkm_memory *memory; + u64 push; + + u32 suspend_put; +}; + +int nvkm_disp_core_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_disp_chan_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_disp_wndw_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); + +struct nvkm_disp_chan_func { + int (*push)(struct nvkm_disp_chan *, u64 object); + int (*init)(struct nvkm_disp_chan *); + void (*fini)(struct nvkm_disp_chan *); + void (*intr)(struct nvkm_disp_chan *, bool en); + u64 (*user)(struct nvkm_disp_chan *, u64 *size); + int (*bind)(struct nvkm_disp_chan *, struct nvkm_object *, u32 handle); +}; + +void nv50_disp_chan_intr(struct nvkm_disp_chan *, bool); +u64 nv50_disp_chan_user(struct nvkm_disp_chan *, u64 *); +extern const struct nvkm_disp_chan_func nv50_disp_pioc_func; +extern const struct nvkm_disp_chan_func nv50_disp_dmac_func; +int nv50_disp_dmac_push(struct nvkm_disp_chan *, u64); +int nv50_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); +extern const struct nvkm_disp_chan_func nv50_disp_core_func; + +void gf119_disp_chan_intr(struct nvkm_disp_chan *, bool); +extern const struct nvkm_disp_chan_func gf119_disp_pioc_func; +extern const struct nvkm_disp_chan_func gf119_disp_dmac_func; +void gf119_disp_dmac_fini(struct nvkm_disp_chan *); +int gf119_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); +extern const struct nvkm_disp_chan_func gf119_disp_core_func; +void gf119_disp_core_fini(struct nvkm_disp_chan *); + +extern const struct nvkm_disp_chan_func gp102_disp_dmac_func; + +u64 gv100_disp_chan_user(struct nvkm_disp_chan *, u64 *); +int gv100_disp_dmac_init(struct nvkm_disp_chan *); +void gv100_disp_dmac_fini(struct nvkm_disp_chan *); +int gv100_disp_dmac_bind(struct nvkm_disp_chan *, struct nvkm_object *, u32); + +struct nvkm_disp_chan_user { + const struct nvkm_disp_chan_func *func; + int ctrl; + int user; + const struct nvkm_disp_chan_mthd *mthd; +}; + +extern const struct nvkm_disp_chan_user nv50_disp_oimm; +extern const struct nvkm_disp_chan_user nv50_disp_curs; + +extern const struct nvkm_disp_chan_user g84_disp_core; +extern const struct nvkm_disp_chan_user g84_disp_base; +extern const struct nvkm_disp_chan_user g84_disp_ovly; + +extern const struct nvkm_disp_chan_user g94_disp_core; + +extern const struct nvkm_disp_chan_user gt200_disp_ovly; + +extern const struct nvkm_disp_chan_user gf119_disp_base; +extern const struct nvkm_disp_chan_user gf119_disp_oimm; +extern const struct nvkm_disp_chan_user gf119_disp_curs; + +extern const struct nvkm_disp_chan_user gk104_disp_core; +extern const struct nvkm_disp_chan_user gk104_disp_ovly; + +extern const struct nvkm_disp_chan_user gv100_disp_core; +extern const struct nvkm_disp_chan_user gv100_disp_curs; +extern const struct nvkm_disp_chan_user gv100_disp_wndw; +extern const struct nvkm_disp_chan_user gv100_disp_wimm; + +struct nvkm_disp_mthd_list { + u32 mthd; + u32 addr; + struct { + u32 mthd; + u32 addr; + const char *name; + } data[]; +}; + +struct nvkm_disp_chan_mthd { + const char *name; + u32 addr; + s32 prev; + struct { + const char *name; + int nr; + const struct nvkm_disp_mthd_list *mthd; + } data[]; +}; + +void nv50_disp_chan_mthd(struct nvkm_disp_chan *, int debug); + +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_base; +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_sor; +extern const struct nvkm_disp_mthd_list nv50_disp_core_mthd_pior; +extern const struct nvkm_disp_mthd_list nv50_disp_base_mthd_image; + +extern const struct nvkm_disp_chan_mthd g84_disp_core_mthd; +extern const struct nvkm_disp_mthd_list g84_disp_core_mthd_dac; +extern const struct nvkm_disp_mthd_list g84_disp_core_mthd_head; + +extern const struct nvkm_disp_chan_mthd g94_disp_core_mthd; + +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_base; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_dac; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_sor; +extern const struct nvkm_disp_mthd_list gf119_disp_core_mthd_pior; +extern const struct nvkm_disp_chan_mthd gf119_disp_base_mthd; + +extern const struct nvkm_disp_chan_mthd gk104_disp_core_mthd; +extern const struct nvkm_disp_chan_mthd gk104_disp_ovly_mthd; +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c deleted file mode 100644 index 525f95d06429..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changf119.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static void -gf119_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000000 << index); - nvkm_wr32(device, 0x61008c, 0x00000001 << index); -} - -static void -gf119_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) -{ - struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_wr32(device, 0x61008c, 0x00000001 << index); - nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000001 << index); -} - -const struct nvkm_event_func -gf119_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, - .init = gf119_disp_chan_uevent_init, - .fini = gf119_disp_chan_uevent_fini, -}; - -void -gf119_disp_chan_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00000001 << chan->chid.user; - if (!en) { - nvkm_mask(device, 0x610090, mask, 0x00000000); - nvkm_mask(device, 0x6100a0, mask, 0x00000000); - } else { - nvkm_mask(device, 0x6100a0, mask, mask); - } -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c deleted file mode 100644 index 75247c9c7e10..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/changv100.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "channv50.h" - -const struct nvkm_event_func -gv100_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, -}; - -u64 -gv100_disp_chan_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x1000; - return 0x690000 + ((chan->chid.user - 1) * 0x1000); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c deleted file mode 100644 index a7a7eb041515..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "rootnv50.h" - -#include <core/client.h> -#include <core/notify.h> -#include <core/oproxy.h> -#include <core/ramht.h> -#include <engine/dma.h> - -#include <nvif/cl507d.h> -#include <nvif/event.h> -#include <nvif/unpack.h> - -static void -nv50_disp_mthd_list(struct nv50_disp *disp, int debug, u32 base, int c, - const struct nv50_disp_mthd_list *list, int inst) -{ - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int i; - - for (i = 0; list->data[i].mthd; i++) { - if (list->data[i].addr) { - u32 next = nvkm_rd32(device, list->data[i].addr + base + 0); - u32 prev = nvkm_rd32(device, list->data[i].addr + base + c); - u32 mthd = list->data[i].mthd + (list->mthd * inst); - const char *name = list->data[i].name; - char mods[16]; - - if (prev != next) - snprintf(mods, sizeof(mods), "-> %08x", next); - else - snprintf(mods, sizeof(mods), "%13c", ' '); - - nvkm_printk_(subdev, debug, info, - "\t%04x: %08x %s%s%s\n", - mthd, prev, mods, name ? " // " : "", - name ? name : ""); - } - } -} - -void -nv50_disp_chan_mthd(struct nv50_disp_chan *chan, int debug) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - const struct nv50_disp_chan_mthd *mthd = chan->mthd; - const struct nv50_disp_mthd_list *list; - int i, j; - - if (debug > subdev->debug) - return; - if (!mthd) - return; - - for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { - u32 base = chan->head * mthd->addr; - for (j = 0; j < mthd->data[i].nr; j++, base += list->addr) { - const char *cname = mthd->name; - const char *sname = ""; - char cname_[16], sname_[16]; - - if (mthd->addr) { - snprintf(cname_, sizeof(cname_), "%s %d", - mthd->name, chan->chid.user); - cname = cname_; - } - - if (mthd->data[i].nr > 1) { - snprintf(sname_, sizeof(sname_), " - %s %d", - mthd->data[i].name, j); - sname = sname_; - } - - nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname); - nv50_disp_mthd_list(disp, debug, base, mthd->prev, - list, j); - } - } -} - -static void -nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) -{ - struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000000 << index); - nvkm_wr32(device, 0x610020, 0x00000001 << index); -} - -static void -nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) -{ - struct nv50_disp *disp = container_of(event, typeof(*disp), uevent); - struct nvkm_device *device = disp->base.engine.subdev.device; - nvkm_wr32(device, 0x610020, 0x00000001 << index); - nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000001 << index); -} - -void -nv50_disp_chan_uevent_send(struct nv50_disp *disp, int chid) -{ - struct nvif_notify_uevent_rep { - } rep; - - nvkm_event_send(&disp->uevent, 1, chid, &rep, sizeof(rep)); -} - -int -nv50_disp_chan_uevent_ctor(struct nvkm_object *object, void *data, u32 size, - struct nvkm_notify *notify) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - union { - struct nvif_notify_uevent_req none; - } *args = data; - int ret = -ENOSYS; - - if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { - notify->size = sizeof(struct nvif_notify_uevent_rep); - notify->types = 1; - notify->index = chan->chid.user; - return 0; - } - - return ret; -} - -const struct nvkm_event_func -nv50_disp_chan_uevent = { - .ctor = nv50_disp_chan_uevent_ctor, - .init = nv50_disp_chan_uevent_init, - .fini = nv50_disp_chan_uevent_fini, -}; - -u64 -nv50_disp_chan_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x1000; - return 0x640000 + (chan->chid.user * 0x1000); -} - -void -nv50_disp_chan_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00010001 << chan->chid.user; - const u32 data = en ? 0x00010000 << chan->chid.user : 0x00000000; - nvkm_mask(device, 0x610028, mask, data); -} - -static int -nv50_disp_chan_rd32(struct nvkm_object *object, u64 addr, u32 *data) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - u64 size, base = chan->func->user(chan, &size); - *data = nvkm_rd32(device, base + addr); - return 0; -} - -static int -nv50_disp_chan_wr32(struct nvkm_object *object, u64 addr, u32 data) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - u64 size, base = chan->func->user(chan, &size); - nvkm_wr32(device, base + addr, data); - return 0; -} - -static int -nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, - struct nvkm_event **pevent) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nv50_disp *disp = chan->disp; - switch (type) { - case NV50_DISP_CORE_CHANNEL_DMA_V0_NTFY_UEVENT: - *pevent = &disp->uevent; - return 0; - default: - break; - } - return -EINVAL; -} - -static int -nv50_disp_chan_map(struct nvkm_object *object, void *argv, u32 argc, - enum nvkm_object_map *type, u64 *addr, u64 *size) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u64 base = device->func->resource_addr(device, 0); - *type = NVKM_OBJECT_MAP_IO; - *addr = base + chan->func->user(chan, size); - return 0; -} - -struct nv50_disp_chan_object { - struct nvkm_oproxy oproxy; - struct nv50_disp *disp; - int hash; -}; - -static void -nv50_disp_chan_child_del_(struct nvkm_oproxy *base) -{ - struct nv50_disp_chan_object *object = - container_of(base, typeof(*object), oproxy); - nvkm_ramht_remove(object->disp->ramht, object->hash); -} - -static const struct nvkm_oproxy_func -nv50_disp_chan_child_func_ = { - .dtor[0] = nv50_disp_chan_child_del_, -}; - -static int -nv50_disp_chan_child_new(const struct nvkm_oclass *oclass, - void *argv, u32 argc, struct nvkm_object **pobject) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(oclass->parent); - struct nv50_disp *disp = chan->disp; - struct nvkm_device *device = disp->base.engine.subdev.device; - const struct nvkm_device_oclass *sclass = oclass->priv; - struct nv50_disp_chan_object *object; - int ret; - - if (!(object = kzalloc(sizeof(*object), GFP_KERNEL))) - return -ENOMEM; - nvkm_oproxy_ctor(&nv50_disp_chan_child_func_, oclass, &object->oproxy); - object->disp = disp; - *pobject = &object->oproxy.base; - - ret = sclass->ctor(device, oclass, argv, argc, &object->oproxy.object); - if (ret) - return ret; - - object->hash = chan->func->bind(chan, object->oproxy.object, - oclass->handle); - if (object->hash < 0) - return object->hash; - - return 0; -} - -static int -nv50_disp_chan_child_get(struct nvkm_object *object, int index, - struct nvkm_oclass *sclass) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const struct nvkm_device_oclass *oclass = NULL; - - if (chan->func->bind) - sclass->engine = nvkm_device_engine(device, NVKM_ENGINE_DMAOBJ, 0); - else - sclass->engine = NULL; - - if (sclass->engine && sclass->engine->func->base.sclass) { - sclass->engine->func->base.sclass(sclass, index, &oclass); - if (oclass) { - sclass->ctor = nv50_disp_chan_child_new, - sclass->priv = oclass; - return 0; - } - } - - return -EINVAL; -} - -static int -nv50_disp_chan_fini(struct nvkm_object *object, bool suspend) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - chan->func->fini(chan); - chan->func->intr(chan, false); - return 0; -} - -static int -nv50_disp_chan_init(struct nvkm_object *object) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - chan->func->intr(chan, true); - return chan->func->init(chan); -} - -static void * -nv50_disp_chan_dtor(struct nvkm_object *object) -{ - struct nv50_disp_chan *chan = nv50_disp_chan(object); - struct nv50_disp *disp = chan->disp; - if (chan->chid.user >= 0) - disp->chan[chan->chid.user] = NULL; - nvkm_memory_unref(&chan->memory); - return chan; -} - -static const struct nvkm_object_func -nv50_disp_chan = { - .dtor = nv50_disp_chan_dtor, - .init = nv50_disp_chan_init, - .fini = nv50_disp_chan_fini, - .rd32 = nv50_disp_chan_rd32, - .wr32 = nv50_disp_chan_wr32, - .ntfy = nv50_disp_chan_ntfy, - .map = nv50_disp_chan_map, - .sclass = nv50_disp_chan_child_get, -}; - -int -nv50_disp_chan_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int ctrl, int user, int head, - const struct nvkm_oclass *oclass, - struct nvkm_object **pobject) -{ - struct nv50_disp_chan *chan; - - if (!(chan = kzalloc(sizeof(*chan), GFP_KERNEL))) - return -ENOMEM; - *pobject = &chan->object; - - nvkm_object_ctor(&nv50_disp_chan, oclass, &chan->object); - chan->func = func; - chan->mthd = mthd; - chan->disp = disp; - chan->chid.ctrl = ctrl; - chan->chid.user = user; - chan->head = head; - - if (disp->chan[chan->chid.user]) { - chan->chid.user = -1; - return -EBUSY; - } - disp->chan[chan->chid.user] = chan; - return 0; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h deleted file mode 100644 index 9cf2cfe2010c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h +++ /dev/null @@ -1,193 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV50_DISP_CHAN_H__ -#define __NV50_DISP_CHAN_H__ -#define nv50_disp_chan(p) container_of((p), struct nv50_disp_chan, object) -#include <core/object.h> -#include "nv50.h" -struct nv50_disp_root; - -struct nv50_disp_chan { - const struct nv50_disp_chan_func *func; - const struct nv50_disp_chan_mthd *mthd; - struct nv50_disp *disp; - - struct { - int ctrl; - int user; - } chid; - int head; - - struct nvkm_object object; - - struct nvkm_memory *memory; - u64 push; - - u32 suspend_put; -}; - -struct nv50_disp_chan_func { - int (*init)(struct nv50_disp_chan *); - void (*fini)(struct nv50_disp_chan *); - void (*intr)(struct nv50_disp_chan *, bool en); - u64 (*user)(struct nv50_disp_chan *, u64 *size); - int (*bind)(struct nv50_disp_chan *, struct nvkm_object *, u32 handle); -}; - -int nv50_disp_chan_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int ctrl, int user, int head, - const struct nvkm_oclass *, struct nvkm_object **); -int nv50_disp_dmac_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int chid, int head, u64 push, - const struct nvkm_oclass *, struct nvkm_object **); - -void nv50_disp_chan_intr(struct nv50_disp_chan *, bool); -u64 nv50_disp_chan_user(struct nv50_disp_chan *, u64 *); -extern const struct nv50_disp_chan_func nv50_disp_pioc_func; -extern const struct nv50_disp_chan_func nv50_disp_dmac_func; -int nv50_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); -extern const struct nv50_disp_chan_func nv50_disp_core_func; - -void gf119_disp_chan_intr(struct nv50_disp_chan *, bool); -extern const struct nv50_disp_chan_func gf119_disp_pioc_func; -extern const struct nv50_disp_chan_func gf119_disp_dmac_func; -void gf119_disp_dmac_fini(struct nv50_disp_chan *); -int gf119_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); -extern const struct nv50_disp_chan_func gf119_disp_core_func; -void gf119_disp_core_fini(struct nv50_disp_chan *); - -extern const struct nv50_disp_chan_func gp102_disp_dmac_func; - -u64 gv100_disp_chan_user(struct nv50_disp_chan *, u64 *); -int gv100_disp_dmac_init(struct nv50_disp_chan *); -void gv100_disp_dmac_fini(struct nv50_disp_chan *); -int gv100_disp_dmac_bind(struct nv50_disp_chan *, struct nvkm_object *, u32); - -int nv50_disp_curs_new_(const struct nv50_disp_chan_func *, - struct nv50_disp *, int ctrl, int user, - const struct nvkm_oclass *, void *argv, u32 argc, - struct nvkm_object **); -int nv50_disp_oimm_new_(const struct nv50_disp_chan_func *, - struct nv50_disp *, int ctrl, int user, - const struct nvkm_oclass *, void *argv, u32 argc, - struct nvkm_object **); -int nv50_disp_base_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int chid, - const struct nvkm_oclass *, void *argv, u32 argc, - struct nvkm_object **); -int nv50_disp_core_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **); -int nv50_disp_ovly_new_(const struct nv50_disp_chan_func *, - const struct nv50_disp_chan_mthd *, - struct nv50_disp *, int chid, - const struct nvkm_oclass *, void *argv, u32 argc, - struct nvkm_object **); - -int nv50_disp_curs_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int nv50_disp_oimm_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int nv50_disp_base_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int nv50_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int nv50_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int g84_disp_base_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int g84_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int g84_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int g94_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gt200_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gf119_disp_curs_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gf119_disp_oimm_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gf119_disp_base_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gf119_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gf119_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gk104_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gk104_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gp102_disp_curs_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gp102_disp_oimm_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gp102_disp_base_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gp102_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gp102_disp_ovly_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -int gv100_disp_curs_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gv100_disp_wimm_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gv100_disp_core_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); -int gv100_disp_wndw_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -struct nv50_disp_mthd_list { - u32 mthd; - u32 addr; - struct { - u32 mthd; - u32 addr; - const char *name; - } data[]; -}; - -struct nv50_disp_chan_mthd { - const char *name; - u32 addr; - s32 prev; - struct { - const char *name; - int nr; - const struct nv50_disp_mthd_list *mthd; - } data[]; -}; - -void nv50_disp_chan_mthd(struct nv50_disp_chan *, int debug); - -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_base; -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_sor; -extern const struct nv50_disp_mthd_list nv50_disp_core_mthd_pior; -extern const struct nv50_disp_mthd_list nv50_disp_base_mthd_image; - -extern const struct nv50_disp_chan_mthd g84_disp_core_mthd; -extern const struct nv50_disp_mthd_list g84_disp_core_mthd_dac; -extern const struct nv50_disp_mthd_list g84_disp_core_mthd_head; - -extern const struct nv50_disp_chan_mthd g94_disp_core_mthd; - -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_base; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_dac; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_sor; -extern const struct nv50_disp_mthd_list gf119_disp_core_mthd_pior; -extern const struct nv50_disp_chan_mthd gf119_disp_base_mthd; - -extern const struct nv50_disp_chan_mthd gk104_disp_core_mthd; -extern const struct nv50_disp_chan_mthd gk104_disp_ovly_mthd; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c index febc5c274488..7ed11801a3ae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.c @@ -86,6 +86,7 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info, conn->disp = disp; conn->index = index; conn->info = *info; + conn->info.hpd = DCB_GPIO_UNUSED; CONN_DBG(conn, "type %02x loc %d hpd %02x dp %x di %x sr %x lcdid %x", info->type, info->location, info->hpd, info->dp, @@ -100,11 +101,12 @@ nvkm_conn_ctor(struct nvkm_disp *disp, int index, struct nvbios_connE *info, ret = nvkm_gpio_find(gpio, 0, info->hpd, DCB_GPIO_UNUSED, &func); if (ret) { - CONN_ERR(conn, "func %02x lookup failed, %d", - info->hpd, ret); + CONN_ERR(conn, "func %02x lookup failed, %d", info->hpd, ret); return; } + conn->info.hpd = func.line; + ret = nvkm_notify_init(NULL, &gpio->event, nvkm_conn_hpd, true, &(struct nvkm_gpio_ntfy_req) { .mask = NVKM_GPIO_TOGGLED, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h index dcbe60a4b911..f109634ce5ca 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/conn.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_CONN_H__ #define __NVKM_DISP_CONN_H__ -#include <engine/disp.h> +#include "priv.h" #include <core/notify.h> #include <subdev/bios.h> @@ -15,6 +15,8 @@ struct nvkm_conn { struct nvkm_notify hpd; struct list_head head; + + struct nvkm_object object; }; int nvkm_conn_new(struct nvkm_disp *, int index, struct nvbios_connE *, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c deleted file mode 100644 index cfc54aad3e7c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg84.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -const struct nv50_disp_mthd_list -g84_disp_core_mthd_dac = { - .mthd = 0x0080, - .addr = 0x000008, - .data = { - { 0x0400, 0x610b58 }, - { 0x0404, 0x610bdc }, - { 0x0420, 0x610bc4 }, - {} - } -}; - -const struct nv50_disp_mthd_list -g84_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000540, - .data = { - { 0x0800, 0x610ad8 }, - { 0x0804, 0x610ad0 }, - { 0x0808, 0x610a48 }, - { 0x080c, 0x610a78 }, - { 0x0810, 0x610ac0 }, - { 0x0814, 0x610af8 }, - { 0x0818, 0x610b00 }, - { 0x081c, 0x610ae8 }, - { 0x0820, 0x610af0 }, - { 0x0824, 0x610b08 }, - { 0x0828, 0x610b10 }, - { 0x082c, 0x610a68 }, - { 0x0830, 0x610a60 }, - { 0x0834, 0x000000 }, - { 0x0838, 0x610a40 }, - { 0x0840, 0x610a24 }, - { 0x0844, 0x610a2c }, - { 0x0848, 0x610aa8 }, - { 0x084c, 0x610ab0 }, - { 0x085c, 0x610c5c }, - { 0x0860, 0x610a84 }, - { 0x0864, 0x610a90 }, - { 0x0868, 0x610b18 }, - { 0x086c, 0x610b20 }, - { 0x0870, 0x610ac8 }, - { 0x0874, 0x610a38 }, - { 0x0878, 0x610c50 }, - { 0x0880, 0x610a58 }, - { 0x0884, 0x610a9c }, - { 0x089c, 0x610c68 }, - { 0x08a0, 0x610a70 }, - { 0x08a4, 0x610a50 }, - { 0x08a8, 0x610ae0 }, - { 0x08c0, 0x610b28 }, - { 0x08c4, 0x610b30 }, - { 0x08c8, 0x610b40 }, - { 0x08d4, 0x610b38 }, - { 0x08d8, 0x610b48 }, - { 0x08dc, 0x610b50 }, - { 0x0900, 0x610a18 }, - { 0x0904, 0x610ab8 }, - { 0x0910, 0x610c70 }, - { 0x0914, 0x610c78 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -g84_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &g84_disp_core_mthd_dac }, - { "SOR", 2, &nv50_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &g84_disp_core_mthd_head }, - {} - } -}; - -int -g84_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &g84_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c deleted file mode 100644 index e911925f1182..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coreg94.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g94_disp_core_mthd_sor = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0600, 0x610794 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -g94_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &g84_disp_core_mthd_dac }, - { "SOR", 4, &g94_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &g84_disp_core_mthd_head }, - {} - } -}; - -int -g94_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &g94_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c deleted file mode 100644 index 689e3cdd959a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregf119.c +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <subdev/timer.h> - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x660080 }, - { 0x0084, 0x660084 }, - { 0x0088, 0x660088 }, - { 0x008c, 0x000000 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_dac = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0180, 0x660180 }, - { 0x0184, 0x660184 }, - { 0x0188, 0x660188 }, - { 0x0190, 0x660190 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_sor = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0200, 0x660200 }, - { 0x0204, 0x660204 }, - { 0x0208, 0x660208 }, - { 0x0210, 0x660210 }, - {} - } -}; - -const struct nv50_disp_mthd_list -gf119_disp_core_mthd_pior = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0300, 0x660300 }, - { 0x0304, 0x660304 }, - { 0x0308, 0x660308 }, - { 0x0310, 0x660310 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gf119_disp_core_mthd_head = { - .mthd = 0x0300, - .addr = 0x000300, - .data = { - { 0x0400, 0x660400 }, - { 0x0404, 0x660404 }, - { 0x0408, 0x660408 }, - { 0x040c, 0x66040c }, - { 0x0410, 0x660410 }, - { 0x0414, 0x660414 }, - { 0x0418, 0x660418 }, - { 0x041c, 0x66041c }, - { 0x0420, 0x660420 }, - { 0x0424, 0x660424 }, - { 0x0428, 0x660428 }, - { 0x042c, 0x66042c }, - { 0x0430, 0x660430 }, - { 0x0434, 0x660434 }, - { 0x0438, 0x660438 }, - { 0x0440, 0x660440 }, - { 0x0444, 0x660444 }, - { 0x0448, 0x660448 }, - { 0x044c, 0x66044c }, - { 0x0450, 0x660450 }, - { 0x0454, 0x660454 }, - { 0x0458, 0x660458 }, - { 0x045c, 0x66045c }, - { 0x0460, 0x660460 }, - { 0x0468, 0x660468 }, - { 0x046c, 0x66046c }, - { 0x0470, 0x660470 }, - { 0x0474, 0x660474 }, - { 0x0480, 0x660480 }, - { 0x0484, 0x660484 }, - { 0x048c, 0x66048c }, - { 0x0490, 0x660490 }, - { 0x0494, 0x660494 }, - { 0x0498, 0x660498 }, - { 0x04b0, 0x6604b0 }, - { 0x04b8, 0x6604b8 }, - { 0x04bc, 0x6604bc }, - { 0x04c0, 0x6604c0 }, - { 0x04c4, 0x6604c4 }, - { 0x04c8, 0x6604c8 }, - { 0x04d0, 0x6604d0 }, - { 0x04d4, 0x6604d4 }, - { 0x04e0, 0x6604e0 }, - { 0x04e4, 0x6604e4 }, - { 0x04e8, 0x6604e8 }, - { 0x04ec, 0x6604ec }, - { 0x04f0, 0x6604f0 }, - { 0x04f4, 0x6604f4 }, - { 0x04f8, 0x6604f8 }, - { 0x04fc, 0x6604fc }, - { 0x0500, 0x660500 }, - { 0x0504, 0x660504 }, - { 0x0508, 0x660508 }, - { 0x050c, 0x66050c }, - { 0x0510, 0x660510 }, - { 0x0514, 0x660514 }, - { 0x0518, 0x660518 }, - { 0x051c, 0x66051c }, - { 0x052c, 0x66052c }, - { 0x0530, 0x660530 }, - { 0x054c, 0x66054c }, - { 0x0550, 0x660550 }, - { 0x0554, 0x660554 }, - { 0x0558, 0x660558 }, - { 0x055c, 0x66055c }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gf119_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_core_mthd_base }, - { "DAC", 3, &gf119_disp_core_mthd_dac }, - { "SOR", 8, &gf119_disp_core_mthd_sor }, - { "PIOR", 4, &gf119_disp_core_mthd_pior }, - { "HEAD", 4, &gf119_disp_core_mthd_head }, - {} - } -}; - -void -gf119_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* deactivate channel */ - nvkm_mask(device, 0x610490, 0x00000010, 0x00000000); - nvkm_mask(device, 0x610490, 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "core fini: %08x\n", - nvkm_rd32(device, 0x610490)); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000); -} - -static int -gf119_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610494, chan->push); - nvkm_wr32(device, 0x610498, 0x00010000); - nvkm_wr32(device, 0x61049c, 0x00000001); - nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610490, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610490)); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_core_func = { - .init = gf119_disp_core_init, - .fini = gf119_disp_core_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; - -int -gf119_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gf119_disp_core_func, &gf119_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c deleted file mode 100644 index 5c800174e079..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregk104.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gk104_disp_core_mthd_head = { - .mthd = 0x0300, - .addr = 0x000300, - .data = { - { 0x0400, 0x660400 }, - { 0x0404, 0x660404 }, - { 0x0408, 0x660408 }, - { 0x040c, 0x66040c }, - { 0x0410, 0x660410 }, - { 0x0414, 0x660414 }, - { 0x0418, 0x660418 }, - { 0x041c, 0x66041c }, - { 0x0420, 0x660420 }, - { 0x0424, 0x660424 }, - { 0x0428, 0x660428 }, - { 0x042c, 0x66042c }, - { 0x0430, 0x660430 }, - { 0x0434, 0x660434 }, - { 0x0438, 0x660438 }, - { 0x0440, 0x660440 }, - { 0x0444, 0x660444 }, - { 0x0448, 0x660448 }, - { 0x044c, 0x66044c }, - { 0x0450, 0x660450 }, - { 0x0454, 0x660454 }, - { 0x0458, 0x660458 }, - { 0x045c, 0x66045c }, - { 0x0460, 0x660460 }, - { 0x0468, 0x660468 }, - { 0x046c, 0x66046c }, - { 0x0470, 0x660470 }, - { 0x0474, 0x660474 }, - { 0x047c, 0x66047c }, - { 0x0480, 0x660480 }, - { 0x0484, 0x660484 }, - { 0x0488, 0x660488 }, - { 0x048c, 0x66048c }, - { 0x0490, 0x660490 }, - { 0x0494, 0x660494 }, - { 0x0498, 0x660498 }, - { 0x04a0, 0x6604a0 }, - { 0x04b0, 0x6604b0 }, - { 0x04b8, 0x6604b8 }, - { 0x04bc, 0x6604bc }, - { 0x04c0, 0x6604c0 }, - { 0x04c4, 0x6604c4 }, - { 0x04c8, 0x6604c8 }, - { 0x04d0, 0x6604d0 }, - { 0x04d4, 0x6604d4 }, - { 0x04e0, 0x6604e0 }, - { 0x04e4, 0x6604e4 }, - { 0x04e8, 0x6604e8 }, - { 0x04ec, 0x6604ec }, - { 0x04f0, 0x6604f0 }, - { 0x04f4, 0x6604f4 }, - { 0x04f8, 0x6604f8 }, - { 0x04fc, 0x6604fc }, - { 0x0500, 0x660500 }, - { 0x0504, 0x660504 }, - { 0x0508, 0x660508 }, - { 0x050c, 0x66050c }, - { 0x0510, 0x660510 }, - { 0x0514, 0x660514 }, - { 0x0518, 0x660518 }, - { 0x051c, 0x66051c }, - { 0x0520, 0x660520 }, - { 0x0524, 0x660524 }, - { 0x052c, 0x66052c }, - { 0x0530, 0x660530 }, - { 0x054c, 0x66054c }, - { 0x0550, 0x660550 }, - { 0x0554, 0x660554 }, - { 0x0558, 0x660558 }, - { 0x055c, 0x66055c }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gk104_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_core_mthd_base }, - { "DAC", 3, &gf119_disp_core_mthd_dac }, - { "SOR", 8, &gf119_disp_core_mthd_sor }, - { "PIOR", 4, &gf119_disp_core_mthd_pior }, - { "HEAD", 4, &gk104_disp_core_mthd_head }, - {} - } -}; - -int -gk104_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gf119_disp_core_func, &gk104_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c deleted file mode 100644 index 1b435beef3bf..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregp102.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static int -gp102_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x611494, chan->push); - nvkm_wr32(device, 0x611498, 0x00010000); - nvkm_wr32(device, 0x61149c, 0x00000001); - nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610490, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610490)); - return -EBUSY; - } - - return 0; -} - -static const struct nv50_disp_chan_func -gp102_disp_core_func = { - .init = gp102_disp_core_init, - .fini = gf119_disp_core_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; - -int -gp102_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gp102_disp_core_func, &gk104_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c deleted file mode 100644 index 1d333c484a49..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/coregv100.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0200, 0x680200 }, - { 0x0208, 0x680208 }, - { 0x020c, 0x68020c }, - { 0x0210, 0x680210 }, - { 0x0214, 0x680214 }, - { 0x0218, 0x680218 }, - { 0x021c, 0x68021c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_sor = { - .mthd = 0x0020, - .addr = 0x000020, - .data = { - { 0x0300, 0x680300 }, - { 0x0304, 0x680304 }, - { 0x0308, 0x680308 }, - { 0x030c, 0x68030c }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_wndw = { - .mthd = 0x0080, - .addr = 0x000080, - .data = { - { 0x1000, 0x681000 }, - { 0x1004, 0x681004 }, - { 0x1008, 0x681008 }, - { 0x100c, 0x68100c }, - { 0x1010, 0x681010 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -gv100_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000400, - .data = { - { 0x2000, 0x682000 }, - { 0x2004, 0x682004 }, - { 0x2008, 0x682008 }, - { 0x200c, 0x68200c }, - { 0x2014, 0x682014 }, - { 0x2018, 0x682018 }, - { 0x201c, 0x68201c }, - { 0x2020, 0x682020 }, - { 0x2028, 0x682028 }, - { 0x202c, 0x68202c }, - { 0x2030, 0x682030 }, - { 0x2038, 0x682038 }, - { 0x203c, 0x68203c }, - { 0x2048, 0x682048 }, - { 0x204c, 0x68204c }, - { 0x2050, 0x682050 }, - { 0x2054, 0x682054 }, - { 0x2058, 0x682058 }, - { 0x205c, 0x68205c }, - { 0x2060, 0x682060 }, - { 0x2064, 0x682064 }, - { 0x2068, 0x682068 }, - { 0x206c, 0x68206c }, - { 0x2070, 0x682070 }, - { 0x2074, 0x682074 }, - { 0x2078, 0x682078 }, - { 0x207c, 0x68207c }, - { 0x2080, 0x682080 }, - { 0x2088, 0x682088 }, - { 0x2090, 0x682090 }, - { 0x209c, 0x68209c }, - { 0x20a0, 0x6820a0 }, - { 0x20a4, 0x6820a4 }, - { 0x20a8, 0x6820a8 }, - { 0x20ac, 0x6820ac }, - { 0x2180, 0x682180 }, - { 0x2184, 0x682184 }, - { 0x218c, 0x68218c }, - { 0x2194, 0x682194 }, - { 0x2198, 0x682198 }, - { 0x219c, 0x68219c }, - { 0x21a0, 0x6821a0 }, - { 0x21a4, 0x6821a4 }, - { 0x2214, 0x682214 }, - { 0x2218, 0x682218 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gv100_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x008000, - .data = { - { "Global", 1, &gv100_disp_core_mthd_base }, - { "SOR", 4, &gv100_disp_core_mthd_sor }, - { "WINDOW", 8, &gv100_disp_core_mthd_wndw }, - { "HEAD", 4, &gv100_disp_core_mthd_head }, - {} - } -}; - -static int -gv100_disp_core_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610630); - if ((stat & 0x001f0000) == 0x000b0000) - return 0; - ); - return -EBUSY; -} - -static u64 -gv100_disp_core_user(struct nv50_disp_chan *chan, u64 *psize) -{ - *psize = 0x10000; - return 0x680000; -} - -static void -gv100_disp_core_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00000001; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611dac, mask, data); -} - -static void -gv100_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000000); - gv100_disp_core_idle(chan); - nvkm_mask(device, 0x6104e0, 0x00000002, 0x00000000); - chan->suspend_put = nvkm_rd32(device, 0x680000); -} - -static int -gv100_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - nvkm_wr32(device, 0x610b24, lower_32_bits(chan->push)); - nvkm_wr32(device, 0x610b20, upper_32_bits(chan->push)); - nvkm_wr32(device, 0x610b28, 0x00000001); - nvkm_wr32(device, 0x610b2c, 0x00000040); - - nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x680000, chan->suspend_put); - nvkm_wr32(device, 0x6104e0, 0x00000013); - return gv100_disp_core_idle(chan); -} - -static const struct nv50_disp_chan_func -gv100_disp_core = { - .init = gv100_disp_core_init, - .fini = gv100_disp_core_fini, - .intr = gv100_disp_core_intr, - .user = gv100_disp_core_user, - .bind = gv100_disp_dmac_bind, -}; - -int -gv100_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&gv100_disp_core, &gv100_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c deleted file mode 100644 index 660310b27f9c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/corenv50.c +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/client.h> -#include <subdev/timer.h> - -#include <nvif/cl507d.h> -#include <nvif/unpack.h> - -int -nv50_disp_core_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_core_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - u64 push; - int ret = -ENOSYS; - - nvif_ioctl(parent, "create disp core channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp core channel dma vers %d " - "pushbuf %016llx\n", - args->v0.version, args->v0.pushbuf); - push = args->v0.pushbuf; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid, 0, - push, oclass, pobject); -} - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x610bb8 }, - { 0x0088, 0x610b9c }, - { 0x008c, 0x000000 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -nv50_disp_core_mthd_dac = { - .mthd = 0x0080, - .addr = 0x000008, - .data = { - { 0x0400, 0x610b58 }, - { 0x0404, 0x610bdc }, - { 0x0420, 0x610828 }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_sor = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0600, 0x610b70 }, - {} - } -}; - -const struct nv50_disp_mthd_list -nv50_disp_core_mthd_pior = { - .mthd = 0x0040, - .addr = 0x000008, - .data = { - { 0x0700, 0x610b80 }, - {} - } -}; - -static const struct nv50_disp_mthd_list -nv50_disp_core_mthd_head = { - .mthd = 0x0400, - .addr = 0x000540, - .data = { - { 0x0800, 0x610ad8 }, - { 0x0804, 0x610ad0 }, - { 0x0808, 0x610a48 }, - { 0x080c, 0x610a78 }, - { 0x0810, 0x610ac0 }, - { 0x0814, 0x610af8 }, - { 0x0818, 0x610b00 }, - { 0x081c, 0x610ae8 }, - { 0x0820, 0x610af0 }, - { 0x0824, 0x610b08 }, - { 0x0828, 0x610b10 }, - { 0x082c, 0x610a68 }, - { 0x0830, 0x610a60 }, - { 0x0834, 0x000000 }, - { 0x0838, 0x610a40 }, - { 0x0840, 0x610a24 }, - { 0x0844, 0x610a2c }, - { 0x0848, 0x610aa8 }, - { 0x084c, 0x610ab0 }, - { 0x0860, 0x610a84 }, - { 0x0864, 0x610a90 }, - { 0x0868, 0x610b18 }, - { 0x086c, 0x610b20 }, - { 0x0870, 0x610ac8 }, - { 0x0874, 0x610a38 }, - { 0x0880, 0x610a58 }, - { 0x0884, 0x610a9c }, - { 0x08a0, 0x610a70 }, - { 0x08a4, 0x610a50 }, - { 0x08a8, 0x610ae0 }, - { 0x08c0, 0x610b28 }, - { 0x08c4, 0x610b30 }, - { 0x08c8, 0x610b40 }, - { 0x08d4, 0x610b38 }, - { 0x08d8, 0x610b48 }, - { 0x08dc, 0x610b50 }, - { 0x0900, 0x610a18 }, - { 0x0904, 0x610ab8 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_core_mthd = { - .name = "Core", - .addr = 0x000000, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_core_mthd_base }, - { "DAC", 3, &nv50_disp_core_mthd_dac }, - { "SOR", 2, &nv50_disp_core_mthd_sor }, - { "PIOR", 3, &nv50_disp_core_mthd_pior }, - { "HEAD", 2, &nv50_disp_core_mthd_head }, - {} - } -}; - -static void -nv50_disp_core_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* deactivate channel */ - nvkm_mask(device, 0x610200, 0x00000010, 0x00000000); - nvkm_mask(device, 0x610200, 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "core fini: %08x\n", - nvkm_rd32(device, 0x610200)); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000); -} - -static int -nv50_disp_core_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - - /* attempt to unstick channel from some unknown state */ - if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000) - nvkm_mask(device, 0x610200, 0x00800000, 0x00800000); - if ((nvkm_rd32(device, 0x610200) & 0x003f0000) == 0x00030000) - nvkm_mask(device, 0x610200, 0x00600000, 0x00600000); - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610204, chan->push); - nvkm_wr32(device, 0x610208, 0x00010000); - nvkm_wr32(device, 0x61020c, 0x00000000); - nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000, chan->suspend_put); - nvkm_wr32(device, 0x610200, 0x01000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "core init: %08x\n", - nvkm_rd32(device, 0x610200)); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_core_func = { - .init = nv50_disp_core_init, - .fini = nv50_disp_core_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = nv50_disp_dmac_bind, -}; - -int -nv50_disp_core_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_core_new_(&nv50_disp_core_func, &nv50_disp_core_mthd, - disp, 0, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c deleted file mode 100644 index cdda3658dcb3..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgf119.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gf119_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gf119_disp_pioc_func, disp, 13, 13, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c deleted file mode 100644 index 1a4601f975e6..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gf119_disp_pioc_func, disp, 13, 17, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c deleted file mode 100644 index a3e4f6900245..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursgv100.c +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static int -gv100_disp_curs_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 soff = (chan->chid.ctrl - 1) * 0x04; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610664 + soff); - if ((stat & 0x00070000) == 0x00040000) - return 0; - ); - return -EBUSY; -} - -static void -gv100_disp_curs_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00010000 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611dac, mask, data); -} - -static void -gv100_disp_curs_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 hoff = chan->chid.ctrl * 4; - nvkm_mask(device, 0x6104e0 + hoff, 0x00000010, 0x00000010); - gv100_disp_curs_idle(chan); - nvkm_mask(device, 0x6104e0 + hoff, 0x00000001, 0x00000000); -} - -static int -gv100_disp_curs_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - nvkm_wr32(device, 0x6104e0 + chan->chid.ctrl * 4, 0x00000001); - return gv100_disp_curs_idle(chan); -} - -static const struct nv50_disp_chan_func -gv100_disp_curs = { - .init = gv100_disp_curs_init, - .fini = gv100_disp_curs_fini, - .intr = gv100_disp_curs_intr, - .user = gv100_disp_chan_user, -}; - -int -gv100_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&gv100_disp_curs, disp, 73, 73, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c deleted file mode 100644 index d29758504a5f..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/cursnv50.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507a.h> -#include <nvif/unpack.h> - -int -nv50_disp_curs_new_(const struct nv50_disp_chan_func *func, - struct nv50_disp *disp, int ctrl, int user, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_cursor_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - - nvif_ioctl(parent, "create disp cursor size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp cursor vers %d head %d\n", - args->v0.version, args->v0.head); - if (!nvkm_head_find(&disp->base, args->v0.head)) - return -EINVAL; - head = args->v0.head; - } else - return ret; - - return nv50_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, - head, oclass, pobject); -} - -int -nv50_disp_curs_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_curs_new_(&nv50_disp_pioc_func, disp, 7, 7, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c deleted file mode 100644 index 71a94777ea2e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacgf119.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -static void -gf119_dac_clock(struct nvkm_ior *dac) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - nvkm_mask(device, 0x612280 + doff, 0x07070707, 0x00000000); -} - -static void -gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x640180 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = CRT; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x0000000f; -} - -static const struct nvkm_ior_func -gf119_dac = { - .state = gf119_dac_state, - .power = nv50_dac_power, - .sense = nv50_dac_sense, - .clock = gf119_dac_clock, -}; - -int -gf119_dac_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gf119_dac, disp, DAC, id); -} - -int -gf119_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x612004) & 0x000000f0) >> 4; - return 4; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c deleted file mode 100644 index 558012db35f8..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dacnv50.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -static void -nv50_dac_clock(struct nvkm_ior *dac) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - nvkm_mask(device, 0x614280 + doff, 0x07070707, 0x00000000); -} - -int -nv50_dac_sense(struct nvkm_ior *dac, u32 loadval) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - - dac->func->power(dac, false, true, false, false, false); - - nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); - mdelay(9); - udelay(500); - loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); - - dac->func->power(dac, false, false, false, false, false); - if (!(loadval & 0x80000000)) - return -ETIMEDOUT; - - return (loadval & 0x38000000) >> 27; -} - -static void -nv50_dac_power_wait(struct nvkm_device *device, const u32 doff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) - break; - ); -} - -void -nv50_dac_power(struct nvkm_ior *dac, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 doff = nv50_ior_base(dac); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000040 * ! pu | - 0x00000010 * ! data | - 0x00000004 * ! vsync | - 0x00000001 * ! hsync) << shift; - const u32 field = 0xc0000000 | (0x00000055 << shift); - - nv50_dac_power_wait(device, doff); - nvkm_mask(device, 0x61a004 + doff, field, state); - nv50_dac_power_wait(device, doff); -} - -static void -nv50_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = dac->disp->engine.subdev.device; - const u32 coff = dac->id * 8 + (state == &dac->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b58 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = CRT; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; -} - -static const struct nvkm_ior_func -nv50_dac = { - .state = nv50_dac_state, - .power = nv50_dac_power, - .sense = nv50_dac_sense, - .clock = nv50_dac_clock, -}; - -int -nv50_dac_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_dac, disp, DAC, id); -} - -int -nv50_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x00700000) >> 20; - return 3; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c deleted file mode 100644 index 76425e8586da..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgf119.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/ramht.h> -#include <subdev/timer.h> - -int -gf119_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -9, handle, - chan->chid.user << 27 | 0x00000001); -} - -void -gf119_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* deactivate channel */ - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); -} - -static int -gf119_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_dmac_func = { - .init = gf119_disp_dmac_init, - .fini = gf119_disp_dmac_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c deleted file mode 100644 index da258df268d7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgp102.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -#include <subdev/timer.h> - -static int -gp102_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001); - nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gp102_disp_dmac_func = { - .init = gp102_disp_dmac_init, - .fini = gf119_disp_dmac_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = gf119_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c deleted file mode 100644 index fdb624ac6b87..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacgv100.c +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "channv50.h" - -#include <core/ramht.h> -#include <subdev/timer.h> - -static int -gv100_disp_dmac_idle(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 soff = (chan->chid.ctrl - 1) * 0x04; - nvkm_msec(device, 2000, - u32 stat = nvkm_rd32(device, 0x610664 + soff); - if ((stat & 0x000f0000) == 0x00040000) - return 0; - ); - return -EBUSY; -} - -int -gv100_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -9, handle, - chan->chid.user << 25 | 0x00000040); -} - -void -gv100_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; - const u32 coff = chan->chid.ctrl * 0x04; - nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000000); - gv100_disp_dmac_idle(chan); - nvkm_mask(device, 0x6104e0 + coff, 0x00000002, 0x00000000); - chan->suspend_put = nvkm_rd32(device, 0x690000 + uoff); -} - -int -gv100_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; - const u32 poff = chan->chid.ctrl * 0x10; - const u32 coff = chan->chid.ctrl * 0x04; - - nvkm_wr32(device, 0x610b24 + poff, lower_32_bits(chan->push)); - nvkm_wr32(device, 0x610b20 + poff, upper_32_bits(chan->push)); - nvkm_wr32(device, 0x610b28 + poff, 0x00000001); - nvkm_wr32(device, 0x610b2c + poff, 0x00000040); - - nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000010); - nvkm_wr32(device, 0x690000 + uoff, chan->suspend_put); - nvkm_wr32(device, 0x6104e0 + coff, 0x00000013); - return gv100_disp_dmac_idle(chan); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c deleted file mode 100644 index d0a7da96d62b..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dmacnv50.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -#include <core/client.h> -#include <core/ramht.h> -#include <subdev/fb.h> -#include <subdev/mmu.h> -#include <subdev/timer.h> -#include <engine/dma.h> - -int -nv50_disp_dmac_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, int head, u64 push, - const struct nvkm_oclass *oclass, - struct nvkm_object **pobject) -{ - struct nvkm_client *client = oclass->client; - struct nv50_disp_chan *chan; - int ret; - - ret = nv50_disp_chan_new_(func, mthd, disp, chid, chid, head, oclass, - pobject); - chan = nv50_disp_chan(*pobject); - if (ret) - return ret; - - chan->memory = nvkm_umem_search(client, push); - if (IS_ERR(chan->memory)) - return PTR_ERR(chan->memory); - - if (nvkm_memory_size(chan->memory) < 0x1000) - return -EINVAL; - - switch (nvkm_memory_target(chan->memory)) { - case NVKM_MEM_TARGET_VRAM: chan->push = 0x00000001; break; - case NVKM_MEM_TARGET_NCOH: chan->push = 0x00000002; break; - case NVKM_MEM_TARGET_HOST: chan->push = 0x00000003; break; - default: - return -EINVAL; - } - - chan->push |= nvkm_memory_addr(chan->memory) >> 8; - return 0; -} - -int -nv50_disp_dmac_bind(struct nv50_disp_chan *chan, - struct nvkm_object *object, u32 handle) -{ - return nvkm_ramht_insert(chan->disp->ramht, object, - chan->chid.user, -10, handle, - chan->chid.user << 28 | - chan->chid.user); -} - -static void -nv50_disp_dmac_fini(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* deactivate channel */ - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000); - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini timeout, %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - } - - chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); -} - -static int -nv50_disp_dmac_init(struct nv50_disp_chan *chan) -{ - struct nvkm_subdev *subdev = &chan->disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* initialise channel for dma command submission */ - nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push); - nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000); - nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl); - nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010); - nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); - nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013); - - /* wait for it to go inactive */ - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init timeout, %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_dmac_func = { - .init = nv50_disp_dmac_init, - .fini = nv50_disp_dmac_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, - .bind = nv50_disp_dmac_bind, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c index 8e09315b8fb3..c1b3206f27e6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.c @@ -40,7 +40,7 @@ #define AMPERE_IED_HACK(disp) ((disp)->engine.subdev.device->card_type >= GA100) struct lt_state { - struct nvkm_dp *dp; + struct nvkm_outp *outp; int repeaters; int repeater; @@ -55,7 +55,7 @@ struct lt_state { static int nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) { - struct nvkm_dp *dp = lt->dp; + struct nvkm_outp *outp = lt->outp; u32 addr; int ret; @@ -66,7 +66,7 @@ nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) else addr = DPCD_LS02; - ret = nvkm_rdaux(dp->aux, addr, <->stat[0], 3); + ret = nvkm_rdaux(outp->dp.aux, addr, <->stat[0], 3); if (ret) return ret; @@ -75,18 +75,18 @@ nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) else addr = DPCD_LS06; - ret = nvkm_rdaux(dp->aux, addr, <->stat[4], 2); + ret = nvkm_rdaux(outp->dp.aux, addr, <->stat[4], 2); if (ret) return ret; if (pc) { - ret = nvkm_rdaux(dp->aux, DPCD_LS0C, <->pc2stat, 1); + ret = nvkm_rdaux(outp->dp.aux, DPCD_LS0C, <->pc2stat, 1); if (ret) lt->pc2stat = 0x00; - OUTP_TRACE(&dp->outp, "status %6ph pc2 %02x", - lt->stat, lt->pc2stat); + + OUTP_TRACE(outp, "status %6ph pc2 %02x", lt->stat, lt->pc2stat); } else { - OUTP_TRACE(&dp->outp, "status %6ph", lt->stat); + OUTP_TRACE(outp, "status %6ph", lt->stat); } return 0; @@ -95,8 +95,8 @@ nvkm_dp_train_sense(struct lt_state *lt, bool pc, u32 delay) static int nvkm_dp_train_drive(struct lt_state *lt, bool pc) { - struct nvkm_dp *dp = lt->dp; - struct nvkm_ior *ior = dp->outp.ior; + struct nvkm_outp *outp = lt->outp; + struct nvkm_ior *ior = outp->ior; struct nvkm_bios *bios = ior->disp->engine.subdev.device->bios; struct nvbios_dpout info; struct nvbios_dpcfg ocfg; @@ -127,26 +127,22 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) lt->conf[i] = (lpre << 3) | lvsw; lt->pc2conf[i >> 1] |= lpc2 << ((i & 1) * 4); - OUTP_TRACE(&dp->outp, "config lane %d %02x %02x", - i, lt->conf[i], lpc2); + OUTP_TRACE(outp, "config lane %d %02x %02x", i, lt->conf[i], lpc2); if (lt->repeater != lt->repeaters) continue; - data = nvbios_dpout_match(bios, dp->outp.info.hasht, - dp->outp.info.hashm, + data = nvbios_dpout_match(bios, outp->info.hasht, outp->info.hashm, &ver, &hdr, &cnt, &len, &info); if (!data) continue; - data = nvbios_dpcfg_match(bios, data, lpc2 & 3, lvsw & 3, - lpre & 3, &ver, &hdr, &cnt, &len, - &ocfg); + data = nvbios_dpcfg_match(bios, data, lpc2 & 3, lvsw & 3, lpre & 3, + &ver, &hdr, &cnt, &len, &ocfg); if (!data) continue; - ior->func->dp.drive(ior, i, ocfg.pc, ocfg.dc, - ocfg.pe, ocfg.tx_pu); + ior->func->dp->drive(ior, i, ocfg.pc, ocfg.dc, ocfg.pe, ocfg.tx_pu); } if (lt->repeater) @@ -154,12 +150,12 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) else addr = DPCD_LC03(0); - ret = nvkm_wraux(dp->aux, addr, lt->conf, 4); + ret = nvkm_wraux(outp->dp.aux, addr, lt->conf, 4); if (ret) return ret; if (pc) { - ret = nvkm_wraux(dp->aux, DPCD_LC0F, lt->pc2conf, 2); + ret = nvkm_wraux(outp->dp.aux, DPCD_LC0F, lt->pc2conf, 2); if (ret) return ret; } @@ -170,19 +166,19 @@ nvkm_dp_train_drive(struct lt_state *lt, bool pc) static void nvkm_dp_train_pattern(struct lt_state *lt, u8 pattern) { - struct nvkm_dp *dp = lt->dp; + struct nvkm_outp *outp = lt->outp; u32 addr; u8 sink_tp; - OUTP_TRACE(&dp->outp, "training pattern %d", pattern); - dp->outp.ior->func->dp.pattern(dp->outp.ior, pattern); + OUTP_TRACE(outp, "training pattern %d", pattern); + outp->ior->func->dp->pattern(outp->ior, pattern); if (lt->repeater) addr = DPCD_LTTPR_PATTERN_SET(lt->repeater); else addr = DPCD_LC02; - nvkm_rdaux(dp->aux, addr, &sink_tp, 1); + nvkm_rdaux(outp->dp.aux, addr, &sink_tp, 1); sink_tp &= ~DPCD_LC02_TRAINING_PATTERN_SET; sink_tp |= (pattern != 4) ? pattern : 7; @@ -190,13 +186,13 @@ nvkm_dp_train_pattern(struct lt_state *lt, u8 pattern) sink_tp |= DPCD_LC02_SCRAMBLING_DISABLE; else sink_tp &= ~DPCD_LC02_SCRAMBLING_DISABLE; - nvkm_wraux(dp->aux, addr, &sink_tp, 1); + nvkm_wraux(outp->dp.aux, addr, &sink_tp, 1); } static int nvkm_dp_train_eq(struct lt_state *lt) { - struct nvkm_i2c_aux *aux = lt->dp->aux; + struct nvkm_i2c_aux *aux = lt->outp->dp.aux; bool eq_done = false, cr_done = true; int tries = 0, usec = 0, i; u8 data; @@ -207,17 +203,17 @@ nvkm_dp_train_eq(struct lt_state *lt) nvkm_dp_train_pattern(lt, 4); } else { - if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] >= 0x14 && - lt->dp->dpcd[DPCD_RC03] & DPCD_RC03_TPS4_SUPPORTED) + if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] >= 0x14 && + lt->outp->dp.dpcd[DPCD_RC03] & DPCD_RC03_TPS4_SUPPORTED) nvkm_dp_train_pattern(lt, 4); else - if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] >= 0x12 && - lt->dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED) + if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] >= 0x12 && + lt->outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED) nvkm_dp_train_pattern(lt, 3); else nvkm_dp_train_pattern(lt, 2); - usec = (lt->dp->dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; + usec = (lt->outp->dp.dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; } do { @@ -227,7 +223,7 @@ nvkm_dp_train_eq(struct lt_state *lt) break; eq_done = !!(lt->stat[2] & DPCD_LS04_INTERLANE_ALIGN_DONE); - for (i = 0; i < lt->dp->outp.ior->dp.nr && eq_done; i++) { + for (i = 0; i < lt->outp->ior->dp.nr && eq_done; i++) { u8 lane = (lt->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; if (!(lane & DPCD_LS02_LANE0_CR_DONE)) cr_done = false; @@ -249,8 +245,8 @@ nvkm_dp_train_cr(struct lt_state *lt) nvkm_dp_train_pattern(lt, 1); - if (lt->dp->dpcd[DPCD_RC00_DPCD_REV] < 0x14 && !lt->repeater) - usec = (lt->dp->dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; + if (lt->outp->dp.dpcd[DPCD_RC00_DPCD_REV] < 0x14 && !lt->repeater) + usec = (lt->outp->dp.dpcd[DPCD_RC0E] & DPCD_RC0E_AUX_RD_INTERVAL) * 4000; do { if (nvkm_dp_train_drive(lt, false) || @@ -258,7 +254,7 @@ nvkm_dp_train_cr(struct lt_state *lt) break; cr_done = true; - for (i = 0; i < lt->dp->outp.ior->dp.nr; i++) { + for (i = 0; i < lt->outp->ior->dp.nr; i++) { u8 lane = (lt->stat[i >> 1] >> ((i & 1) * 4)) & 0xf; if (!(lane & DPCD_LS02_LANE0_CR_DONE)) { cr_done = false; @@ -278,45 +274,44 @@ nvkm_dp_train_cr(struct lt_state *lt) } static int -nvkm_dp_train_links(struct nvkm_dp *dp, int rate) +nvkm_dp_train_links(struct nvkm_outp *outp, int rate) { - struct nvkm_ior *ior = dp->outp.ior; - struct nvkm_disp *disp = dp->outp.disp; + struct nvkm_ior *ior = outp->ior; + struct nvkm_disp *disp = outp->disp; struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_bios *bios = subdev->device->bios; struct lt_state lt = { - .dp = dp, + .outp = outp, }; u32 lnkcmp; u8 sink[2], data; int ret; - OUTP_DBG(&dp->outp, "training %d x %d MB/s", - ior->dp.nr, ior->dp.bw * 27); + OUTP_DBG(outp, "training %d x %d MB/s", ior->dp.nr, ior->dp.bw * 27); /* Intersect misc. capabilities of the OR and sink. */ if (disp->engine.subdev.device->chipset < 0x110) - dp->dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED; + outp->dp.dpcd[DPCD_RC03] &= ~DPCD_RC03_TPS4_SUPPORTED; if (disp->engine.subdev.device->chipset < 0xd0) - dp->dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED; - lt.pc2 = dp->dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED; + outp->dp.dpcd[DPCD_RC02] &= ~DPCD_RC02_TPS3_SUPPORTED; + lt.pc2 = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_TPS3_SUPPORTED; - if (AMPERE_IED_HACK(disp) && (lnkcmp = lt.dp->info.script[0])) { + if (AMPERE_IED_HACK(disp) && (lnkcmp = lt.outp->dp.info.script[0])) { /* Execute BeforeLinkTraining script from DP Info table. */ while (ior->dp.bw < nvbios_rd08(bios, lnkcmp)) lnkcmp += 3; lnkcmp = nvbios_rd16(bios, lnkcmp + 1); - nvbios_init(&dp->outp.disp->engine.subdev, lnkcmp, - init.outp = &dp->outp.info; + nvbios_init(&outp->disp->engine.subdev, lnkcmp, + init.outp = &outp->info; init.or = ior->id; init.link = ior->asy.link; ); } /* Set desired link configuration on the source. */ - if ((lnkcmp = lt.dp->info.lnkcmp)) { - if (dp->version < 0x30) { + if ((lnkcmp = lt.outp->dp.info.lnkcmp)) { + if (outp->dp.version < 0x30) { while ((ior->dp.bw * 2700) < nvbios_rd16(bios, lnkcmp)) lnkcmp += 4; lnkcmp = nvbios_rd16(bios, lnkcmp + 2); @@ -327,56 +322,56 @@ nvkm_dp_train_links(struct nvkm_dp *dp, int rate) } nvbios_init(subdev, lnkcmp, - init.outp = &dp->outp.info; + init.outp = &outp->info; init.or = ior->id; init.link = ior->asy.link; ); } - ret = ior->func->dp.links(ior, dp->aux); + ret = ior->func->dp->links(ior, outp->dp.aux); if (ret) { if (ret < 0) { - OUTP_ERR(&dp->outp, "train failed with %d", ret); + OUTP_ERR(outp, "train failed with %d", ret); return ret; } return 0; } - ior->func->dp.power(ior, ior->dp.nr); + ior->func->dp->power(ior, ior->dp.nr); /* Select LTTPR non-transparent mode if we have a valid configuration, * use transparent mode otherwise. */ - if (dp->lttpr[0] >= 0x14) { + if (outp->dp.lttpr[0] >= 0x14) { data = DPCD_LTTPR_MODE_TRANSPARENT; - nvkm_wraux(dp->aux, DPCD_LTTPR_MODE, &data, sizeof(data)); + nvkm_wraux(outp->dp.aux, DPCD_LTTPR_MODE, &data, sizeof(data)); - if (dp->lttprs) { + if (outp->dp.lttprs) { data = DPCD_LTTPR_MODE_NON_TRANSPARENT; - nvkm_wraux(dp->aux, DPCD_LTTPR_MODE, &data, sizeof(data)); - lt.repeaters = dp->lttprs; + nvkm_wraux(outp->dp.aux, DPCD_LTTPR_MODE, &data, sizeof(data)); + lt.repeaters = outp->dp.lttprs; } } /* Set desired link configuration on the sink. */ - sink[0] = (dp->rate[rate].dpcd < 0) ? ior->dp.bw : 0; + sink[0] = (outp->dp.rate[rate].dpcd < 0) ? ior->dp.bw : 0; sink[1] = ior->dp.nr; if (ior->dp.ef) sink[1] |= DPCD_LC01_ENHANCED_FRAME_EN; - ret = nvkm_wraux(dp->aux, DPCD_LC00_LINK_BW_SET, sink, 2); + ret = nvkm_wraux(outp->dp.aux, DPCD_LC00_LINK_BW_SET, sink, 2); if (ret) return ret; - if (dp->rate[rate].dpcd >= 0) { - ret = nvkm_rdaux(dp->aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); + if (outp->dp.rate[rate].dpcd >= 0) { + ret = nvkm_rdaux(outp->dp.aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); if (ret) return ret; sink[0] &= ~DPCD_LC15_LINK_RATE_SET_MASK; - sink[0] |= dp->rate[rate].dpcd; + sink[0] |= outp->dp.rate[rate].dpcd; - ret = nvkm_wraux(dp->aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); + ret = nvkm_wraux(outp->dp.aux, DPCD_LC15_LINK_RATE_SET, &sink[0], sizeof(sink[0])); if (ret) return ret; } @@ -384,9 +379,9 @@ nvkm_dp_train_links(struct nvkm_dp *dp, int rate) /* Attempt to train the link in this configuration. */ for (lt.repeater = lt.repeaters; lt.repeater >= 0; lt.repeater--) { if (lt.repeater) - OUTP_DBG(&dp->outp, "training LTTPR%d", lt.repeater); + OUTP_DBG(outp, "training LTTPR%d", lt.repeater); else - OUTP_DBG(&dp->outp, "training sink"); + OUTP_DBG(outp, "training sink"); memset(lt.stat, 0x00, sizeof(lt.stat)); ret = nvkm_dp_train_cr(<); @@ -399,94 +394,92 @@ nvkm_dp_train_links(struct nvkm_dp *dp, int rate) } static void -nvkm_dp_train_fini(struct nvkm_dp *dp) +nvkm_dp_train_fini(struct nvkm_outp *outp) { /* Execute AfterLinkTraining script from DP Info table. */ - nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[1], - init.outp = &dp->outp.info; - init.or = dp->outp.ior->id; - init.link = dp->outp.ior->asy.link; + nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[1], + init.outp = &outp->info; + init.or = outp->ior->id; + init.link = outp->ior->asy.link; ); } static void -nvkm_dp_train_init(struct nvkm_dp *dp) +nvkm_dp_train_init(struct nvkm_outp *outp) { /* Execute EnableSpread/DisableSpread script from DP Info table. */ - if (dp->dpcd[DPCD_RC03] & DPCD_RC03_MAX_DOWNSPREAD) { - nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[2], - init.outp = &dp->outp.info; - init.or = dp->outp.ior->id; - init.link = dp->outp.ior->asy.link; + if (outp->dp.dpcd[DPCD_RC03] & DPCD_RC03_MAX_DOWNSPREAD) { + nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[2], + init.outp = &outp->info; + init.or = outp->ior->id; + init.link = outp->ior->asy.link; ); } else { - nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[3], - init.outp = &dp->outp.info; - init.or = dp->outp.ior->id; - init.link = dp->outp.ior->asy.link; + nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[3], + init.outp = &outp->info; + init.or = outp->ior->id; + init.link = outp->ior->asy.link; ); } - if (!AMPERE_IED_HACK(dp->outp.disp)) { + if (!AMPERE_IED_HACK(outp->disp)) { /* Execute BeforeLinkTraining script from DP Info table. */ - nvbios_init(&dp->outp.disp->engine.subdev, dp->info.script[0], - init.outp = &dp->outp.info; - init.or = dp->outp.ior->id; - init.link = dp->outp.ior->asy.link; + nvbios_init(&outp->disp->engine.subdev, outp->dp.info.script[0], + init.outp = &outp->info; + init.or = outp->ior->id; + init.link = outp->ior->asy.link; ); } } static int -nvkm_dp_train(struct nvkm_dp *dp, u32 dataKBps) +nvkm_dp_train(struct nvkm_outp *outp, u32 dataKBps) { - struct nvkm_ior *ior = dp->outp.ior; + struct nvkm_ior *ior = outp->ior; int ret = -EINVAL, nr, rate; u8 pwr; /* Ensure sink is not in a low-power state. */ - if (!nvkm_rdaux(dp->aux, DPCD_SC00, &pwr, 1)) { + if (!nvkm_rdaux(outp->dp.aux, DPCD_SC00, &pwr, 1)) { if ((pwr & DPCD_SC00_SET_POWER) != DPCD_SC00_SET_POWER_D0) { pwr &= ~DPCD_SC00_SET_POWER; pwr |= DPCD_SC00_SET_POWER_D0; - nvkm_wraux(dp->aux, DPCD_SC00, &pwr, 1); + nvkm_wraux(outp->dp.aux, DPCD_SC00, &pwr, 1); } } - ior->dp.mst = dp->lt.mst; - ior->dp.ef = dp->dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP; + ior->dp.mst = outp->dp.lt.mst; + ior->dp.ef = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_ENHANCED_FRAME_CAP; ior->dp.nr = 0; /* Link training. */ - OUTP_DBG(&dp->outp, "training"); - nvkm_dp_train_init(dp); - for (nr = dp->links; ret < 0 && nr; nr >>= 1) { - for (rate = 0; ret < 0 && rate < dp->rates; rate++) { - if (dp->rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) { + OUTP_DBG(outp, "training"); + nvkm_dp_train_init(outp); + for (nr = outp->dp.links; ret < 0 && nr; nr >>= 1) { + for (rate = 0; ret < 0 && rate < outp->dp.rates; rate++) { + if (outp->dp.rate[rate].rate * nr >= dataKBps || WARN_ON(!ior->dp.nr)) { /* Program selected link configuration. */ - ior->dp.bw = dp->rate[rate].rate / 27000; + ior->dp.bw = outp->dp.rate[rate].rate / 27000; ior->dp.nr = nr; - ret = nvkm_dp_train_links(dp, rate); + ret = nvkm_dp_train_links(outp, rate); } } } - nvkm_dp_train_fini(dp); + nvkm_dp_train_fini(outp); if (ret < 0) - OUTP_ERR(&dp->outp, "training failed"); + OUTP_ERR(outp, "training failed"); else - OUTP_DBG(&dp->outp, "training done"); - atomic_set(&dp->lt.done, 1); + OUTP_DBG(outp, "training done"); + atomic_set(&outp->dp.lt.done, 1); return ret; } void nvkm_dp_disable(struct nvkm_outp *outp, struct nvkm_ior *ior) { - struct nvkm_dp *dp = nvkm_dp(outp); - /* Execute DisableLT script from DP Info Table. */ - nvbios_init(&ior->disp->engine.subdev, dp->info.script[4], - init.outp = &dp->outp.info; + nvbios_init(&ior->disp->engine.subdev, outp->dp.info.script[4], + init.outp = &outp->info; init.or = ior->id; init.link = ior->arm.link; ); @@ -495,18 +488,15 @@ nvkm_dp_disable(struct nvkm_outp *outp, struct nvkm_ior *ior) static void nvkm_dp_release(struct nvkm_outp *outp) { - struct nvkm_dp *dp = nvkm_dp(outp); - /* Prevent link from being retrained if sink sends an IRQ. */ - atomic_set(&dp->lt.done, 0); - dp->outp.ior->dp.nr = 0; + atomic_set(&outp->dp.lt.done, 0); + outp->ior->dp.nr = 0; } static int nvkm_dp_acquire(struct nvkm_outp *outp) { - struct nvkm_dp *dp = nvkm_dp(outp); - struct nvkm_ior *ior = dp->outp.ior; + struct nvkm_ior *ior = outp->ior; struct nvkm_head *head; bool retrain = true; u32 datakbps = 0; @@ -515,10 +505,10 @@ nvkm_dp_acquire(struct nvkm_outp *outp) u8 stat[3]; int ret, i; - mutex_lock(&dp->mutex); + mutex_lock(&outp->dp.mutex); /* Check that link configuration meets current requirements. */ - list_for_each_entry(head, &outp->disp->head, head) { + list_for_each_entry(head, &outp->disp->heads, head) { if (ior->asy.head & (1 << head->id)) { u32 khz = (head->asy.hz >> ior->asy.rgdiv) / 1000; datakbps += khz * head->asy.or.depth; @@ -527,18 +517,17 @@ nvkm_dp_acquire(struct nvkm_outp *outp) linkKBps = ior->dp.bw * 27000 * ior->dp.nr; dataKBps = DIV_ROUND_UP(datakbps, 8); - OUTP_DBG(&dp->outp, "data %d KB/s link %d KB/s mst %d->%d", - dataKBps, linkKBps, ior->dp.mst, dp->lt.mst); - if (linkKBps < dataKBps || ior->dp.mst != dp->lt.mst) { - OUTP_DBG(&dp->outp, "link requirements changed"); + OUTP_DBG(outp, "data %d KB/s link %d KB/s mst %d->%d", + dataKBps, linkKBps, ior->dp.mst, outp->dp.lt.mst); + if (linkKBps < dataKBps || ior->dp.mst != outp->dp.lt.mst) { + OUTP_DBG(outp, "link requirements changed"); goto done; } /* Check that link is still trained. */ - ret = nvkm_rdaux(dp->aux, DPCD_LS02, stat, 3); + ret = nvkm_rdaux(outp->dp.aux, DPCD_LS02, stat, 3); if (ret) { - OUTP_DBG(&dp->outp, - "failed to read link status, assuming no sink"); + OUTP_DBG(outp, "failed to read link status, assuming no sink"); goto done; } @@ -548,125 +537,126 @@ nvkm_dp_acquire(struct nvkm_outp *outp) if (!(lane & DPCD_LS02_LANE0_CR_DONE) || !(lane & DPCD_LS02_LANE0_CHANNEL_EQ_DONE) || !(lane & DPCD_LS02_LANE0_SYMBOL_LOCKED)) { - OUTP_DBG(&dp->outp, - "lane %d not equalised", lane); + OUTP_DBG(outp, "lane %d not equalised", lane); goto done; } } retrain = false; } else { - OUTP_DBG(&dp->outp, "no inter-lane alignment"); + OUTP_DBG(outp, "no inter-lane alignment"); } done: - if (retrain || !atomic_read(&dp->lt.done)) - ret = nvkm_dp_train(dp, dataKBps); - mutex_unlock(&dp->mutex); + if (retrain || !atomic_read(&outp->dp.lt.done)) + ret = nvkm_dp_train(outp, dataKBps); + mutex_unlock(&outp->dp.mutex); return ret; } static bool -nvkm_dp_enable_supported_link_rates(struct nvkm_dp *dp) +nvkm_dp_enable_supported_link_rates(struct nvkm_outp *outp) { u8 sink_rates[DPCD_RC10_SUPPORTED_LINK_RATES__SIZE]; int i, j, k; - if (dp->outp.conn->info.type != DCB_CONNECTOR_eDP || - dp->dpcd[DPCD_RC00_DPCD_REV] < 0x13 || - nvkm_rdaux(dp->aux, DPCD_RC10_SUPPORTED_LINK_RATES(0), sink_rates, sizeof(sink_rates))) + if (outp->conn->info.type != DCB_CONNECTOR_eDP || + outp->dp.dpcd[DPCD_RC00_DPCD_REV] < 0x13 || + nvkm_rdaux(outp->dp.aux, DPCD_RC10_SUPPORTED_LINK_RATES(0), + sink_rates, sizeof(sink_rates))) return false; for (i = 0; i < ARRAY_SIZE(sink_rates); i += 2) { const u32 rate = ((sink_rates[i + 1] << 8) | sink_rates[i]) * 200 / 10; - if (!rate || WARN_ON(dp->rates == ARRAY_SIZE(dp->rate))) + if (!rate || WARN_ON(outp->dp.rates == ARRAY_SIZE(outp->dp.rate))) break; - if (rate > dp->outp.info.dpconf.link_bw * 27000) { - OUTP_DBG(&dp->outp, "rate %d !outp", rate); + if (rate > outp->info.dpconf.link_bw * 27000) { + OUTP_DBG(outp, "rate %d !outp", rate); continue; } - for (j = 0; j < dp->rates; j++) { - if (rate > dp->rate[j].rate) { - for (k = dp->rates; k > j; k--) - dp->rate[k] = dp->rate[k - 1]; + for (j = 0; j < outp->dp.rates; j++) { + if (rate > outp->dp.rate[j].rate) { + for (k = outp->dp.rates; k > j; k--) + outp->dp.rate[k] = outp->dp.rate[k - 1]; break; } } - dp->rate[j].dpcd = i / 2; - dp->rate[j].rate = rate; - dp->rates++; + outp->dp.rate[j].dpcd = i / 2; + outp->dp.rate[j].rate = rate; + outp->dp.rates++; } - for (i = 0; i < dp->rates; i++) - OUTP_DBG(&dp->outp, "link_rate[%d] = %d", dp->rate[i].dpcd, dp->rate[i].rate); + for (i = 0; i < outp->dp.rates; i++) + OUTP_DBG(outp, "link_rate[%d] = %d", outp->dp.rate[i].dpcd, outp->dp.rate[i].rate); - return dp->rates != 0; + return outp->dp.rates != 0; } static bool -nvkm_dp_enable(struct nvkm_dp *dp, bool enable) +nvkm_dp_enable(struct nvkm_outp *outp, bool enable) { - struct nvkm_i2c_aux *aux = dp->aux; + struct nvkm_i2c_aux *aux = outp->dp.aux; if (enable) { - if (!dp->present) { - OUTP_DBG(&dp->outp, "aux power -> always"); + if (!outp->dp.present) { + OUTP_DBG(outp, "aux power -> always"); nvkm_i2c_aux_monitor(aux, true); - dp->present = true; + outp->dp.present = true; } /* Detect any LTTPRs before reading DPCD receiver caps. */ - if (!nvkm_rdaux(aux, DPCD_LTTPR_REV, dp->lttpr, sizeof(dp->lttpr)) && - dp->lttpr[0] >= 0x14 && dp->lttpr[2]) { - switch (dp->lttpr[2]) { - case 0x80: dp->lttprs = 1; break; - case 0x40: dp->lttprs = 2; break; - case 0x20: dp->lttprs = 3; break; - case 0x10: dp->lttprs = 4; break; - case 0x08: dp->lttprs = 5; break; - case 0x04: dp->lttprs = 6; break; - case 0x02: dp->lttprs = 7; break; - case 0x01: dp->lttprs = 8; break; + if (!nvkm_rdaux(aux, DPCD_LTTPR_REV, outp->dp.lttpr, sizeof(outp->dp.lttpr)) && + outp->dp.lttpr[0] >= 0x14 && outp->dp.lttpr[2]) { + switch (outp->dp.lttpr[2]) { + case 0x80: outp->dp.lttprs = 1; break; + case 0x40: outp->dp.lttprs = 2; break; + case 0x20: outp->dp.lttprs = 3; break; + case 0x10: outp->dp.lttprs = 4; break; + case 0x08: outp->dp.lttprs = 5; break; + case 0x04: outp->dp.lttprs = 6; break; + case 0x02: outp->dp.lttprs = 7; break; + case 0x01: outp->dp.lttprs = 8; break; default: /* Unknown LTTPR count, we'll switch to transparent mode. */ WARN_ON(1); - dp->lttprs = 0; + outp->dp.lttprs = 0; break; } } else { /* No LTTPR support, or zero LTTPR count - don't touch it at all. */ - memset(dp->lttpr, 0x00, sizeof(dp->lttpr)); + memset(outp->dp.lttpr, 0x00, sizeof(outp->dp.lttpr)); } - if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, dp->dpcd, sizeof(dp->dpcd))) { + if (!nvkm_rdaux(aux, DPCD_RC00_DPCD_REV, outp->dp.dpcd, sizeof(outp->dp.dpcd))) { const u8 rates[] = { 0x1e, 0x14, 0x0a, 0x06, 0 }; const u8 *rate; int rate_max; - dp->rates = 0; - dp->links = dp->dpcd[DPCD_RC02] & DPCD_RC02_MAX_LANE_COUNT; - dp->links = min(dp->links, dp->outp.info.dpconf.link_nr); - if (dp->lttprs && dp->lttpr[4]) - dp->links = min_t(int, dp->links, dp->lttpr[4]); + outp->dp.rates = 0; + outp->dp.links = outp->dp.dpcd[DPCD_RC02] & DPCD_RC02_MAX_LANE_COUNT; + outp->dp.links = min(outp->dp.links, outp->info.dpconf.link_nr); + if (outp->dp.lttprs && outp->dp.lttpr[4]) + outp->dp.links = min_t(int, outp->dp.links, outp->dp.lttpr[4]); - rate_max = dp->dpcd[DPCD_RC01_MAX_LINK_RATE]; - rate_max = min(rate_max, dp->outp.info.dpconf.link_bw); - if (dp->lttprs && dp->lttpr[1]) - rate_max = min_t(int, rate_max, dp->lttpr[1]); + rate_max = outp->dp.dpcd[DPCD_RC01_MAX_LINK_RATE]; + rate_max = min(rate_max, outp->info.dpconf.link_bw); + if (outp->dp.lttprs && outp->dp.lttpr[1]) + rate_max = min_t(int, rate_max, outp->dp.lttpr[1]); - if (!nvkm_dp_enable_supported_link_rates(dp)) { + if (!nvkm_dp_enable_supported_link_rates(outp)) { for (rate = rates; *rate; rate++) { - if (*rate <= rate_max) { - if (WARN_ON(dp->rates == ARRAY_SIZE(dp->rate))) - break; - - dp->rate[dp->rates].dpcd = -1; - dp->rate[dp->rates].rate = *rate * 27000; - dp->rates++; - } + if (*rate > rate_max) + continue; + + if (WARN_ON(outp->dp.rates == ARRAY_SIZE(outp->dp.rate))) + break; + + outp->dp.rate[outp->dp.rates].dpcd = -1; + outp->dp.rate[outp->dp.rates].rate = *rate * 27000; + outp->dp.rates++; } } @@ -674,13 +664,13 @@ nvkm_dp_enable(struct nvkm_dp *dp, bool enable) } } - if (dp->present) { - OUTP_DBG(&dp->outp, "aux power -> demand"); + if (outp->dp.present) { + OUTP_DBG(outp, "aux power -> demand"); nvkm_i2c_aux_monitor(aux, false); - dp->present = false; + outp->dp.present = false; } - atomic_set(&dp->lt.done, 0); + atomic_set(&outp->dp.lt.done, 0); return false; } @@ -688,18 +678,18 @@ static int nvkm_dp_hpd(struct nvkm_notify *notify) { const struct nvkm_i2c_ntfy_rep *line = notify->data; - struct nvkm_dp *dp = container_of(notify, typeof(*dp), hpd); - struct nvkm_conn *conn = dp->outp.conn; - struct nvkm_disp *disp = dp->outp.disp; + struct nvkm_outp *outp = container_of(notify, typeof(*outp), dp.hpd); + struct nvkm_conn *conn = outp->conn; + struct nvkm_disp *disp = outp->disp; struct nvif_notify_conn_rep_v0 rep = {}; - OUTP_DBG(&dp->outp, "HPD: %d", line->mask); + OUTP_DBG(outp, "HPD: %d", line->mask); if (line->mask & NVKM_I2C_IRQ) { - if (atomic_read(&dp->lt.done)) - dp->outp.func->acquire(&dp->outp); + if (atomic_read(&outp->dp.lt.done)) + outp->func->acquire(outp); rep.mask |= NVIF_NOTIFY_CONN_V0_IRQ; } else { - nvkm_dp_enable(dp, true); + nvkm_dp_enable(outp, true); } if (line->mask & NVKM_I2C_UNPLUG) @@ -714,24 +704,22 @@ nvkm_dp_hpd(struct nvkm_notify *notify) static void nvkm_dp_fini(struct nvkm_outp *outp) { - struct nvkm_dp *dp = nvkm_dp(outp); - nvkm_notify_put(&dp->hpd); - nvkm_dp_enable(dp, false); + nvkm_notify_put(&outp->dp.hpd); + nvkm_dp_enable(outp, false); } static void nvkm_dp_init(struct nvkm_outp *outp) { struct nvkm_gpio *gpio = outp->disp->engine.subdev.device->gpio; - struct nvkm_dp *dp = nvkm_dp(outp); - nvkm_notify_put(&dp->outp.conn->hpd); + nvkm_notify_put(&outp->conn->hpd); /* eDP panels need powering on by us (if the VBIOS doesn't default it * to on) before doing any AUX channel transactions. LVDS panel power * is handled by the SOR itself, and not required for LVDS DDC. */ - if (dp->outp.conn->info.type == DCB_CONNECTOR_eDP) { + if (outp->conn->info.type == DCB_CONNECTOR_eDP) { int power = nvkm_gpio_get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); if (power == 0) nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); @@ -748,21 +736,20 @@ nvkm_dp_init(struct nvkm_outp *outp) /* If the eDP panel can't be detected, we need to restore * the panel power GPIO to avoid breaking another output. */ - if (!nvkm_dp_enable(dp, true) && power == 0) + if (!nvkm_dp_enable(outp, true) && power == 0) nvkm_gpio_set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 0); } else { - nvkm_dp_enable(dp, true); + nvkm_dp_enable(outp, true); } - nvkm_notify_get(&dp->hpd); + nvkm_notify_get(&outp->dp.hpd); } static void * nvkm_dp_dtor(struct nvkm_outp *outp) { - struct nvkm_dp *dp = nvkm_dp(outp); - nvkm_notify_fini(&dp->hpd); - return dp; + nvkm_notify_fini(&outp->dp.hpd); + return outp; } static const struct nvkm_outp_func @@ -775,75 +762,57 @@ nvkm_dp_func = { .disable = nvkm_dp_disable, }; -static int -nvkm_dp_ctor(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, - struct nvkm_i2c_aux *aux, struct nvkm_dp *dp) +int +nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, struct nvkm_outp **poutp) { struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_bios *bios = device->bios; struct nvkm_i2c *i2c = device->i2c; + struct nvkm_outp *outp; u8 hdr, cnt, len; u32 data; int ret; - ret = nvkm_outp_ctor(&nvkm_dp_func, disp, index, dcbE, &dp->outp); + ret = nvkm_outp_new_(&nvkm_dp_func, disp, index, dcbE, poutp); + outp = *poutp; if (ret) return ret; - dp->aux = aux; - if (!dp->aux) { - OUTP_ERR(&dp->outp, "no aux"); + if (dcbE->location == 0) + outp->dp.aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_CCB(dcbE->i2c_index)); + else + outp->dp.aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbE->extdev)); + if (!outp->dp.aux) { + OUTP_ERR(outp, "no aux"); return -EINVAL; } /* bios data is not optional */ - data = nvbios_dpout_match(bios, dp->outp.info.hasht, - dp->outp.info.hashm, &dp->version, - &hdr, &cnt, &len, &dp->info); + data = nvbios_dpout_match(bios, outp->info.hasht, outp->info.hashm, + &outp->dp.version, &hdr, &cnt, &len, &outp->dp.info); if (!data) { - OUTP_ERR(&dp->outp, "no bios dp data"); + OUTP_ERR(outp, "no bios dp data"); return -EINVAL; } - OUTP_DBG(&dp->outp, "bios dp %02x %02x %02x %02x", - dp->version, hdr, cnt, len); + OUTP_DBG(outp, "bios dp %02x %02x %02x %02x", outp->dp.version, hdr, cnt, len); /* hotplug detect, replaces gpio-based mechanism with aux events */ ret = nvkm_notify_init(NULL, &i2c->event, nvkm_dp_hpd, true, &(struct nvkm_i2c_ntfy_req) { .mask = NVKM_I2C_PLUG | NVKM_I2C_UNPLUG | NVKM_I2C_IRQ, - .port = dp->aux->id, + .port = outp->dp.aux->id, }, sizeof(struct nvkm_i2c_ntfy_req), sizeof(struct nvkm_i2c_ntfy_rep), - &dp->hpd); + &outp->dp.hpd); if (ret) { - OUTP_ERR(&dp->outp, "error monitoring aux hpd: %d", ret); + OUTP_ERR(outp, "error monitoring aux hpd: %d", ret); return ret; } - mutex_init(&dp->mutex); - atomic_set(&dp->lt.done, 0); + mutex_init(&outp->dp.mutex); + atomic_set(&outp->dp.lt.done, 0); return 0; } - -int -nvkm_dp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, - struct nvkm_outp **poutp) -{ - struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c; - struct nvkm_i2c_aux *aux; - struct nvkm_dp *dp; - - if (dcbE->location == 0) - aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_CCB(dcbE->i2c_index)); - else - aux = nvkm_i2c_aux_find(i2c, NVKM_I2C_AUX_EXT(dcbE->extdev)); - - if (!(dp = kzalloc(sizeof(*dp), GFP_KERNEL))) - return -ENOMEM; - *poutp = &dp->outp; - - return nvkm_dp_ctor(disp, index, dcbE, aux, dp); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h index 8e59dd469da6..1d86baa6a424 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/dp.h @@ -1,41 +1,8 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_DP_H__ #define __NVKM_DISP_DP_H__ -#define nvkm_dp(p) container_of((p), struct nvkm_dp, outp) #include "outp.h" -#include <core/notify.h> -#include <subdev/bios.h> -#include <subdev/bios/dp.h> - -struct nvkm_dp { - struct nvkm_outp outp; - - struct nvbios_dpout info; - u8 version; - - struct nvkm_i2c_aux *aux; - - struct nvkm_notify hpd; - bool present; - u8 lttpr[6]; - u8 lttprs; - u8 dpcd[16]; - - struct { - int dpcd; /* -1, or index into SUPPORTED_LINK_RATES table */ - u32 rate; - } rate[8]; - int rates; - int links; - - struct mutex mutex; - struct { - atomic_t done; - bool mst; - } lt; -}; - int nvkm_dp_new(struct nvkm_disp *, int index, struct dcb_output *, struct nvkm_outp **); void nvkm_dp_disable(struct nvkm_outp *, struct nvkm_ior *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c index 156bbe8b2de3..4966a51af3d7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g84.c @@ -21,28 +21,307 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +void +g84_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + 0x1f000000 /* ??? */ | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header); + nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); + } + + /* Audio InfoFrame */ + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x616508 + hoff, 0x000a0184); + nvkm_wr32(device, 0x61650c + hoff, 0x00000071); + nvkm_wr32(device, 0x616510 + hoff, 0x00000000); + nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); + + /* Vendor InfoFrame */ + nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000); + if (vendor_size) { + nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header); + nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high); + /* Is there a second (or up to fourth?) set of subpack registers here? */ + /* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */ + /* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */ + nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001); + } + + nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ + nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ + nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ + + /* ??? */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + + /* HDMI_CTRL */ + nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); +} + +static const struct nvkm_ior_func +g84_sor = { + .state = nv50_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = g84_sor_hdmi_ctrl, + }, +}; + +int +g84_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&g84_sor, disp, SOR, id, false); +} + +static const struct nvkm_disp_mthd_list +g84_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x6109a0 }, + { 0x0088, 0x6109c0 }, + { 0x008c, 0x6109c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +g84_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &g84_disp_ovly_mthd_base }, + {} + } +}; + +const struct nvkm_disp_chan_user +g84_disp_ovly = { + .func = &nv50_disp_dmac_func, + .ctrl = 3, + .user = 3, + .mthd = &g84_disp_ovly_mthd, +}; + +static const struct nvkm_disp_mthd_list +g84_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0008c4 }, + { 0x0088, 0x0008d0 }, + { 0x008c, 0x0008dc }, + { 0x0090, 0x0008e4 }, + { 0x0094, 0x610884 }, + { 0x00a0, 0x6108a0 }, + { 0x00a4, 0x610878 }, + { 0x00c0, 0x61086c }, + { 0x00c4, 0x610800 }, + { 0x00c8, 0x61080c }, + { 0x00cc, 0x610818 }, + { 0x00e0, 0x610858 }, + { 0x00e4, 0x610860 }, + { 0x00e8, 0x6108ac }, + { 0x00ec, 0x6108b4 }, + { 0x00fc, 0x610824 }, + { 0x0100, 0x610894 }, + { 0x0104, 0x61082c }, + { 0x0110, 0x6108bc }, + { 0x0114, 0x61088c }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +g84_disp_base_mthd = { + .name = "Base", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &g84_disp_base_mthd_base }, + { "Image", 2, &nv50_disp_base_mthd_image }, + {} + } +}; + +const struct nvkm_disp_chan_user +g84_disp_base = { + .func = &nv50_disp_dmac_func, + .ctrl = 1, + .user = 1, + .mthd = &g84_disp_base_mthd, +}; + +const struct nvkm_disp_mthd_list +g84_disp_core_mthd_dac = { + .mthd = 0x0080, + .addr = 0x000008, + .data = { + { 0x0400, 0x610b58 }, + { 0x0404, 0x610bdc }, + { 0x0420, 0x610bc4 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +g84_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000540, + .data = { + { 0x0800, 0x610ad8 }, + { 0x0804, 0x610ad0 }, + { 0x0808, 0x610a48 }, + { 0x080c, 0x610a78 }, + { 0x0810, 0x610ac0 }, + { 0x0814, 0x610af8 }, + { 0x0818, 0x610b00 }, + { 0x081c, 0x610ae8 }, + { 0x0820, 0x610af0 }, + { 0x0824, 0x610b08 }, + { 0x0828, 0x610b10 }, + { 0x082c, 0x610a68 }, + { 0x0830, 0x610a60 }, + { 0x0834, 0x000000 }, + { 0x0838, 0x610a40 }, + { 0x0840, 0x610a24 }, + { 0x0844, 0x610a2c }, + { 0x0848, 0x610aa8 }, + { 0x084c, 0x610ab0 }, + { 0x085c, 0x610c5c }, + { 0x0860, 0x610a84 }, + { 0x0864, 0x610a90 }, + { 0x0868, 0x610b18 }, + { 0x086c, 0x610b20 }, + { 0x0870, 0x610ac8 }, + { 0x0874, 0x610a38 }, + { 0x0878, 0x610c50 }, + { 0x0880, 0x610a58 }, + { 0x0884, 0x610a9c }, + { 0x089c, 0x610c68 }, + { 0x08a0, 0x610a70 }, + { 0x08a4, 0x610a50 }, + { 0x08a8, 0x610ae0 }, + { 0x08c0, 0x610b28 }, + { 0x08c4, 0x610b30 }, + { 0x08c8, 0x610b40 }, + { 0x08d4, 0x610b38 }, + { 0x08d8, 0x610b48 }, + { 0x08dc, 0x610b50 }, + { 0x0900, 0x610a18 }, + { 0x0904, 0x610ab8 }, + { 0x0910, 0x610c70 }, + { 0x0914, 0x610c78 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +g84_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &g84_disp_core_mthd_dac }, + { "SOR", 2, &nv50_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &g84_disp_core_mthd_head }, + {} + } +}; + +const struct nvkm_disp_chan_user +g84_disp_core = { + .func = &nv50_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &g84_disp_core_mthd, +}; + +static const struct nvkm_disp_func g84_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = &g84_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = nv50_sor_cnt, .new = g84_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,G82_DISP }, + .user = { + {{0,0,G82_DISP_CURSOR }, nvkm_disp_chan_new, &nv50_disp_curs }, + {{0,0,G82_DISP_OVERLAY }, nvkm_disp_chan_new, &nv50_disp_oimm }, + {{0,0,G82_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,G82_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g84_disp_core }, + {{0,0,G82_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, & g84_disp_ovly }, + {} + }, }; int g84_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&g84_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&g84_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c index 3425b5d3bc72..a4853c4e5ee3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/g94.c @@ -21,28 +21,357 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <subdev/timer.h> + +#include <nvif/class.h> + +void +g94_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + + nvkm_mask(device, 0x61c128 + loff, 0x0000003f, watermark); +} + +void +g94_sor_dp_activesym(struct nvkm_ior *sor, int head, + u8 TU, u8 VTUa, u8 VTUf, u8 VTUi) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + + nvkm_mask(device, 0x61c10c + loff, 0x000001fc, TU << 2); + nvkm_mask(device, 0x61c128 + loff, 0x010f7f00, VTUa << 24 | VTUf << 16 | VTUi << 8); +} + +void +g94_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, h); + nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, v); +} + +void +g94_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp->lanes[ln] * 8; + u32 data[3]; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x0000ff00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); +} + +void +g94_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + u32 data; + + switch (pattern) { + case 0: data = 0x00001000; break; + case 1: data = 0x01000000; break; + case 2: data = 0x02000000; break; + default: + WARN_ON(1); + return; + } + + nvkm_mask(device, 0x61c10c + loff, 0x0f001000, data); +} + +void +g94_sor_dp_power(struct nvkm_ior *sor, int nr) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 mask = 0, i; + + for (i = 0; i < nr; i++) + mask |= 1 << sor->func->dp->lanes[i]; + + nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask); + nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c034 + soff) & 0x80000000)) + break; + ); +} + +int +g94_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.ef) + dpctrl |= 0x00004000; + if (sor->dp.bw > 0x06) + clksor |= 0x00040000; + + nvkm_mask(device, 0x614300 + soff, 0x000c0000, clksor); + nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl); + return 0; +} + +const struct nvkm_ior_func_dp +g94_sor_dp = { + .lanes = { 2, 1, 0, 3}, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, +}; + +static bool +g94_sor_war_needed(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + if (sor->asy.proto == TMDS) { + switch (nvkm_rd32(device, 0x614300 + soff) & 0x00030000) { + case 0x00000000: + case 0x00030000: + return true; + default: + break; + } + } + + return false; +} + +static void +g94_sor_war_update_sppll1(struct nvkm_disp *disp) +{ + struct nvkm_device *device = disp->engine.subdev.device; + struct nvkm_ior *ior; + bool used = false; + u32 clksor; + + list_for_each_entry(ior, &disp->iors, head) { + if (ior->type != SOR) + continue; + + clksor = nvkm_rd32(device, 0x614300 + nv50_ior_base(ior)); + switch (clksor & 0x03000000) { + case 0x02000000: + case 0x03000000: + used = true; + break; + default: + break; + } + } + + if (used) + return; + + nvkm_mask(device, 0x00e840, 0x80000000, 0x00000000); +} + +static void +g94_sor_war_3(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 sorpwr; + + if (!g94_sor_war_needed(sor)) + return; + + sorpwr = nvkm_rd32(device, 0x61c004 + soff); + if (sorpwr & 0x00000001) { + u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); + u32 pd_pc = (seqctl & 0x00000f00) >> 8; + u32 pu_pc = seqctl & 0x0000000f; + + nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x1f008000); + + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); + nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000000); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); + + nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x00002000); + nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f000000); + } + + nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x00000000); + + if (sorpwr & 0x00000001) + nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000001); + + g94_sor_war_update_sppll1(sor->disp); +} + +static void +g94_sor_war_2(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + + if (!g94_sor_war_needed(sor)) + return; + + nvkm_mask(device, 0x00e840, 0x80000000, 0x80000000); + nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x03000000); + nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000001); + + nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x00000000); + nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x14000000); + nvkm_usec(device, 400, NVKM_DELAY); + nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x00000000); + nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x01000000); + + if (nvkm_rd32(device, 0x61c004 + soff) & 0x00000001) { + u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); + u32 pu_pc = seqctl & 0x0000000f; + nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f008000); + } +} + +void +g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610794 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x00000003; + nv50_pior_depth(sor, state, ctrl); +} + +static const struct nvkm_ior_func +g94_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .war_2 = g94_sor_war_2, + .war_3 = g94_sor_war_3, + .dp = &g94_sor_dp, +}; + +static int +g94_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&g94_sor, disp, SOR, id, false); +} + +int +g94_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x0f000000) >> 24; + return 4; +} + +static const struct nvkm_disp_mthd_list +g94_disp_core_mthd_sor = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0600, 0x610794 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +g94_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &g84_disp_core_mthd_dac }, + { "SOR", 4, &g94_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &g84_disp_core_mthd_head }, + {} + } +}; + +const struct nvkm_disp_chan_user +g94_disp_core = { + .func = &nv50_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &g94_disp_core_mthd, +}; + +static const struct nvkm_disp_func g94_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = &g94_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = g94_sor_cnt, .new = g94_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT206_DISP }, + .user = { + {{0,0, G82_DISP_CURSOR }, nvkm_disp_chan_new, & nv50_disp_curs }, + {{0,0, G82_DISP_OVERLAY }, nvkm_disp_chan_new, & nv50_disp_oimm }, + {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT206_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g94_disp_core }, + {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, >200_disp_ovly }, + {} + }, }; int g94_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&g94_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&g94_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c index 68aa52588d92..7489d0d7fce0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ga102.c @@ -19,29 +19,135 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <subdev/timer.h> + +#include <nvif/class.h> + +static int +ga102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + switch (sor->dp.bw) { + case 0x06: clksor |= 0x00000000; break; + case 0x0a: clksor |= 0x00040000; break; + case 0x14: clksor |= 0x00080000; break; + case 0x1e: clksor |= 0x000c0000; break; + case 0x08: clksor |= 0x00100000; break; + case 0x09: clksor |= 0x00140000; break; + case 0x0c: clksor |= 0x00180000; break; + case 0x10: clksor |= 0x001c0000; break; + default: + WARN_ON(1); + return -EINVAL; + } + + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.mst) + dpctrl |= 0x40000000; + if (sor->dp.ef) + dpctrl |= 0x00004000; + + nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); + + /*XXX*/ + nvkm_msec(device, 40, NVKM_DELAY); + nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000); + nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001); + + nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); + return 0; +} + +static const struct nvkm_ior_func_dp +ga102_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = ga102_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = tu102_sor_dp_vcpi, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, +}; + +static void +ga102_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + u32 div2 = 0; + + if (sor->asy.proto == TMDS) { + if (sor->tmds.high_speed) + div2 = 1; + } + + nvkm_wr32(device, 0x00ec08 + (sor->id * 0x10), 0x00000000); + nvkm_wr32(device, 0x00ec04 + (sor->id * 0x10), div2); +} + +static const struct nvkm_ior_func +ga102_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = ga102_sor_clock, + .hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &ga102_sor_dp, + .hda = &gv100_sor_hda, +}; + +static int +ga102_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda = nvkm_rd32(device, 0x08a15c); + + return nvkm_ior_new_(&ga102_sor, disp, SOR, id, hda & BIT(id)); +} + +static const struct nvkm_disp_func ga102_disp = { + .oneinit = nv50_disp_oneinit, .init = tu102_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, - .uevent = &gv100_disp_chan_uevent, .super = gv100_disp_super, - .root = &ga102_disp_root_oclass, + .uevent = &gv100_disp_chan_uevent, .wndw = { .cnt = gv100_disp_wndw_cnt }, .head = { .cnt = gv100_head_cnt, .new = gv100_head_new }, .sor = { .cnt = gv100_sor_cnt, .new = ga102_sor_new }, .ramht_size = 0x2000, + .root = { 0, 0,GA102_DISP }, + .user = { + {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, + {{ 0, 0,GA102_DISP_CURSOR }, nvkm_disp_chan_new, &gv100_disp_curs }, + {{ 0, 0,GA102_DISP_WINDOW_IMM_CHANNEL_DMA}, nvkm_disp_wndw_new, &gv100_disp_wimm }, + {{ 0, 0,GA102_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gv100_disp_core }, + {{ 0, 0,GA102_DISP_WINDOW_CHANNEL_DMA }, nvkm_disp_wndw_new, &gv100_disp_wndw }, + {} + }, }; int ga102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&ga102_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&ga102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c index a6bafe7fea1f..39822f1b5b95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gf119.c @@ -21,75 +21,1033 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" +#include "outp.h" #include <core/ramht.h> #include <subdev/timer.h> +#include <nvif/class.h> + +static void +gf119_sor_hda_device_entry(struct nvkm_ior *ior, int head) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + + nvkm_mask(device, 0x616548 + hoff, 0x00000070, head << 4); +} + +void +gf119_sor_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = 0x030 * ior->id + (head * 0x04); + int i; + + for (i = 0; i < size; i++) + nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | data[i]); + for (; i < 0x60; i++) + nvkm_wr32(device, 0x10ec00 + soff, (i << 8)); + nvkm_mask(device, 0x10ec10 + soff, 0x80000002, 0x80000002); +} + +void +gf119_sor_hda_hpd(struct nvkm_ior *ior, int head, bool present) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = 0x030 * ior->id + (head * 0x04); + u32 data = 0x80000000; + u32 mask = 0x80000001; + + if (present) { + ior->func->hda->device_entry(ior, head); + data |= 0x00000001; + } else { + mask |= 0x00000002; + } + + nvkm_mask(device, 0x10ec10 + soff, mask, data); +} + +const struct nvkm_ior_func_hda +gf119_sor_hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gf119_sor_hda_device_entry, +}; + +void +gf119_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616610 + hoff, 0x0800003f, 0x08000000 | watermark); +} + +void +gf119_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, h); + nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, v); +} + +void +gf119_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x616618 + hoff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x616618 + hoff) & 0x80000000)) + break; + ); +} + +void +gf119_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot); + nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn); +} + +void +gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp->lanes[ln] * 8; + u32 data[4]; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x0000ff00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); + + data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); + nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); +} + +static void +gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 data; + + switch (pattern) { + case 0: data = 0x10101010; break; + case 1: data = 0x01010101; break; + case 2: data = 0x02020202; break; + case 3: data = 0x03030303; break; + default: + WARN_ON(1); + return; + } + + nvkm_mask(device, 0x61c110 + soff, 0x1f1f1f1f, data); +} + +int +gf119_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + clksor |= sor->dp.bw << 18; + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.mst) + dpctrl |= 0x40000000; + if (sor->dp.ef) + dpctrl |= 0x00004000; + + nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); + nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); + return 0; +} + +const struct nvkm_ior_func_dp +gf119_sor_dp = { + .lanes = { 2, 1, 0, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gf119_sor_dp_pattern, + .drive = gf119_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, +}; + +static void +gf119_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x61671c + hoff, avi_infoframe.header); + nvkm_wr32(device, 0x616720 + hoff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x616724 + hoff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x616728 + hoff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x61672c + hoff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); + } + + /* GENERIC(?) / Vendor InfoFrame? */ + nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000); + if (vendor_size) { + /* + * These appear to be the audio infoframe registers, + * but no other set of infoframe registers has yet + * been found. + */ + nvkm_wr32(device, 0x616738 + hoff, vendor_infoframe.header); + nvkm_wr32(device, 0x61673c + hoff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x616740 + hoff, vendor_infoframe.subpack0_high); + /* Is there a second (or further?) set of subpack registers here? */ + nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001); + } + + /* ??? InfoFrame? */ + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6167ac + hoff, 0x00000010); + nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000001); + + /* HDMI_CTRL */ + nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); +} + +void +gf119_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 div1 = sor->asy.link == 3; + u32 div2 = sor->asy.link == 3; + + if (sor->asy.proto == TMDS) { + const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a; + nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18); + if (sor->tmds.high_speed) + div2 = 1; + } + + nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1); +} + +void +gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = (state == &sor->asy) * 0x20000 + sor->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x640200 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x0000000f; +} + +static const struct nvkm_ior_func +gf119_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gf119_sor_hdmi_ctrl, + }, + .dp = &gf119_sor_dp, + .hda = &gf119_sor_hda, +}; + +static int +gf119_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gf119_sor, disp, SOR, id, true); +} + +int +gf119_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = (nvkm_rd32(device, 0x612004) & 0x0000ff00) >> 8; + return 8; +} + +static void +gf119_dac_clock(struct nvkm_ior *dac) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + nvkm_mask(device, 0x612280 + doff, 0x07070707, 0x00000000); +} + +static void +gf119_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 coff = (state == &dac->asy) * 0x20000 + dac->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x640180 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = CRT; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x0000000f; +} + +static const struct nvkm_ior_func +gf119_dac = { + .state = gf119_dac_state, + .power = nv50_dac_power, + .sense = nv50_dac_sense, + .clock = gf119_dac_clock, +}; + +int +gf119_dac_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gf119_dac, disp, DAC, id, false); +} + +int +gf119_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = (nvkm_rd32(device, 0x612004) & 0x000000f0) >> 4; + return 4; +} + +static void +gf119_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000000); +} + +static void +gf119_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001); +} + +void +gf119_head_rgclk(struct nvkm_head *head, int div) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x612200 + (head->id * 0x800), 0x0000000f, div); +} + +static void +gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300; + u32 data; + + data = nvkm_rd32(device, 0x640414 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x640418 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x64041c + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x640420 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + state->hz = nvkm_rd32(device, 0x640450 + hoff); + + data = nvkm_rd32(device, 0x640404 + hoff); + switch ((data & 0x000003c0) >> 6) { + case 6: state->or.depth = 30; break; + case 5: state->or.depth = 24; break; + case 2: state->or.depth = 18; break; + case 0: state->or.depth = 18; break; /*XXX: "default" */ + default: + state->or.depth = 18; + WARN_ON(1); + break; + } +} + +static const struct nvkm_head_func +gf119_head = { + .state = gf119_head_state, + .rgpos = nv50_head_rgpos, + .rgclk = gf119_head_rgclk, + .vblank_get = gf119_head_vblank_get, + .vblank_put = gf119_head_vblank_put, +}; + +int +gf119_head_new(struct nvkm_disp *disp, int id) +{ + return nvkm_head_new_(&gf119_head, disp, id); +} + +int +gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + *pmask = nvkm_rd32(device, 0x612004) & 0x0000000f; + return nvkm_rd32(device, 0x022448); +} + +static void +gf119_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000000 << index); + nvkm_wr32(device, 0x61008c, 0x00000001 << index); +} + +static void +gf119_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_wr32(device, 0x61008c, 0x00000001 << index); + nvkm_mask(device, 0x610090, 0x00000001 << index, 0x00000001 << index); +} + +const struct nvkm_event_func +gf119_disp_chan_uevent = { + .init = gf119_disp_chan_uevent_init, + .fini = gf119_disp_chan_uevent_fini, +}; + +void +gf119_disp_chan_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->chid.user; + if (!en) { + nvkm_mask(device, 0x610090, mask, 0x00000000); + nvkm_mask(device, 0x6100a0, mask, 0x00000000); + } else { + nvkm_mask(device, 0x6100a0, mask, mask); + } +} + +static void +gf119_disp_pioc_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + } +} + +static int +gf119_disp_pioc_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* activate channel */ + nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10)); + if ((tmp & 0x00030000) == 0x00010000) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_pioc_func = { + .init = gf119_disp_pioc_init, + .fini = gf119_disp_pioc_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, +}; + +int +gf119_disp_dmac_bind(struct nvkm_disp_chan *chan, struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -9, handle, + chan->chid.user << 27 | 0x00000001); +} + +void +gf119_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* deactivate channel */ + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00001010, 0x00001000); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); +} + +static int +gf119_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610494 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x610498 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61049c + (ctrl * 0x0010), 0x00000001); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_dmac_func = { + .push = nv50_disp_dmac_push, + .init = gf119_disp_dmac_init, + .fini = gf119_disp_dmac_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +const struct nvkm_disp_chan_user +gf119_disp_curs = { + .func = &gf119_disp_pioc_func, + .ctrl = 13, + .user = 13, +}; + +const struct nvkm_disp_chan_user +gf119_disp_oimm = { + .func = &gf119_disp_pioc_func, + .ctrl = 9, + .user = 9, +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_ovly_mthd_base = { + .mthd = 0x0000, + .data = { + { 0x0080, 0x665080 }, + { 0x0084, 0x665084 }, + { 0x0088, 0x665088 }, + { 0x008c, 0x66508c }, + { 0x0090, 0x665090 }, + { 0x0094, 0x665094 }, + { 0x00a0, 0x6650a0 }, + { 0x00a4, 0x6650a4 }, + { 0x00b0, 0x6650b0 }, + { 0x00b4, 0x6650b4 }, + { 0x00b8, 0x6650b8 }, + { 0x00c0, 0x6650c0 }, + { 0x00e0, 0x6650e0 }, + { 0x00e4, 0x6650e4 }, + { 0x00e8, 0x6650e8 }, + { 0x0100, 0x665100 }, + { 0x0104, 0x665104 }, + { 0x0108, 0x665108 }, + { 0x010c, 0x66510c }, + { 0x0110, 0x665110 }, + { 0x0118, 0x665118 }, + { 0x011c, 0x66511c }, + { 0x0120, 0x665120 }, + { 0x0124, 0x665124 }, + { 0x0130, 0x665130 }, + { 0x0134, 0x665134 }, + { 0x0138, 0x665138 }, + { 0x013c, 0x66513c }, + { 0x0140, 0x665140 }, + { 0x0144, 0x665144 }, + { 0x0148, 0x665148 }, + { 0x014c, 0x66514c }, + { 0x0150, 0x665150 }, + { 0x0154, 0x665154 }, + { 0x0158, 0x665158 }, + { 0x015c, 0x66515c }, + { 0x0160, 0x665160 }, + { 0x0164, 0x665164 }, + { 0x0168, 0x665168 }, + { 0x016c, 0x66516c }, + { 0x0400, 0x665400 }, + { 0x0408, 0x665408 }, + { 0x040c, 0x66540c }, + { 0x0410, 0x665410 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gf119_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_ovly_mthd_base }, + {} + } +}; + +static const struct nvkm_disp_chan_user +gf119_disp_ovly = { + .func = &gf119_disp_dmac_func, + .ctrl = 5, + .user = 5, + .mthd = &gf119_disp_ovly_mthd, +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x661080 }, + { 0x0084, 0x661084 }, + { 0x0088, 0x661088 }, + { 0x008c, 0x66108c }, + { 0x0090, 0x661090 }, + { 0x0094, 0x661094 }, + { 0x00a0, 0x6610a0 }, + { 0x00a4, 0x6610a4 }, + { 0x00c0, 0x6610c0 }, + { 0x00c4, 0x6610c4 }, + { 0x00c8, 0x6610c8 }, + { 0x00cc, 0x6610cc }, + { 0x00e0, 0x6610e0 }, + { 0x00e4, 0x6610e4 }, + { 0x00e8, 0x6610e8 }, + { 0x00ec, 0x6610ec }, + { 0x00fc, 0x6610fc }, + { 0x0100, 0x661100 }, + { 0x0104, 0x661104 }, + { 0x0108, 0x661108 }, + { 0x010c, 0x66110c }, + { 0x0110, 0x661110 }, + { 0x0114, 0x661114 }, + { 0x0118, 0x661118 }, + { 0x011c, 0x66111c }, + { 0x0130, 0x661130 }, + { 0x0134, 0x661134 }, + { 0x0138, 0x661138 }, + { 0x013c, 0x66113c }, + { 0x0140, 0x661140 }, + { 0x0144, 0x661144 }, + { 0x0148, 0x661148 }, + { 0x014c, 0x66114c }, + { 0x0150, 0x661150 }, + { 0x0154, 0x661154 }, + { 0x0158, 0x661158 }, + { 0x015c, 0x66115c }, + { 0x0160, 0x661160 }, + { 0x0164, 0x661164 }, + { 0x0168, 0x661168 }, + { 0x016c, 0x66116c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_base_mthd_image = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0400, 0x661400 }, + { 0x0404, 0x661404 }, + { 0x0408, 0x661408 }, + { 0x040c, 0x66140c }, + { 0x0410, 0x661410 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gf119_disp_base_mthd = { + .name = "Base", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_base_mthd_base }, + { "Image", 2, &gf119_disp_base_mthd_image }, + {} + } +}; + +const struct nvkm_disp_chan_user +gf119_disp_base = { + .func = &gf119_disp_dmac_func, + .ctrl = 1, + .user = 1, + .mthd = &gf119_disp_base_mthd, +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x660080 }, + { 0x0084, 0x660084 }, + { 0x0088, 0x660088 }, + { 0x008c, 0x000000 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_dac = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0180, 0x660180 }, + { 0x0184, 0x660184 }, + { 0x0188, 0x660188 }, + { 0x0190, 0x660190 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_sor = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0200, 0x660200 }, + { 0x0204, 0x660204 }, + { 0x0208, 0x660208 }, + { 0x0210, 0x660210 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_pior = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0300, 0x660300 }, + { 0x0304, 0x660304 }, + { 0x0308, 0x660308 }, + { 0x0310, 0x660310 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gf119_disp_core_mthd_head = { + .mthd = 0x0300, + .addr = 0x000300, + .data = { + { 0x0400, 0x660400 }, + { 0x0404, 0x660404 }, + { 0x0408, 0x660408 }, + { 0x040c, 0x66040c }, + { 0x0410, 0x660410 }, + { 0x0414, 0x660414 }, + { 0x0418, 0x660418 }, + { 0x041c, 0x66041c }, + { 0x0420, 0x660420 }, + { 0x0424, 0x660424 }, + { 0x0428, 0x660428 }, + { 0x042c, 0x66042c }, + { 0x0430, 0x660430 }, + { 0x0434, 0x660434 }, + { 0x0438, 0x660438 }, + { 0x0440, 0x660440 }, + { 0x0444, 0x660444 }, + { 0x0448, 0x660448 }, + { 0x044c, 0x66044c }, + { 0x0450, 0x660450 }, + { 0x0454, 0x660454 }, + { 0x0458, 0x660458 }, + { 0x045c, 0x66045c }, + { 0x0460, 0x660460 }, + { 0x0468, 0x660468 }, + { 0x046c, 0x66046c }, + { 0x0470, 0x660470 }, + { 0x0474, 0x660474 }, + { 0x0480, 0x660480 }, + { 0x0484, 0x660484 }, + { 0x048c, 0x66048c }, + { 0x0490, 0x660490 }, + { 0x0494, 0x660494 }, + { 0x0498, 0x660498 }, + { 0x04b0, 0x6604b0 }, + { 0x04b8, 0x6604b8 }, + { 0x04bc, 0x6604bc }, + { 0x04c0, 0x6604c0 }, + { 0x04c4, 0x6604c4 }, + { 0x04c8, 0x6604c8 }, + { 0x04d0, 0x6604d0 }, + { 0x04d4, 0x6604d4 }, + { 0x04e0, 0x6604e0 }, + { 0x04e4, 0x6604e4 }, + { 0x04e8, 0x6604e8 }, + { 0x04ec, 0x6604ec }, + { 0x04f0, 0x6604f0 }, + { 0x04f4, 0x6604f4 }, + { 0x04f8, 0x6604f8 }, + { 0x04fc, 0x6604fc }, + { 0x0500, 0x660500 }, + { 0x0504, 0x660504 }, + { 0x0508, 0x660508 }, + { 0x050c, 0x66050c }, + { 0x0510, 0x660510 }, + { 0x0514, 0x660514 }, + { 0x0518, 0x660518 }, + { 0x051c, 0x66051c }, + { 0x052c, 0x66052c }, + { 0x0530, 0x660530 }, + { 0x054c, 0x66054c }, + { 0x0550, 0x660550 }, + { 0x0554, 0x660554 }, + { 0x0558, 0x660558 }, + { 0x055c, 0x66055c }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gf119_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_core_mthd_base }, + { "DAC", 3, &gf119_disp_core_mthd_dac }, + { "SOR", 8, &gf119_disp_core_mthd_sor }, + { "PIOR", 4, &gf119_disp_core_mthd_pior }, + { "HEAD", 4, &gf119_disp_core_mthd_head }, + {} + } +}; + +void +gf119_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* deactivate channel */ + nvkm_mask(device, 0x610490, 0x00000010, 0x00000000); + nvkm_mask(device, 0x610490, 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "core fini: %08x\n", + nvkm_rd32(device, 0x610490)); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000); +} + +static int +gf119_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610494, chan->push); + nvkm_wr32(device, 0x610498, 0x00010000); + nvkm_wr32(device, 0x61049c, 0x00000001); + nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610490, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610490)); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gf119_disp_core_func = { + .push = nv50_disp_dmac_push, + .init = gf119_disp_core_init, + .fini = gf119_disp_core_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +static const struct nvkm_disp_chan_user +gf119_disp_core = { + .func = &gf119_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &gf119_disp_core_mthd, +}; + void gf119_disp_super(struct work_struct *work) { - struct nv50_disp *disp = - container_of(work, struct nv50_disp, supervisor); - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_disp *disp = container_of(work, struct nvkm_disp, super.work); + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_head *head; u32 mask[4]; - nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super)); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_debug(subdev, "supervisor %d\n", ffs(disp->super.pending)); + mutex_lock(&disp->super.mutex); + + list_for_each_entry(head, &disp->heads, head) { mask[head->id] = nvkm_rd32(device, 0x6101d4 + (head->id * 0x800)); HEAD_DBG(head, "%08x", mask[head->id]); } - if (disp->super & 0x00000001) { + if (disp->super.pending & 0x00000001) { nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); nv50_disp_super_1(disp); - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_1_0(disp, head); } } else - if (disp->super & 0x00000002) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000002) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_2_0(disp, head); } - nvkm_outp_route(&disp->base); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_outp_route(disp); + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00010000)) continue; nv50_disp_super_2_1(disp, head); } - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_2_2(disp, head); } } else - if (disp->super & 0x00000004) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000004) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_3_0(disp, head); } } - list_for_each_entry(head, &disp->base.head, head) + list_for_each_entry(head, &disp->heads, head) nvkm_wr32(device, 0x6101d4 + (head->id * 0x800), 0x00000000); + nvkm_wr32(device, 0x6101d0, 0x80000000); + mutex_unlock(&disp->super.mutex); } void -gf119_disp_intr_error(struct nv50_disp *disp, int chid) +gf119_disp_intr_error(struct nvkm_disp *disp, int chid) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x6101f0 + (chid * 12)); u32 type = (stat & 0x00007000) >> 12; @@ -119,9 +1077,9 @@ gf119_disp_intr_error(struct nv50_disp *disp, int chid) } void -gf119_disp_intr(struct nv50_disp *disp) +gf119_disp_intr(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_head *head; u32 intr = nvkm_rd32(device, 0x610088); @@ -147,9 +1105,9 @@ gf119_disp_intr(struct nv50_disp *disp) if (intr & 0x00100000) { u32 stat = nvkm_rd32(device, 0x6100ac); if (stat & 0x00000007) { - disp->super = (stat & 0x00000007); - queue_work(disp->wq, &disp->supervisor); - nvkm_wr32(device, 0x6100ac, disp->super); + disp->super.pending = (stat & 0x00000007); + queue_work(disp->super.wq, &disp->super.work); + nvkm_wr32(device, 0x6100ac, disp->super.pending); stat &= ~0x00000007; } @@ -161,13 +1119,13 @@ gf119_disp_intr(struct nv50_disp *disp) intr &= ~0x00100000; } - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 0x800; u32 mask = 0x01000000 << head->id; if (mask & intr) { u32 stat = nvkm_rd32(device, 0x6100bc + hoff); if (stat & 0x00000001) - nvkm_disp_vblank(&disp->base, head->id); + nvkm_disp_vblank(disp, head->id); nvkm_mask(device, 0x6100bc + hoff, 0, 0); nvkm_rd32(device, 0x6100c0 + hoff); } @@ -175,17 +1133,17 @@ gf119_disp_intr(struct nv50_disp *disp) } void -gf119_disp_fini(struct nv50_disp *disp) +gf119_disp_fini(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; /* disable all interrupts */ nvkm_wr32(device, 0x6100b0, 0x00000000); } int -gf119_disp_init(struct nv50_disp *disp) +gf119_disp_init(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_head *head; u32 tmp; int i; @@ -196,7 +1154,7 @@ gf119_disp_init(struct nv50_disp *disp) */ /* ... CRTC caps */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 0x800; tmp = nvkm_rd32(device, 0x616104 + hoff); nvkm_wr32(device, 0x6101b4 + hoff, tmp); @@ -243,7 +1201,7 @@ gf119_disp_init(struct nv50_disp *disp) * * ftp://download.nvidia.com/open-gpu-doc/gk104-disable-underflow-reporting/1/gk104-disable-underflow-reporting.txt */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 0x800; nvkm_mask(device, 0x616308 + hoff, 0x00000111, 0x00000010); } @@ -251,23 +1209,32 @@ gf119_disp_init(struct nv50_disp *disp) return 0; } -static const struct nv50_disp_func +static const struct nvkm_disp_func gf119_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gf119_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gf119_sor_new }, + .root = { 0,0,GF110_DISP }, + .user = { + {{0,0,GF110_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GF110_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GF110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GF110_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gf119_disp_core }, + {{0,0,GF110_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gf119_disp_ovly }, + {} + }, }; int gf119_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gf119_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gf119_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c index 3b79cf233ac5..7248e9ec835e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk104.c @@ -21,28 +21,291 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +void +gk104_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + const u32 hdmi = head * 0x400; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header); + nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001); + } + + /* GENERIC(?) / Vendor InfoFrame? */ + nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000); + if (vendor_size) { + nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header); + nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high); + /* Is there a second (or further?) set of subpack registers here? */ + nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001); + } + + + /* ??? InfoFrame? */ + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010); + nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000001); + + /* ??? */ + nvkm_wr32(device, 0x690080 + hdmi, 0x82000000); + + /* HDMI_CTRL */ + nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); +} + +static const struct nvkm_ior_func +gk104_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + }, + .dp = &gf119_sor_dp, + .hda = &gf119_sor_hda, +}; + +int +gk104_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gk104_sor, disp, SOR, id, true); +} + +static const struct nvkm_disp_mthd_list +gk104_disp_ovly_mthd_base = { + .mthd = 0x0000, + .data = { + { 0x0080, 0x665080 }, + { 0x0084, 0x665084 }, + { 0x0088, 0x665088 }, + { 0x008c, 0x66508c }, + { 0x0090, 0x665090 }, + { 0x0094, 0x665094 }, + { 0x00a0, 0x6650a0 }, + { 0x00a4, 0x6650a4 }, + { 0x00b0, 0x6650b0 }, + { 0x00b4, 0x6650b4 }, + { 0x00b8, 0x6650b8 }, + { 0x00c0, 0x6650c0 }, + { 0x00c4, 0x6650c4 }, + { 0x00e0, 0x6650e0 }, + { 0x00e4, 0x6650e4 }, + { 0x00e8, 0x6650e8 }, + { 0x0100, 0x665100 }, + { 0x0104, 0x665104 }, + { 0x0108, 0x665108 }, + { 0x010c, 0x66510c }, + { 0x0110, 0x665110 }, + { 0x0118, 0x665118 }, + { 0x011c, 0x66511c }, + { 0x0120, 0x665120 }, + { 0x0124, 0x665124 }, + { 0x0130, 0x665130 }, + { 0x0134, 0x665134 }, + { 0x0138, 0x665138 }, + { 0x013c, 0x66513c }, + { 0x0140, 0x665140 }, + { 0x0144, 0x665144 }, + { 0x0148, 0x665148 }, + { 0x014c, 0x66514c }, + { 0x0150, 0x665150 }, + { 0x0154, 0x665154 }, + { 0x0158, 0x665158 }, + { 0x015c, 0x66515c }, + { 0x0160, 0x665160 }, + { 0x0164, 0x665164 }, + { 0x0168, 0x665168 }, + { 0x016c, 0x66516c }, + { 0x0400, 0x665400 }, + { 0x0404, 0x665404 }, + { 0x0408, 0x665408 }, + { 0x040c, 0x66540c }, + { 0x0410, 0x665410 }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gk104_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x001000, + .prev = -0x020000, + .data = { + { "Global", 1, &gk104_disp_ovly_mthd_base }, + {} + } +}; + +const struct nvkm_disp_chan_user +gk104_disp_ovly = { + .func = &gf119_disp_dmac_func, + .ctrl = 5, + .user = 5, + .mthd = &gk104_disp_ovly_mthd, +}; + +static const struct nvkm_disp_mthd_list +gk104_disp_core_mthd_head = { + .mthd = 0x0300, + .addr = 0x000300, + .data = { + { 0x0400, 0x660400 }, + { 0x0404, 0x660404 }, + { 0x0408, 0x660408 }, + { 0x040c, 0x66040c }, + { 0x0410, 0x660410 }, + { 0x0414, 0x660414 }, + { 0x0418, 0x660418 }, + { 0x041c, 0x66041c }, + { 0x0420, 0x660420 }, + { 0x0424, 0x660424 }, + { 0x0428, 0x660428 }, + { 0x042c, 0x66042c }, + { 0x0430, 0x660430 }, + { 0x0434, 0x660434 }, + { 0x0438, 0x660438 }, + { 0x0440, 0x660440 }, + { 0x0444, 0x660444 }, + { 0x0448, 0x660448 }, + { 0x044c, 0x66044c }, + { 0x0450, 0x660450 }, + { 0x0454, 0x660454 }, + { 0x0458, 0x660458 }, + { 0x045c, 0x66045c }, + { 0x0460, 0x660460 }, + { 0x0468, 0x660468 }, + { 0x046c, 0x66046c }, + { 0x0470, 0x660470 }, + { 0x0474, 0x660474 }, + { 0x047c, 0x66047c }, + { 0x0480, 0x660480 }, + { 0x0484, 0x660484 }, + { 0x0488, 0x660488 }, + { 0x048c, 0x66048c }, + { 0x0490, 0x660490 }, + { 0x0494, 0x660494 }, + { 0x0498, 0x660498 }, + { 0x04a0, 0x6604a0 }, + { 0x04b0, 0x6604b0 }, + { 0x04b8, 0x6604b8 }, + { 0x04bc, 0x6604bc }, + { 0x04c0, 0x6604c0 }, + { 0x04c4, 0x6604c4 }, + { 0x04c8, 0x6604c8 }, + { 0x04d0, 0x6604d0 }, + { 0x04d4, 0x6604d4 }, + { 0x04e0, 0x6604e0 }, + { 0x04e4, 0x6604e4 }, + { 0x04e8, 0x6604e8 }, + { 0x04ec, 0x6604ec }, + { 0x04f0, 0x6604f0 }, + { 0x04f4, 0x6604f4 }, + { 0x04f8, 0x6604f8 }, + { 0x04fc, 0x6604fc }, + { 0x0500, 0x660500 }, + { 0x0504, 0x660504 }, + { 0x0508, 0x660508 }, + { 0x050c, 0x66050c }, + { 0x0510, 0x660510 }, + { 0x0514, 0x660514 }, + { 0x0518, 0x660518 }, + { 0x051c, 0x66051c }, + { 0x0520, 0x660520 }, + { 0x0524, 0x660524 }, + { 0x052c, 0x66052c }, + { 0x0530, 0x660530 }, + { 0x054c, 0x66054c }, + { 0x0550, 0x660550 }, + { 0x0554, 0x660554 }, + { 0x0558, 0x660558 }, + { 0x055c, 0x66055c }, + {} + } +}; + +const struct nvkm_disp_chan_mthd +gk104_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = -0x020000, + .data = { + { "Global", 1, &gf119_disp_core_mthd_base }, + { "DAC", 3, &gf119_disp_core_mthd_dac }, + { "SOR", 8, &gf119_disp_core_mthd_sor }, + { "PIOR", 4, &gf119_disp_core_mthd_pior }, + { "HEAD", 4, &gk104_disp_core_mthd_head }, + {} + } +}; + +const struct nvkm_disp_chan_user +gk104_disp_core = { + .func = &gf119_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &gk104_disp_core_mthd, +}; + +static const struct nvkm_disp_func gk104_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gk104_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gk104_sor_new }, + .root = { 0,0,GK104_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK104_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GK104_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gk104_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gk104_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gk104_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c index 988eb12237a6..1704aa381ee9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gk110.c @@ -21,28 +21,39 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_disp_func gk110_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gk110_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gk104_sor_new }, + .root = { 0,0,GK110_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GK110_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gk110_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gk110_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gk110_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c index 5d8108feeacd..9e9ef49bd8ac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm107.c @@ -21,28 +21,94 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +void +gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + u32 mask = 0x1f1f1f1f, data; + + switch (pattern) { + case 0: data = 0x10101010; break; + case 1: data = 0x01010101; break; + case 2: data = 0x02020202; break; + case 3: data = 0x03030303; break; + case 4: data = 0x1b1b1b1b; break; + default: + WARN_ON(1); + return; + } + + if (sor->asy.link & 1) + nvkm_mask(device, 0x61c110 + soff, mask, data); + else + nvkm_mask(device, 0x61c12c + soff, mask, data); +} + +static const struct nvkm_ior_func_dp +gm107_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gf119_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, +}; + +static const struct nvkm_ior_func +gm107_sor = { + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + }, + .dp = &gm107_sor_dp, + .hda = &gf119_sor_hda, +}; + +static int +gm107_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&gm107_sor, disp, SOR, id, true); +} + +static const struct nvkm_disp_func gm107_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gm107_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gm107_sor_new }, + .root = { 0,0,GM107_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GM107_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gm107_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gm107_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gm107_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c index f7bb66087476..4ecc8f98af6e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gm200.c @@ -21,28 +21,162 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" +#include "outp.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +void +gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 loff = nv50_sor_link(sor); + const u32 shift = sor->func->dp->lanes[ln] * 8; + u32 data[4]; + + pu &= 0x0f; + + data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); + data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); + data[2] = nvkm_rd32(device, 0x61c130 + loff); + if ((data[2] & 0x00000f00) < (pu << 8) || ln == 0) + data[2] = (data[2] & ~0x00000f00) | (pu << 8); + + nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); + nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); + nvkm_wr32(device, 0x61c130 + loff, data[2]); + + data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); + nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); +} + +const struct nvkm_ior_func_dp +gm200_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = gf119_sor_dp_vcpi, + .audio = gf119_sor_dp_audio, + .audio_sym = gf119_sor_dp_audio_sym, + .watermark = gf119_sor_dp_watermark, +}; + +void +gm200_sor_hdmi_scdc(struct nvkm_ior *ior, u8 scdc) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(ior); + const u32 ctrl = scdc & 0x3; + + nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl); + + ior->tmds.high_speed = !!(scdc & 0x2); +} + +void +gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) +{ + struct nvkm_device *device = outp->disp->engine.subdev.device; + const u32 moff = __ffs(outp->info.or) * 0x100; + const u32 sor = ior ? ior->id + 1 : 0; + u32 link = ior ? (ior->asy.link == 2) : 0; + + if (outp->info.sorconf.link & 1) { + nvkm_mask(device, 0x612308 + moff, 0x0000001f, link << 4 | sor); + link++; + } + + if (outp->info.sorconf.link & 2) + nvkm_mask(device, 0x612388 + moff, 0x0000001f, link << 4 | sor); +} + +int +gm200_sor_route_get(struct nvkm_outp *outp, int *link) +{ + struct nvkm_device *device = outp->disp->engine.subdev.device; + const int sublinks = outp->info.sorconf.link; + int lnk[2], sor[2], m, s; + + for (*link = 0, m = __ffs(outp->info.or) * 2, s = 0; s < 2; m++, s++) { + if (sublinks & BIT(s)) { + u32 data = nvkm_rd32(device, 0x612308 + (m * 0x80)); + lnk[s] = (data & 0x00000010) >> 4; + sor[s] = (data & 0x0000000f); + if (!sor[s]) + return -1; + *link |= lnk[s]; + } + } + + if (sublinks == 3) { + if (sor[0] != sor[1] || WARN_ON(lnk[0] || !lnk[1])) + return -1; + } + + return ((sublinks & 1) ? sor[0] : sor[1]) - 1; +} + +static const struct nvkm_ior_func +gm200_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &gm200_sor_dp, + .hda = &gf119_sor_hda, +}; + +static int +gm200_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x101034); + + return nvkm_ior_new_(&gm200_sor, disp, SOR, id, hda & BIT(id)); +} + +static const struct nvkm_disp_func gm200_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gm200_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .dac = { .cnt = gf119_dac_cnt, .new = gf119_dac_new }, .sor = { .cnt = gf119_sor_cnt, .new = gm200_sor_new }, + .root = { 0,0,GM200_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GM200_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gm200_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gm200_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gm200_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c index af0ca812a394..7172a9dfd89b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp100.c @@ -21,27 +21,67 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_ior_func +gp100_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gf119_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gk104_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &gm200_sor_dp, + .hda = &gf119_sor_hda, +}; + +int +gp100_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x10ebb0) >> 8; + + return nvkm_ior_new_(&gp100_sor, disp, SOR, id, hda & BIT(id)); +} + +static const struct nvkm_disp_func gp100_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gf119_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gp100_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .sor = { .cnt = gf119_sor_cnt, .new = gp100_sor_new }, + .root = { 0,0,GP100_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gf119_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gf119_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gf119_disp_base }, + {{0,0,GP100_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gk104_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gk104_disp_ovly }, + {} + }, }; int gp100_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gp100_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gp100_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c index 065fea1bdfd1..07e9aeec5e08 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gp102.c @@ -21,16 +21,133 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" + +#include <subdev/timer.h> + +#include <nvif/class.h> + +static int +gp102_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x611494 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x611498 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61149c + (ctrl * 0x0010), 0x00000001); + nvkm_mask(device, 0x610490 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610490 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init: %08x\n", user, + nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +gp102_disp_dmac_func = { + .push = nv50_disp_dmac_push, + .init = gp102_disp_dmac_init, + .fini = gf119_disp_dmac_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_curs = { + .func = &gf119_disp_pioc_func, + .ctrl = 13, + .user = 17, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_oimm = { + .func = &gf119_disp_pioc_func, + .ctrl = 9, + .user = 13, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_ovly = { + .func = &gp102_disp_dmac_func, + .ctrl = 5, + .user = 5, + .mthd = &gk104_disp_ovly_mthd, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_base = { + .func = &gp102_disp_dmac_func, + .ctrl = 1, + .user = 1, + .mthd = &gf119_disp_base_mthd, +}; + +static int +gp102_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x611494, chan->push); + nvkm_wr32(device, 0x611498, 0x00010000); + nvkm_wr32(device, 0x61149c, 0x00000001); + nvkm_mask(device, 0x610490, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610490, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610490) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610490)); + return -EBUSY; + } + + return 0; +} + +static const struct nvkm_disp_chan_func +gp102_disp_core_func = { + .push = nv50_disp_dmac_push, + .init = gp102_disp_core_init, + .fini = gf119_disp_core_fini, + .intr = gf119_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = gf119_disp_dmac_bind, +}; + +static const struct nvkm_disp_chan_user +gp102_disp_core = { + .func = &gp102_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &gk104_disp_core_mthd, +}; static void -gp102_disp_intr_error(struct nv50_disp *disp, int chid) +gp102_disp_intr_error(struct nvkm_disp *disp, int chid) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 mthd = nvkm_rd32(device, 0x6111f0 + (chid * 12)); u32 data = nvkm_rd32(device, 0x6111f4 + (chid * 12)); @@ -53,22 +170,31 @@ gp102_disp_intr_error(struct nv50_disp *disp, int chid) nvkm_wr32(device, 0x6111f0 + (chid * 12), 0x90000000); } -static const struct nv50_disp_func +static const struct nvkm_disp_func gp102_disp = { + .oneinit = nv50_disp_oneinit, .init = gf119_disp_init, .fini = gf119_disp_fini, .intr = gf119_disp_intr, .intr_error = gp102_disp_intr_error, - .uevent = &gf119_disp_chan_uevent, .super = gf119_disp_super, - .root = &gp102_disp_root_oclass, + .uevent = &gf119_disp_chan_uevent, .head = { .cnt = gf119_head_cnt, .new = gf119_head_new }, .sor = { .cnt = gf119_sor_cnt, .new = gp100_sor_new }, + .root = { 0,0,GP102_DISP }, + .user = { + {{0,0,GK104_DISP_CURSOR }, nvkm_disp_chan_new, &gp102_disp_curs }, + {{0,0,GK104_DISP_OVERLAY }, nvkm_disp_chan_new, &gp102_disp_oimm }, + {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &gp102_disp_base }, + {{0,0,GP102_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gp102_disp_core }, + {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, nvkm_disp_chan_new, &gp102_disp_ovly }, + {} + }, }; int gp102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gp102_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gp102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c index 22bc269df64a..6f69c4e3ade2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt200.c @@ -21,28 +21,89 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_disp_mthd_list +gt200_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x6109a0 }, + { 0x0088, 0x6109c0 }, + { 0x008c, 0x6109c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00b0, 0x610c98 }, + { 0x00b4, 0x610ca4 }, + { 0x00b8, 0x610cac }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gt200_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, >200_disp_ovly_mthd_base }, + {} + } +}; + +const struct nvkm_disp_chan_user +gt200_disp_ovly = { + .func = &nv50_disp_dmac_func, + .ctrl = 3, + .user = 3, + .mthd = >200_disp_ovly_mthd, +}; + +static const struct nvkm_disp_func gt200_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = >200_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = nv50_sor_cnt, .new = g84_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT200_DISP }, + .user = { + {{0,0, G82_DISP_CURSOR }, nvkm_disp_chan_new, & nv50_disp_curs }, + {{0,0, G82_DISP_OVERLAY }, nvkm_disp_chan_new, & nv50_disp_oimm }, + {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT200_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g84_disp_core }, + {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, >200_disp_ovly }, + {} + }, }; int gt200_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(>200_disp, device, type, inst, pdisp); + return nvkm_disp_new_(>200_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c index 63a912b174d7..70c49e7af9cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gt215.c @@ -21,28 +21,188 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <subdev/timer.h> + +#include <nvif/class.h> + +static void +gt215_sor_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 soff = ior->id * 0x800; + int i; + + for (i = 0; i < size; i++) + nvkm_wr32(device, 0x61c440 + soff, (i << 8) | data[i]); + for (; i < 0x60; i++) + nvkm_wr32(device, 0x61c440 + soff, (i << 8)); + nvkm_mask(device, 0x61c448 + soff, 0x80000002, 0x80000002); +} + +static void +gt215_sor_hda_hpd(struct nvkm_ior *ior, int head, bool present) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + u32 data = 0x80000000; + u32 mask = 0x80000001; + if (present) + data |= 0x00000001; + else + mask |= 0x00000002; + nvkm_mask(device, 0x61c448 + ior->id * 0x800, mask, data); +} + +const struct nvkm_ior_func_hda +gt215_sor_hda = { + .hpd = gt215_sor_hda_hpd, + .eld = gt215_sor_hda_eld, +}; + +void +gt215_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x61c1e0 + soff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c1e0 + soff) & 0x80000000)) + break; + ); +} + +static const struct nvkm_ior_func_dp +gt215_sor_dp = { + .lanes = { 2, 1, 0, 3 }, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio = gt215_sor_dp_audio, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, +}; + +void +gt215_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + 0x1f000000 /* ??? */ | + max_ac_packet << 16 | + rekey; + const u32 soff = nv50_ior_base(ior); + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x61c53c + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame */ + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x61c528 + soff, avi_infoframe.header); + nvkm_wr32(device, 0x61c52c + soff, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x61c530 + soff, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x61c534 + soff, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x61c538 + soff, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); + } + + /* Audio InfoFrame */ + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x61c508 + soff, 0x000a0184); + nvkm_wr32(device, 0x61c50c + soff, 0x00000071); + nvkm_wr32(device, 0x61c510 + soff, 0x00000000); + nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001); + + /* Vendor InfoFrame */ + nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000); + if (vendor_size) { + nvkm_wr32(device, 0x61c544 + soff, vendor_infoframe.header); + nvkm_wr32(device, 0x61c548 + soff, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x61c54c + soff, vendor_infoframe.subpack0_high); + /* Is there a second (or up to fourth?) set of subpack registers here? */ + /* nvkm_wr32(device, 0x61c550 + soff, vendor_infoframe.subpack1_low); */ + /* nvkm_wr32(device, 0x61c554 + soff, vendor_infoframe.subpack1_high); */ + nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001); + } + + nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ + nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ + nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ + + /* ??? */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ + nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ + nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ + + /* HDMI_CTRL */ + nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl); +} + +static const struct nvkm_ior_func +gt215_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = gt215_sor_hdmi_ctrl, + }, + .dp = >215_sor_dp, + .hda = >215_sor_hda, +}; + +static int +gt215_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(>215_sor, disp, SOR, id, true); +} + +static const struct nvkm_disp_func gt215_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = >215_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = g94_sor_cnt, .new = gt215_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT214_DISP }, + .user = { + {{0,0,GT214_DISP_CURSOR }, nvkm_disp_chan_new, & nv50_disp_curs }, + {{0,0,GT214_DISP_OVERLAY }, nvkm_disp_chan_new, & nv50_disp_oimm }, + {{0,0,GT214_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT214_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g94_disp_core }, + {{0,0,GT214_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, & g84_disp_ovly }, + {} + }, }; int gt215_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(>215_disp, device, type, inst, pdisp); + return nvkm_disp_new_(>215_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c index 53879d5271cf..6b9d49270fa7 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/gv100.c @@ -19,84 +19,862 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" +#include "hdmi.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" +#include "outp.h" +#include <core/client.h> #include <core/gpuobj.h> +#include <core/ramht.h> #include <subdev/timer.h> +#include <nvif/class.h> +#include <nvif/unpack.h> + +static void +gv100_sor_hda_device_entry(struct nvkm_ior *ior, int head) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + + nvkm_mask(device, 0x616528 + hoff, 0x00000070, head << 4); +} + +const struct nvkm_ior_func_hda +gv100_sor_hda = { + .hpd = gf119_sor_hda_hpd, + .eld = gf119_sor_hda_eld, + .device_entry = gv100_sor_hda_device_entry, +}; + +void +gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark); +} + +void +gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x616568 + hoff, 0x0000ffff, h); + nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v); +} + +void +gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = 0x800 * head; + const u32 data = 0x80000000 | (0x00000001 * enable); + const u32 mask = 0x8000000d; + + nvkm_mask(device, 0x616560 + hoff, mask, data); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x616560 + hoff) & 0x80000000)) + break; + ); +} + +static const struct nvkm_ior_func_dp +gv100_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = gf119_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, +}; + +void +gv100_sor_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, + u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) +{ + struct nvkm_device *device = ior->disp->engine.subdev.device; + const u32 ctrl = 0x40000000 * enable | + max_ac_packet << 16 | + rekey; + const u32 hoff = head * 0x800; + const u32 hdmi = head * 0x400; + struct packed_hdmi_infoframe avi_infoframe; + struct packed_hdmi_infoframe vendor_infoframe; + + pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); + pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); + + if (!(ctrl & 0x40000000)) { + nvkm_mask(device, 0x6165c0 + hoff, 0x40000000, 0x00000000); + nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); + return; + } + + /* AVI InfoFrame (AVI). */ + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); + if (avi_size) { + nvkm_wr32(device, 0x6f0008 + hdmi, avi_infoframe.header); + nvkm_wr32(device, 0x6f000c + hdmi, avi_infoframe.subpack0_low); + nvkm_wr32(device, 0x6f0010 + hdmi, avi_infoframe.subpack0_high); + nvkm_wr32(device, 0x6f0014 + hdmi, avi_infoframe.subpack1_low); + nvkm_wr32(device, 0x6f0018 + hdmi, avi_infoframe.subpack1_high); + nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000001); + } + + /* Vendor-specific InfoFrame (VSI). */ + nvkm_mask(device, 0x6f0100 + hdmi, 0x00010001, 0x00000000); + if (vendor_size) { + nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); + nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); + nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); + nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0120 + hdmi, 0x00000000); + nvkm_wr32(device, 0x6f0124 + hdmi, 0x00000000); + nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000001); + } + + + /* General Control (GCP). */ + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); + nvkm_wr32(device, 0x6f00cc + hdmi, 0x00000010); + nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); + + /* Audio Clock Regeneration (ACR). */ + nvkm_wr32(device, 0x6f0080 + hdmi, 0x82000000); + + /* NV_PDISP_SF_HDMI_CTRL. */ + nvkm_mask(device, 0x6165c0 + hoff, 0x401f007f, ctrl); +} + +void +gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = (state == &sor->arm) * 0x8000 + sor->id * 0x20; + u32 ctrl = nvkm_rd32(device, 0x680300 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + case 8: state->proto = DP; state->link = 1; break; + case 9: state->proto = DP; state->link = 2; break; + default: + state->proto = UNKNOWN; + break; + } + + state->head = ctrl & 0x000000ff; +} + +static const struct nvkm_ior_func +gv100_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &gv100_sor_dp, + .hda = &gv100_sor_hda, +}; + +static int +gv100_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda; + + if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) + hda = nvkm_rd32(device, 0x118fb0) >> 8; + + return nvkm_ior_new_(&gv100_sor, disp, SOR, id, hda & BIT(id)); +} + +int +gv100_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610060) & 0x0000ff00) >> 8; + return (nvkm_rd32(device, 0x610074) & 0x00000f00) >> 8; +} + +static void +gv100_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000000); +} + +static void +gv100_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000004); +} + +static void +gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + /* vline read locks hline. */ + *vline = nvkm_rd32(device, 0x616330 + hoff) & 0x0000ffff; + *hline = nvkm_rd32(device, 0x616334 + hoff) & 0x0000ffff; +} + +static void +gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = (state == &head->arm) * 0x8000 + head->id * 0x400; + u32 data; + + data = nvkm_rd32(device, 0x682064 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x682068 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x68206c + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x682070 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + state->hz = nvkm_rd32(device, 0x68200c + hoff); + + data = nvkm_rd32(device, 0x682004 + hoff); + switch ((data & 0x000000f0) >> 4) { + case 5: state->or.depth = 30; break; + case 4: state->or.depth = 24; break; + case 1: state->or.depth = 18; break; + default: + state->or.depth = 18; + WARN_ON(1); + break; + } +} + +static const struct nvkm_head_func +gv100_head = { + .state = gv100_head_state, + .rgpos = gv100_head_rgpos, + .rgclk = gf119_head_rgclk, + .vblank_get = gv100_head_vblank_get, + .vblank_put = gv100_head_vblank_put, +}; + +int +gv100_head_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + if (!(nvkm_rd32(device, 0x610060) & (0x00000001 << id))) + return 0; + + return nvkm_head_new_(&gv100_head, disp, id); +} + +int +gv100_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = nvkm_rd32(device, 0x610060) & 0x000000ff; + return nvkm_rd32(device, 0x610074) & 0x0000000f; +} + +const struct nvkm_event_func +gv100_disp_chan_uevent = { +}; + +u64 +gv100_disp_chan_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x1000; + return 0x690000 + ((chan->chid.user - 1) * 0x1000); +} + +static int +gv100_disp_dmac_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 soff = (chan->chid.ctrl - 1) * 0x04; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610664 + soff); + if ((stat & 0x000f0000) == 0x00040000) + return 0; + ); + return -EBUSY; +} + +int +gv100_disp_dmac_bind(struct nvkm_disp_chan *chan, + struct nvkm_object *object, u32 handle) +{ + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -9, handle, + chan->chid.user << 25 | 0x00000040); +} + +void +gv100_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; + const u32 coff = chan->chid.ctrl * 0x04; + nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000000); + gv100_disp_dmac_idle(chan); + nvkm_mask(device, 0x6104e0 + coff, 0x00000002, 0x00000000); + chan->suspend_put = nvkm_rd32(device, 0x690000 + uoff); +} + +int +gv100_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + const u32 uoff = (chan->chid.ctrl - 1) * 0x1000; + const u32 poff = chan->chid.ctrl * 0x10; + const u32 coff = chan->chid.ctrl * 0x04; + + nvkm_wr32(device, 0x610b24 + poff, lower_32_bits(chan->push)); + nvkm_wr32(device, 0x610b20 + poff, upper_32_bits(chan->push)); + nvkm_wr32(device, 0x610b28 + poff, 0x00000001); + nvkm_wr32(device, 0x610b2c + poff, 0x00000040); + + nvkm_mask(device, 0x6104e0 + coff, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x690000 + uoff, chan->suspend_put); + nvkm_wr32(device, 0x6104e0 + coff, 0x00000013); + return gv100_disp_dmac_idle(chan); +} + +static void +gv100_disp_wimm_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611da8, mask, data); +} + +static const struct nvkm_disp_chan_func +gv100_disp_wimm_func = { + .push = nv50_disp_dmac_push, + .init = gv100_disp_dmac_init, + .fini = gv100_disp_dmac_fini, + .intr = gv100_disp_wimm_intr, + .user = gv100_disp_chan_user, +}; + +const struct nvkm_disp_chan_user +gv100_disp_wimm = { + .func = &gv100_disp_wimm_func, + .ctrl = 33, + .user = 33, +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_wndw_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0200, 0x690200 }, + { 0x020c, 0x69020c }, + { 0x0210, 0x690210 }, + { 0x0214, 0x690214 }, + { 0x0218, 0x690218 }, + { 0x021c, 0x69021c }, + { 0x0220, 0x690220 }, + { 0x0224, 0x690224 }, + { 0x0228, 0x690228 }, + { 0x022c, 0x69022c }, + { 0x0230, 0x690230 }, + { 0x0234, 0x690234 }, + { 0x0238, 0x690238 }, + { 0x0240, 0x690240 }, + { 0x0244, 0x690244 }, + { 0x0248, 0x690248 }, + { 0x024c, 0x69024c }, + { 0x0250, 0x690250 }, + { 0x0254, 0x690254 }, + { 0x0260, 0x690260 }, + { 0x0264, 0x690264 }, + { 0x0268, 0x690268 }, + { 0x026c, 0x69026c }, + { 0x0270, 0x690270 }, + { 0x0274, 0x690274 }, + { 0x0280, 0x690280 }, + { 0x0284, 0x690284 }, + { 0x0288, 0x690288 }, + { 0x028c, 0x69028c }, + { 0x0290, 0x690290 }, + { 0x0298, 0x690298 }, + { 0x029c, 0x69029c }, + { 0x02a0, 0x6902a0 }, + { 0x02a4, 0x6902a4 }, + { 0x02a8, 0x6902a8 }, + { 0x02ac, 0x6902ac }, + { 0x02b0, 0x6902b0 }, + { 0x02b4, 0x6902b4 }, + { 0x02b8, 0x6902b8 }, + { 0x02bc, 0x6902bc }, + { 0x02c0, 0x6902c0 }, + { 0x02c4, 0x6902c4 }, + { 0x02c8, 0x6902c8 }, + { 0x02cc, 0x6902cc }, + { 0x02d0, 0x6902d0 }, + { 0x02d4, 0x6902d4 }, + { 0x02d8, 0x6902d8 }, + { 0x02dc, 0x6902dc }, + { 0x02e0, 0x6902e0 }, + { 0x02e4, 0x6902e4 }, + { 0x02e8, 0x6902e8 }, + { 0x02ec, 0x6902ec }, + { 0x02f0, 0x6902f0 }, + { 0x02f4, 0x6902f4 }, + { 0x02f8, 0x6902f8 }, + { 0x02fc, 0x6902fc }, + { 0x0300, 0x690300 }, + { 0x0304, 0x690304 }, + { 0x0308, 0x690308 }, + { 0x0310, 0x690310 }, + { 0x0314, 0x690314 }, + { 0x0318, 0x690318 }, + { 0x031c, 0x69031c }, + { 0x0320, 0x690320 }, + { 0x0324, 0x690324 }, + { 0x0328, 0x690328 }, + { 0x032c, 0x69032c }, + { 0x033c, 0x69033c }, + { 0x0340, 0x690340 }, + { 0x0344, 0x690344 }, + { 0x0348, 0x690348 }, + { 0x034c, 0x69034c }, + { 0x0350, 0x690350 }, + { 0x0354, 0x690354 }, + { 0x0358, 0x690358 }, + { 0x0364, 0x690364 }, + { 0x0368, 0x690368 }, + { 0x036c, 0x69036c }, + { 0x0370, 0x690370 }, + { 0x0374, 0x690374 }, + { 0x0380, 0x690380 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gv100_disp_wndw_mthd = { + .name = "Window", + .addr = 0x001000, + .prev = 0x000800, + .data = { + { "Global", 1, &gv100_disp_wndw_mthd_base }, + {} + } +}; + +static void +gv100_disp_wndw_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611da4, mask, data); +} + +static const struct nvkm_disp_chan_func +gv100_disp_wndw_func = { + .push = nv50_disp_dmac_push, + .init = gv100_disp_dmac_init, + .fini = gv100_disp_dmac_fini, + .intr = gv100_disp_wndw_intr, + .user = gv100_disp_chan_user, + .bind = gv100_disp_dmac_bind, +}; + +const struct nvkm_disp_chan_user +gv100_disp_wndw = { + .func = &gv100_disp_wndw_func, + .ctrl = 1, + .user = 1, + .mthd = &gv100_disp_wndw_mthd, +}; + int gv100_disp_wndw_cnt(struct nvkm_disp *disp, unsigned long *pmask) { struct nvkm_device *device = disp->engine.subdev.device; + *pmask = nvkm_rd32(device, 0x610064); return (nvkm_rd32(device, 0x610074) & 0x03f00000) >> 20; } +static int +gv100_disp_curs_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 soff = (chan->chid.ctrl - 1) * 0x04; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610664 + soff); + if ((stat & 0x00070000) == 0x00040000) + return 0; + ); + return -EBUSY; +} + +static void +gv100_disp_curs_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00010000 << chan->head; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611dac, mask, data); +} + +static void +gv100_disp_curs_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 hoff = chan->chid.ctrl * 4; + nvkm_mask(device, 0x6104e0 + hoff, 0x00000010, 0x00000010); + gv100_disp_curs_idle(chan); + nvkm_mask(device, 0x6104e0 + hoff, 0x00000001, 0x00000000); +} + +static int +gv100_disp_curs_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + nvkm_wr32(device, 0x6104e0 + chan->chid.ctrl * 4, 0x00000001); + return gv100_disp_curs_idle(chan); +} + +static const struct nvkm_disp_chan_func +gv100_disp_curs_func = { + .init = gv100_disp_curs_init, + .fini = gv100_disp_curs_fini, + .intr = gv100_disp_curs_intr, + .user = gv100_disp_chan_user, +}; + +const struct nvkm_disp_chan_user +gv100_disp_curs = { + .func = &gv100_disp_curs_func, + .ctrl = 73, + .user = 73, +}; + +const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0200, 0x680200 }, + { 0x0208, 0x680208 }, + { 0x020c, 0x68020c }, + { 0x0210, 0x680210 }, + { 0x0214, 0x680214 }, + { 0x0218, 0x680218 }, + { 0x021c, 0x68021c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_sor = { + .mthd = 0x0020, + .addr = 0x000020, + .data = { + { 0x0300, 0x680300 }, + { 0x0304, 0x680304 }, + { 0x0308, 0x680308 }, + { 0x030c, 0x68030c }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_wndw = { + .mthd = 0x0080, + .addr = 0x000080, + .data = { + { 0x1000, 0x681000 }, + { 0x1004, 0x681004 }, + { 0x1008, 0x681008 }, + { 0x100c, 0x68100c }, + { 0x1010, 0x681010 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +gv100_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000400, + .data = { + { 0x2000, 0x682000 }, + { 0x2004, 0x682004 }, + { 0x2008, 0x682008 }, + { 0x200c, 0x68200c }, + { 0x2014, 0x682014 }, + { 0x2018, 0x682018 }, + { 0x201c, 0x68201c }, + { 0x2020, 0x682020 }, + { 0x2028, 0x682028 }, + { 0x202c, 0x68202c }, + { 0x2030, 0x682030 }, + { 0x2038, 0x682038 }, + { 0x203c, 0x68203c }, + { 0x2048, 0x682048 }, + { 0x204c, 0x68204c }, + { 0x2050, 0x682050 }, + { 0x2054, 0x682054 }, + { 0x2058, 0x682058 }, + { 0x205c, 0x68205c }, + { 0x2060, 0x682060 }, + { 0x2064, 0x682064 }, + { 0x2068, 0x682068 }, + { 0x206c, 0x68206c }, + { 0x2070, 0x682070 }, + { 0x2074, 0x682074 }, + { 0x2078, 0x682078 }, + { 0x207c, 0x68207c }, + { 0x2080, 0x682080 }, + { 0x2088, 0x682088 }, + { 0x2090, 0x682090 }, + { 0x209c, 0x68209c }, + { 0x20a0, 0x6820a0 }, + { 0x20a4, 0x6820a4 }, + { 0x20a8, 0x6820a8 }, + { 0x20ac, 0x6820ac }, + { 0x2180, 0x682180 }, + { 0x2184, 0x682184 }, + { 0x218c, 0x68218c }, + { 0x2194, 0x682194 }, + { 0x2198, 0x682198 }, + { 0x219c, 0x68219c }, + { 0x21a0, 0x6821a0 }, + { 0x21a4, 0x6821a4 }, + { 0x2214, 0x682214 }, + { 0x2218, 0x682218 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +gv100_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x008000, + .data = { + { "Global", 1, &gv100_disp_core_mthd_base }, + { "SOR", 4, &gv100_disp_core_mthd_sor }, + { "WINDOW", 8, &gv100_disp_core_mthd_wndw }, + { "HEAD", 4, &gv100_disp_core_mthd_head }, + {} + } +}; + +static int +gv100_disp_core_idle(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + nvkm_msec(device, 2000, + u32 stat = nvkm_rd32(device, 0x610630); + if ((stat & 0x001f0000) == 0x000b0000) + return 0; + ); + return -EBUSY; +} + +static u64 +gv100_disp_core_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x10000; + return 0x680000; +} + +static void +gv100_disp_core_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00000001; + const u32 data = en ? mask : 0; + nvkm_mask(device, 0x611dac, mask, data); +} + +static void +gv100_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000000); + gv100_disp_core_idle(chan); + nvkm_mask(device, 0x6104e0, 0x00000002, 0x00000000); + chan->suspend_put = nvkm_rd32(device, 0x680000); +} + +static int +gv100_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + nvkm_wr32(device, 0x610b24, lower_32_bits(chan->push)); + nvkm_wr32(device, 0x610b20, upper_32_bits(chan->push)); + nvkm_wr32(device, 0x610b28, 0x00000001); + nvkm_wr32(device, 0x610b2c, 0x00000040); + + nvkm_mask(device, 0x6104e0, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x680000, chan->suspend_put); + nvkm_wr32(device, 0x6104e0, 0x00000013); + return gv100_disp_core_idle(chan); +} + +static const struct nvkm_disp_chan_func +gv100_disp_core_func = { + .push = nv50_disp_dmac_push, + .init = gv100_disp_core_init, + .fini = gv100_disp_core_fini, + .intr = gv100_disp_core_intr, + .user = gv100_disp_core_user, + .bind = gv100_disp_dmac_bind, +}; + +const struct nvkm_disp_chan_user +gv100_disp_core = { + .func = &gv100_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &gv100_disp_core_mthd, +}; + +#define gv100_disp_caps(p) container_of((p), struct gv100_disp_caps, object) + +struct gv100_disp_caps { + struct nvkm_object object; + struct nvkm_disp *disp; +}; + +static int +gv100_disp_caps_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) +{ + struct gv100_disp_caps *caps = gv100_disp_caps(object); + struct nvkm_device *device = caps->disp->engine.subdev.device; + *type = NVKM_OBJECT_MAP_IO; + *addr = 0x640000 + device->func->resource_addr(device, 0); + *size = 0x1000; + return 0; +} + +static const struct nvkm_object_func +gv100_disp_caps = { + .map = gv100_disp_caps_map, +}; + +int +gv100_disp_caps_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + struct gv100_disp_caps *caps; + + if (!(caps = kzalloc(sizeof(*caps), GFP_KERNEL))) + return -ENOMEM; + *pobject = &caps->object; + + nvkm_object_ctor(&gv100_disp_caps, oclass, &caps->object); + caps->disp = disp; + return 0; +} + void gv100_disp_super(struct work_struct *work) { - struct nv50_disp *disp = - container_of(work, struct nv50_disp, supervisor); - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_disp *disp = container_of(work, struct nvkm_disp, super.work); + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_head *head; - u32 stat = nvkm_rd32(device, 0x6107a8); - u32 mask[4]; + u32 stat, mask[4]; + + mutex_lock(&disp->super.mutex); + stat = nvkm_rd32(device, 0x6107a8); - nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super), stat); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_debug(subdev, "supervisor %d: %08x\n", ffs(disp->super.pending), stat); + list_for_each_entry(head, &disp->heads, head) { mask[head->id] = nvkm_rd32(device, 0x6107ac + (head->id * 4)); HEAD_DBG(head, "%08x", mask[head->id]); } - if (disp->super & 0x00000001) { + if (disp->super.pending & 0x00000001) { nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); nv50_disp_super_1(disp); - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_1_0(disp, head); } } else - if (disp->super & 0x00000002) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000002) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_2_0(disp, head); } - nvkm_outp_route(&disp->base); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_outp_route(disp); + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00010000)) continue; nv50_disp_super_2_1(disp, head); } - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_2_2(disp, head); } } else - if (disp->super & 0x00000004) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000004) { + list_for_each_entry(head, &disp->heads, head) { if (!(mask[head->id] & 0x00001000)) continue; nv50_disp_super_3_0(disp, head); } } - list_for_each_entry(head, &disp->base.head, head) + list_for_each_entry(head, &disp->heads, head) nvkm_wr32(device, 0x6107ac + (head->id * 4), 0x00000000); + nvkm_wr32(device, 0x6107a8, 0x80000000); + mutex_unlock(&disp->super.mutex); } static void -gv100_disp_exception(struct nv50_disp *disp, int chid) +gv100_disp_exception(struct nvkm_disp *disp, int chid) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611020 + (chid * 12)); u32 type = (stat & 0x00007000) >> 12; @@ -136,16 +914,16 @@ gv100_disp_exception(struct nv50_disp *disp, int chid) } static void -gv100_disp_intr_ctrl_disp(struct nv50_disp *disp) +gv100_disp_intr_ctrl_disp(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611c30); if (stat & 0x00000007) { - disp->super = (stat & 0x00000007); - queue_work(disp->wq, &disp->supervisor); - nvkm_wr32(device, 0x611860, disp->super); + disp->super.pending = (stat & 0x00000007); + queue_work(disp->super.wq, &disp->super.work); + nvkm_wr32(device, 0x611860, disp->super.pending); stat &= ~0x00000007; } @@ -184,9 +962,9 @@ gv100_disp_intr_ctrl_disp(struct nv50_disp *disp) } static void -gv100_disp_intr_exc_other(struct nv50_disp *disp) +gv100_disp_intr_exc_other(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611854); unsigned long mask; @@ -213,9 +991,9 @@ gv100_disp_intr_exc_other(struct nv50_disp *disp) } static void -gv100_disp_intr_exc_winim(struct nv50_disp *disp) +gv100_disp_intr_exc_winim(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; unsigned long stat = nvkm_rd32(device, 0x611850); int wndw; @@ -233,9 +1011,9 @@ gv100_disp_intr_exc_winim(struct nv50_disp *disp) } static void -gv100_disp_intr_exc_win(struct nv50_disp *disp) +gv100_disp_intr_exc_win(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; unsigned long stat = nvkm_rd32(device, 0x61184c); int wndw; @@ -253,9 +1031,9 @@ gv100_disp_intr_exc_win(struct nv50_disp *disp) } static void -gv100_disp_intr_head_timing(struct nv50_disp *disp, int head) +gv100_disp_intr_head_timing(struct nvkm_disp *disp, int head) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611800 + (head * 0x04)); @@ -266,7 +1044,7 @@ gv100_disp_intr_head_timing(struct nv50_disp *disp, int head) } if (stat & 0x00000004) { - nvkm_disp_vblank(&disp->base, head); + nvkm_disp_vblank(disp, head); nvkm_wr32(device, 0x611800 + (head * 0x04), 0x00000004); stat &= ~0x00000004; } @@ -278,9 +1056,9 @@ gv100_disp_intr_head_timing(struct nv50_disp *disp, int head) } void -gv100_disp_intr(struct nv50_disp *disp) +gv100_disp_intr(struct nvkm_disp *disp) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 stat = nvkm_rd32(device, 0x611ec0); unsigned long mask; @@ -318,16 +1096,16 @@ gv100_disp_intr(struct nv50_disp *disp) } void -gv100_disp_fini(struct nv50_disp *disp) +gv100_disp_fini(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; nvkm_wr32(device, 0x611db0, 0x00000000); } static int -gv100_disp_init(struct nv50_disp *disp) +gv100_disp_init(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_head *head; int i, j; u32 tmp; @@ -354,7 +1132,7 @@ gv100_disp_init(struct nv50_disp *disp) } /* Head capabilities. */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const int id = head->id; /* RG. */ @@ -414,7 +1192,7 @@ gv100_disp_init(struct nv50_disp *disp) nvkm_wr32(device, 0x611da4, 0x00000000); /* EN. */ /* HEAD_TIMING(n): VBLANK. */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 4; nvkm_wr32(device, 0x611cc0 + hoff, 0x00000004); /* MSK. */ nvkm_wr32(device, 0x611d80 + hoff, 0x00000000); /* EN. */ @@ -426,23 +1204,32 @@ gv100_disp_init(struct nv50_disp *disp) return 0; } -static const struct nv50_disp_func +static const struct nvkm_disp_func gv100_disp = { + .oneinit = nv50_disp_oneinit, .init = gv100_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, - .uevent = &gv100_disp_chan_uevent, .super = gv100_disp_super, - .root = &gv100_disp_root_oclass, + .uevent = &gv100_disp_chan_uevent, .wndw = { .cnt = gv100_disp_wndw_cnt }, .head = { .cnt = gv100_head_cnt, .new = gv100_head_new }, .sor = { .cnt = gv100_sor_cnt, .new = gv100_sor_new }, .ramht_size = 0x2000, + .root = { 0, 0,GV100_DISP }, + .user = { + {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, + {{ 0, 0,GV100_DISP_CURSOR }, nvkm_disp_chan_new, &gv100_disp_curs }, + {{ 0, 0,GV100_DISP_WINDOW_IMM_CHANNEL_DMA}, nvkm_disp_wndw_new, &gv100_disp_wimm }, + {{ 0, 0,GV100_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gv100_disp_core }, + {{ 0, 0,GV100_DISP_WINDOW_CHANNEL_DMA }, nvkm_disp_wndw_new, &gv100_disp_wndw }, + {} + }, }; int gv100_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&gv100_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&gv100_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c deleted file mode 100644 index 19d2d58344e4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagf119.c +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -void -gf119_hda_device_entry(struct nvkm_ior *ior, int head) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - nvkm_mask(device, 0x616548 + hoff, 0x00000070, head << 4); -} - -void -gf119_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = 0x030 * ior->id + (head * 0x04); - int i; - - for (i = 0; i < size; i++) - nvkm_wr32(device, 0x10ec00 + soff, (i << 8) | data[i]); - for (; i < 0x60; i++) - nvkm_wr32(device, 0x10ec00 + soff, (i << 8)); - nvkm_mask(device, 0x10ec10 + soff, 0x80000002, 0x80000002); -} - -void -gf119_hda_hpd(struct nvkm_ior *ior, int head, bool present) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = 0x030 * ior->id + (head * 0x04); - u32 data = 0x80000000; - u32 mask = 0x80000001; - if (present) { - ior->func->hda.device_entry(ior, head); - data |= 0x00000001; - } else { - mask |= 0x00000002; - } - nvkm_mask(device, 0x10ec10 + soff, mask, data); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c deleted file mode 100644 index 0d1b81fe1093..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagt215.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -void -gt215_hda_eld(struct nvkm_ior *ior, int head, u8 *data, u8 size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = ior->id * 0x800; - int i; - - for (i = 0; i < size; i++) - nvkm_wr32(device, 0x61c440 + soff, (i << 8) | data[i]); - for (; i < 0x60; i++) - nvkm_wr32(device, 0x61c440 + soff, (i << 8)); - nvkm_mask(device, 0x61c448 + soff, 0x80000002, 0x80000002); -} - -void -gt215_hda_hpd(struct nvkm_ior *ior, int head, bool present) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - u32 data = 0x80000000; - u32 mask = 0x80000001; - if (present) - data |= 0x00000001; - else - mask |= 0x00000002; - nvkm_mask(device, 0x61c448 + ior->id * 0x800, mask, data); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c deleted file mode 100644 index 57d374ecfeef..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdagv100.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright 2020 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -void -gv100_hda_device_entry(struct nvkm_ior *ior, int head) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - nvkm_mask(device, 0x616528 + hoff, 0x00000070, head << 4); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c deleted file mode 100644 index 661410f9b457..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmig84.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -g84_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - 0x1f000000 /* ??? */ | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x6165a4 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x61653c + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x616528 + hoff, avi_infoframe.header); - nvkm_wr32(device, 0x61652c + hoff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x616530 + hoff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x616534 + hoff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x616538 + hoff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x616520 + hoff, 0x00000001, 0x00000001); - } - - /* Audio InfoFrame */ - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x616508 + hoff, 0x000a0184); - nvkm_wr32(device, 0x61650c + hoff, 0x00000071); - nvkm_wr32(device, 0x616510 + hoff, 0x00000000); - nvkm_mask(device, 0x616500 + hoff, 0x00000001, 0x00000001); - - /* Vendor InfoFrame */ - nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010000); - if (vendor_size) { - nvkm_wr32(device, 0x616544 + hoff, vendor_infoframe.header); - nvkm_wr32(device, 0x616548 + hoff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x61654c + hoff, vendor_infoframe.subpack0_high); - /* Is there a second (or up to fourth?) set of subpack registers here? */ - /* nvkm_wr32(device, 0x616550 + hoff, vendor_infoframe->subpack1_low); */ - /* nvkm_wr32(device, 0x616554 + hoff, vendor_infoframe->subpack1_high); */ - nvkm_mask(device, 0x61653c + hoff, 0x00010001, 0x00010001); - } - - nvkm_mask(device, 0x6165d0 + hoff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - nvkm_mask(device, 0x616568 + hoff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - nvkm_mask(device, 0x616578 + hoff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ - - /* ??? */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ - - /* HDMI_CTRL */ - nvkm_mask(device, 0x6165a4 + hoff, 0x5f1f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c deleted file mode 100644 index 6cac0e72b4cc..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigf119.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gf119_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x61671c + hoff, avi_infoframe.header); - nvkm_wr32(device, 0x616720 + hoff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x616724 + hoff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x616728 + hoff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x61672c + hoff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x616714 + hoff, 0x00000001, 0x00000001); - } - - /* GENERIC(?) / Vendor InfoFrame? */ - nvkm_mask(device, 0x616730 + hoff, 0x00010001, 0x00010000); - if (vendor_size) { - /* - * These appear to be the audio infoframe registers, - * but no other set of infoframe registers has yet - * been found. - */ - nvkm_wr32(device, 0x616738 + hoff, vendor_infoframe.header); - nvkm_wr32(device, 0x61673c + hoff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x616740 + hoff, vendor_infoframe.subpack0_high); - /* Is there a second (or further?) set of subpack registers here? */ - nvkm_mask(device, 0x616730 + hoff, 0x00000001, 0x00000001); - } - - /* ??? InfoFrame? */ - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6167ac + hoff, 0x00000010); - nvkm_mask(device, 0x6167a4 + hoff, 0x00000001, 0x00000001); - - /* HDMI_CTRL */ - nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c deleted file mode 100644 index ed0a6100d76b..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigk104.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2014 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gk104_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - const u32 hdmi = head * 0x400; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x616798 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x690008 + hdmi, avi_infoframe.header); - nvkm_wr32(device, 0x69000c + hdmi, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x690010 + hdmi, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x690014 + hdmi, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x690018 + hdmi, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x690000 + hdmi, 0x00000001, 0x00000001); - } - - /* GENERIC(?) / Vendor InfoFrame? */ - nvkm_mask(device, 0x690100 + hdmi, 0x00010001, 0x00000000); - if (vendor_size) { - nvkm_wr32(device, 0x690108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x69010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x690110 + hdmi, vendor_infoframe.subpack0_high); - /* Is there a second (or further?) set of subpack registers here? */ - nvkm_mask(device, 0x690100 + hdmi, 0x00000001, 0x00000001); - } - - - /* ??? InfoFrame? */ - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6900cc + hdmi, 0x00000010); - nvkm_mask(device, 0x6900c0 + hdmi, 0x00000001, 0x00000001); - - /* ??? */ - nvkm_wr32(device, 0x690080 + hdmi, 0x82000000); - - /* HDMI_CTRL */ - nvkm_mask(device, 0x616798 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c deleted file mode 100644 index bb32befa6ad4..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigm200.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2018 Ilia Mirkin - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ilia Mirkin - */ -#include "hdmi.h" - -void -gm200_hdmi_scdc(struct nvkm_ior *ior, u8 scdc) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(ior); - const u32 ctrl = scdc & 0x3; - - nvkm_mask(device, 0x61c5bc + soff, 0x00000003, ctrl); - - ior->tmds.high_speed = !!(scdc & 0x2); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c deleted file mode 100644 index 0993d223bb9c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigt215.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "hdmi.h" - -void -gt215_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - 0x1f000000 /* ??? */ | - max_ac_packet << 16 | - rekey; - const u32 soff = nv50_ior_base(ior); - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x61c5a4 + soff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x61c53c + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame */ - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x61c528 + soff, avi_infoframe.header); - nvkm_wr32(device, 0x61c52c + soff, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x61c530 + soff, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x61c534 + soff, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x61c538 + soff, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x61c520 + soff, 0x00000001, 0x00000001); - } - - /* Audio InfoFrame */ - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x61c508 + soff, 0x000a0184); - nvkm_wr32(device, 0x61c50c + soff, 0x00000071); - nvkm_wr32(device, 0x61c510 + soff, 0x00000000); - nvkm_mask(device, 0x61c500 + soff, 0x00000001, 0x00000001); - - /* Vendor InfoFrame */ - nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010000); - if (vendor_size) { - nvkm_wr32(device, 0x61c544 + soff, vendor_infoframe.header); - nvkm_wr32(device, 0x61c548 + soff, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x61c54c + soff, vendor_infoframe.subpack0_high); - /* Is there a second (or up to fourth?) set of subpack registers here? */ - /* nvkm_wr32(device, 0x61c550 + soff, vendor_infoframe.subpack1_low); */ - /* nvkm_wr32(device, 0x61c554 + soff, vendor_infoframe.subpack1_high); */ - nvkm_mask(device, 0x61c53c + soff, 0x00010001, 0x00010001); - } - - nvkm_mask(device, 0x61c5d0 + soff, 0x00070001, 0x00010001); /* SPARE, HW_CTS */ - nvkm_mask(device, 0x61c568 + soff, 0x00010101, 0x00000000); /* ACR_CTRL, ?? */ - nvkm_mask(device, 0x61c578 + soff, 0x80000000, 0x80000000); /* ACR_0441_ENABLE */ - - /* ??? */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00100000); /* RESETF */ - nvkm_mask(device, 0x61733c, 0x10000000, 0x10000000); /* LOOKUP_EN */ - nvkm_mask(device, 0x61733c, 0x00100000, 0x00000000); /* !RESETF */ - - /* HDMI_CTRL */ - nvkm_mask(device, 0x61c5a4 + soff, 0x5f1f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c deleted file mode 100644 index 3ff49344abc7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/hdmigv100.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "hdmi.h" - -void -gv100_hdmi_ctrl(struct nvkm_ior *ior, int head, bool enable, u8 max_ac_packet, - u8 rekey, u8 *avi, u8 avi_size, u8 *vendor, u8 vendor_size) -{ - struct nvkm_device *device = ior->disp->engine.subdev.device; - const u32 ctrl = 0x40000000 * enable | - max_ac_packet << 16 | - rekey; - const u32 hoff = head * 0x800; - const u32 hdmi = head * 0x400; - struct packed_hdmi_infoframe avi_infoframe; - struct packed_hdmi_infoframe vendor_infoframe; - - pack_hdmi_infoframe(&avi_infoframe, avi, avi_size); - pack_hdmi_infoframe(&vendor_infoframe, vendor, vendor_size); - - if (!(ctrl & 0x40000000)) { - nvkm_mask(device, 0x6165c0 + hoff, 0x40000000, 0x00000000); - nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); - return; - } - - /* AVI InfoFrame (AVI). */ - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000000); - if (avi_size) { - nvkm_wr32(device, 0x6f0008 + hdmi, avi_infoframe.header); - nvkm_wr32(device, 0x6f000c + hdmi, avi_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0010 + hdmi, avi_infoframe.subpack0_high); - nvkm_wr32(device, 0x6f0014 + hdmi, avi_infoframe.subpack1_low); - nvkm_wr32(device, 0x6f0018 + hdmi, avi_infoframe.subpack1_high); - nvkm_mask(device, 0x6f0000 + hdmi, 0x00000001, 0x00000001); - } - - /* Vendor-specific InfoFrame (VSI). */ - nvkm_mask(device, 0x6f0100 + hdmi, 0x00010001, 0x00000000); - if (vendor_size) { - nvkm_wr32(device, 0x6f0108 + hdmi, vendor_infoframe.header); - nvkm_wr32(device, 0x6f010c + hdmi, vendor_infoframe.subpack0_low); - nvkm_wr32(device, 0x6f0110 + hdmi, vendor_infoframe.subpack0_high); - nvkm_wr32(device, 0x6f0114 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0118 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f011c + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0120 + hdmi, 0x00000000); - nvkm_wr32(device, 0x6f0124 + hdmi, 0x00000000); - nvkm_mask(device, 0x6f0100 + hdmi, 0x00000001, 0x00000001); - } - - - /* General Control (GCP). */ - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000000); - nvkm_wr32(device, 0x6f00cc + hdmi, 0x00000010); - nvkm_mask(device, 0x6f00c0 + hdmi, 0x00000001, 0x00000001); - - /* Audio Clock Regeneration (ACR). */ - nvkm_wr32(device, 0x6f0080 + hdmi, 0x82000000); - - /* NV_PDISP_SF_HDMI_CTRL. */ - nvkm_mask(device, 0x6165c0 + hoff, 0x401f007f, ctrl); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c index 5c557f3e6c2c..83152c26fe3e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.c @@ -32,7 +32,7 @@ struct nvkm_head * nvkm_head_find(struct nvkm_disp *disp, int id) { struct nvkm_head *head; - list_for_each_entry(head, &disp->head, head) { + list_for_each_entry(head, &disp->heads, head) { if (head->id == id) return head; } @@ -99,7 +99,7 @@ nvkm_head_new_(const struct nvkm_head_func *func, head->func = func; head->disp = disp; head->id = id; - list_add_tail(&head->head, &disp->head); + list_add_tail(&head->head, &disp->heads); HEAD_DBG(head, "ctor"); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h index 7dde6237441d..84a2989193cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/head.h @@ -42,19 +42,9 @@ struct nvkm_head_func { void (*vblank_put)(struct nvkm_head *); }; -void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); - -#define HEAD_MSG(h,l,f,a...) do { \ - struct nvkm_head *_h = (h); \ - nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ -} while(0) -#define HEAD_WARN(h,f,a...) HEAD_MSG((h), warn, f, ##a) -#define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a) - -int nv04_head_new(struct nvkm_disp *, int id); - int nv50_head_cnt(struct nvkm_disp *, unsigned long *); int nv50_head_new(struct nvkm_disp *, int id); +void nv50_head_rgpos(struct nvkm_head *, u16 *, u16 *); int gf119_head_cnt(struct nvkm_disp *, unsigned long *); int gf119_head_new(struct nvkm_disp *, int id); @@ -62,4 +52,11 @@ void gf119_head_rgclk(struct nvkm_head *, int); int gv100_head_cnt(struct nvkm_disp *, unsigned long *); int gv100_head_new(struct nvkm_disp *, int id); + +#define HEAD_MSG(h,l,f,a...) do { \ + struct nvkm_head *_h = (h); \ + nvkm_##l(&_h->disp->engine.subdev, "head-%d: "f"\n", _h->id, ##a); \ +} while(0) +#define HEAD_WARN(h,f,a...) HEAD_MSG((h), warn, f, ##a) +#define HEAD_DBG(h,f,a...) HEAD_MSG((h), debug, f, ##a) #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c deleted file mode 100644 index e86298b35902..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgf119.c +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -gf119_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000000); -} - -static void -gf119_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - nvkm_mask(device, 0x6100c0 + hoff, 0x00000001, 0x00000001); -} - -void -gf119_head_rgclk(struct nvkm_head *head, int div) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x612200 + (head->id * 0x800), 0x0000000f, div); -} - -static void -gf119_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = (state == &head->asy) * 0x20000 + head->id * 0x300; - u32 data; - - data = nvkm_rd32(device, 0x640414 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x640418 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x64041c + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x640420 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - state->hz = nvkm_rd32(device, 0x640450 + hoff); - - data = nvkm_rd32(device, 0x640404 + hoff); - switch ((data & 0x000003c0) >> 6) { - case 6: state->or.depth = 30; break; - case 5: state->or.depth = 24; break; - case 2: state->or.depth = 18; break; - case 0: state->or.depth = 18; break; /*XXX: "default" */ - default: - state->or.depth = 18; - WARN_ON(1); - break; - } -} - -static const struct nvkm_head_func -gf119_head = { - .state = gf119_head_state, - .rgpos = nv50_head_rgpos, - .rgclk = gf119_head_rgclk, - .vblank_get = gf119_head_vblank_get, - .vblank_put = gf119_head_vblank_put, -}; - -int -gf119_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&gf119_head, disp, id); -} - -int -gf119_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = nvkm_rd32(device, 0x612004) & 0x0000000f; - return nvkm_rd32(device, 0x022448); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c deleted file mode 100644 index 1a061b42ae5c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headgv100.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "head.h" - -static void -gv100_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000000); -} - -static void -gv100_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x611d80 + (head->id * 4), 0x00000004, 0x00000004); -} - -static void -gv100_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - /* vline read locks hline. */ - *vline = nvkm_rd32(device, 0x616330 + hoff) & 0x0000ffff; - *hline = nvkm_rd32(device, 0x616334 + hoff) & 0x0000ffff; -} - -static void -gv100_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = (state == &head->arm) * 0x8000 + head->id * 0x400; - u32 data; - - data = nvkm_rd32(device, 0x682064 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x682068 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x68206c + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x682070 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - state->hz = nvkm_rd32(device, 0x68200c + hoff); - - data = nvkm_rd32(device, 0x682004 + hoff); - switch ((data & 0x000000f0) >> 4) { - case 5: state->or.depth = 30; break; - case 4: state->or.depth = 24; break; - case 1: state->or.depth = 18; break; - default: - state->or.depth = 18; - WARN_ON(1); - break; - } -} - -static const struct nvkm_head_func -gv100_head = { - .state = gv100_head_state, - .rgpos = gv100_head_rgpos, - .rgclk = gf119_head_rgclk, - .vblank_get = gv100_head_vblank_get, - .vblank_put = gv100_head_vblank_put, -}; - -int -gv100_head_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - if (!(nvkm_rd32(device, 0x610060) & (0x00000001 << id))) - return 0; - return nvkm_head_new_(&gv100_head, disp, id); -} - -int -gv100_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = nvkm_rd32(device, 0x610060) & 0x000000ff; - return nvkm_rd32(device, 0x610074) & 0x0000000f; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c deleted file mode 100644 index dcf459282aa1..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv04.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -nv04_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000000); -} - -static void -nv04_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001); -} - -static void -nv04_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - u32 data = nvkm_rd32(device, 0x600868 + (head->id * 0x2000)); - *hline = (data & 0xffff0000) >> 16; - *vline = (data & 0x0000ffff); -} - -static void -nv04_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x0200; - state->vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0x0000ffff; - state->vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0x0000ffff; - state->vblanke = state->vtotal - 1; - state->hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0x0000ffff; - state->htotal = nvkm_rd32(device, 0x680824 + hoff) & 0x0000ffff; - state->hblanke = state->htotal - 1; -} - -static const struct nvkm_head_func -nv04_head = { - .state = nv04_head_state, - .rgpos = nv04_head_rgpos, - .vblank_get = nv04_head_vblank_get, - .vblank_put = nv04_head_vblank_put, -}; - -int -nv04_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&nv04_head, disp, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c deleted file mode 100644 index e7d5c397cd29..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/headnv50.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "head.h" - -static void -nv50_head_vblank_put(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x61002c, (4 << head->id), 0); -} - -static void -nv50_head_vblank_get(struct nvkm_head *head) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id)); -} - -static void -nv50_head_rgclk(struct nvkm_head *head, int div) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - nvkm_mask(device, 0x614200 + (head->id * 0x800), 0x0000000f, div); -} - -void -nv50_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x800; - /* vline read locks hline. */ - *vline = nvkm_rd32(device, 0x616340 + hoff) & 0x0000ffff; - *hline = nvkm_rd32(device, 0x616344 + hoff) & 0x0000ffff; -} - -static void -nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) -{ - struct nvkm_device *device = head->disp->engine.subdev.device; - const u32 hoff = head->id * 0x540 + (state == &head->arm) * 4; - u32 data; - - data = nvkm_rd32(device, 0x610ae8 + hoff); - state->vblanke = (data & 0xffff0000) >> 16; - state->hblanke = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610af0 + hoff); - state->vblanks = (data & 0xffff0000) >> 16; - state->hblanks = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610af8 + hoff); - state->vtotal = (data & 0xffff0000) >> 16; - state->htotal = (data & 0x0000ffff); - data = nvkm_rd32(device, 0x610b00 + hoff); - state->vsynce = (data & 0xffff0000) >> 16; - state->hsynce = (data & 0x0000ffff); - state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000; -} - -static const struct nvkm_head_func -nv50_head = { - .state = nv50_head_state, - .rgpos = nv50_head_rgpos, - .rgclk = nv50_head_rgclk, - .vblank_get = nv50_head_vblank_get, - .vblank_put = nv50_head_vblank_put, -}; - -int -nv50_head_new(struct nvkm_disp *disp, int id) -{ - return nvkm_head_new_(&nv50_head, disp, id); -} - -int -nv50_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - *pmask = 3; - return 2; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c index a475ea56795c..e420bf2e4330 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.c @@ -34,7 +34,7 @@ struct nvkm_ior * nvkm_ior_find(struct nvkm_disp *disp, enum nvkm_ior_type type, int id) { struct nvkm_ior *ior; - list_for_each_entry(ior, &disp->ior, head) { + list_for_each_entry(ior, &disp->iors, head) { if (ior->type == type && (id < 0 || ior->id == id)) return ior; } @@ -55,7 +55,7 @@ nvkm_ior_del(struct nvkm_ior **pior) int nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *disp, - enum nvkm_ior_type type, int id) + enum nvkm_ior_type type, int id, bool hda) { struct nvkm_ior *ior; if (!(ior = kzalloc(sizeof(*ior), GFP_KERNEL))) @@ -64,9 +64,9 @@ nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *disp, ior->disp = disp; ior->type = type; ior->id = id; - snprintf(ior->name, sizeof(ior->name), "%s-%d", - nvkm_ior_name[ior->type], ior->id); - list_add_tail(&ior->head, &disp->ior); + ior->hda = hda; + snprintf(ior->name, sizeof(ior->name), "%s-%d", nvkm_ior_name[ior->type], ior->id); + list_add_tail(&ior->head, &disp->iors); IOR_DBG(ior, "ctor"); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h index 9f0bb7c6b010..671c4674ffcc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -13,6 +13,7 @@ struct nvkm_ior { PIOR, } type; int id; + bool hda; char name[8]; struct list_head head; @@ -69,7 +70,7 @@ struct nvkm_ior_func { void (*scdc)(struct nvkm_ior *, u8 scdc); } hdmi; - struct { + const struct nvkm_ior_func_dp { u8 lanes[4]; int (*links)(struct nvkm_ior *, struct nvkm_i2c_aux *); void (*power)(struct nvkm_ior *, int nr); @@ -83,17 +84,17 @@ struct nvkm_ior_func { void (*activesym)(struct nvkm_ior *, int head, u8 TU, u8 VTUa, u8 VTUf, u8 VTUi); void (*watermark)(struct nvkm_ior *, int head, u8 watermark); - } dp; + } *dp; - struct { + const struct nvkm_ior_func_hda { void (*hpd)(struct nvkm_ior *, int head, bool present); void (*eld)(struct nvkm_ior *, int head, u8 *data, u8 size); void (*device_entry)(struct nvkm_ior *, int head); - } hda; + } *hda; }; int nvkm_ior_new_(const struct nvkm_ior_func *func, struct nvkm_disp *, - enum nvkm_ior_type type, int id); + enum nvkm_ior_type type, int id, bool hda); void nvkm_ior_del(struct nvkm_ior **); struct nvkm_ior *nvkm_ior_find(struct nvkm_disp *, enum nvkm_ior_type, int id); @@ -103,10 +104,13 @@ nv50_ior_base(struct nvkm_ior *ior) return ior->id * 0x800; } +int nv50_dac_cnt(struct nvkm_disp *, unsigned long *); +int nv50_dac_new(struct nvkm_disp *, int); void nv50_dac_power(struct nvkm_ior *, bool, bool, bool, bool, bool); int nv50_dac_sense(struct nvkm_ior *, u32); -void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl); +int gf119_dac_cnt(struct nvkm_disp *, unsigned long *); +int gf119_dac_new(struct nvkm_disp *, int); static inline u32 nv50_sor_link(struct nvkm_ior *ior) @@ -114,11 +118,17 @@ nv50_sor_link(struct nvkm_ior *ior) return nv50_ior_base(ior) + ((ior->asy.link == 2) * 0x80); } +int nv50_sor_cnt(struct nvkm_disp *, unsigned long *); void nv50_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); void nv50_sor_power(struct nvkm_ior *, bool, bool, bool, bool, bool); void nv50_sor_clock(struct nvkm_ior *); +int g84_sor_new(struct nvkm_disp *, int); +void g84_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); + +int g94_sor_cnt(struct nvkm_disp *, unsigned long *); void g94_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); +extern const struct nvkm_ior_func_dp g94_sor_dp; int g94_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *); void g94_sor_dp_power(struct nvkm_ior *, int); void g94_sor_dp_pattern(struct nvkm_ior *, int); @@ -127,47 +137,50 @@ void g94_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void g94_sor_dp_activesym(struct nvkm_ior *, int, u8, u8, u8, u8); void g94_sor_dp_watermark(struct nvkm_ior *, int, u8); +void gt215_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gt215_sor_dp_audio(struct nvkm_ior *, int, bool); +extern const struct nvkm_ior_func_hda gt215_sor_hda; +int gf119_sor_cnt(struct nvkm_disp *, unsigned long *); void gf119_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); void gf119_sor_clock(struct nvkm_ior *); +extern const struct nvkm_ior_func_dp gf119_sor_dp; int gf119_sor_dp_links(struct nvkm_ior *, struct nvkm_i2c_aux *); -void gf119_sor_dp_pattern(struct nvkm_ior *, int); void gf119_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int); void gf119_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16); void gf119_sor_dp_audio(struct nvkm_ior *, int, bool); void gf119_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void gf119_sor_dp_watermark(struct nvkm_ior *, int, u8); +extern const struct nvkm_ior_func_hda gf119_sor_hda; +void gf119_sor_hda_hpd(struct nvkm_ior *, int, bool); +void gf119_sor_hda_eld(struct nvkm_ior *, int, u8 *, u8); + +int gk104_sor_new(struct nvkm_disp *, int); +void gk104_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gm107_sor_dp_pattern(struct nvkm_ior *, int); void gm200_sor_route_set(struct nvkm_outp *, struct nvkm_ior *); int gm200_sor_route_get(struct nvkm_outp *, int *); +void gm200_sor_hdmi_scdc(struct nvkm_ior *, u8); +extern const struct nvkm_ior_func_dp gm200_sor_dp; void gm200_sor_dp_drive(struct nvkm_ior *, int, int, int, int, int); +int gp100_sor_new(struct nvkm_disp *, int); + +int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); void gv100_sor_state(struct nvkm_ior *, struct nvkm_ior_state *); +void gv100_sor_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); void gv100_sor_dp_audio(struct nvkm_ior *, int, bool); void gv100_sor_dp_audio_sym(struct nvkm_ior *, int, u16, u32); void gv100_sor_dp_watermark(struct nvkm_ior *, int, u8); +extern const struct nvkm_ior_func_hda gv100_sor_hda; void tu102_sor_dp_vcpi(struct nvkm_ior *, int, u8, u8, u16, u16); -void g84_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gt215_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gf119_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gk104_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); -void gv100_hdmi_ctrl(struct nvkm_ior *, int, bool, u8, u8, u8 *, u8 , u8 *, u8); - -void gm200_hdmi_scdc(struct nvkm_ior *, u8); - -void gt215_hda_hpd(struct nvkm_ior *, int, bool); -void gt215_hda_eld(struct nvkm_ior *, int, u8 *, u8); - -void gf119_hda_hpd(struct nvkm_ior *, int, bool); -void gf119_hda_eld(struct nvkm_ior *, int, u8 *, u8); -void gf119_hda_device_entry(struct nvkm_ior *, int); - -void gv100_hda_device_entry(struct nvkm_ior *, int); +int nv50_pior_cnt(struct nvkm_disp *, unsigned long *); +int nv50_pior_new(struct nvkm_disp *, int); +void nv50_pior_depth(struct nvkm_ior *, struct nvkm_ior_state *, u32 ctrl); #define IOR_MSG(i,l,f,a...) do { \ struct nvkm_ior *_ior = (i); \ @@ -175,40 +188,4 @@ void gv100_hda_device_entry(struct nvkm_ior *, int); } while(0) #define IOR_WARN(i,f,a...) IOR_MSG((i), warn, f, ##a) #define IOR_DBG(i,f,a...) IOR_MSG((i), debug, f, ##a) - -int nv50_dac_cnt(struct nvkm_disp *, unsigned long *); -int nv50_dac_new(struct nvkm_disp *, int); - -int gf119_dac_cnt(struct nvkm_disp *, unsigned long *); -int gf119_dac_new(struct nvkm_disp *, int); - -int nv50_pior_cnt(struct nvkm_disp *, unsigned long *); -int nv50_pior_new(struct nvkm_disp *, int); - -int nv50_sor_cnt(struct nvkm_disp *, unsigned long *); -int nv50_sor_new(struct nvkm_disp *, int); - -int g84_sor_new(struct nvkm_disp *, int); - -int g94_sor_cnt(struct nvkm_disp *, unsigned long *); -int g94_sor_new(struct nvkm_disp *, int); - -int mcp77_sor_new(struct nvkm_disp *, int); -int gt215_sor_new(struct nvkm_disp *, int); -int mcp89_sor_new(struct nvkm_disp *, int); - -int gf119_sor_cnt(struct nvkm_disp *, unsigned long *); -int gf119_sor_new(struct nvkm_disp *, int); - -int gk104_sor_new(struct nvkm_disp *, int); -int gm107_sor_new(struct nvkm_disp *, int); -int gm200_sor_new(struct nvkm_disp *, int); -int gp100_sor_new(struct nvkm_disp *, int); - -int gv100_sor_cnt(struct nvkm_disp *, unsigned long *); -int gv100_sor_new(struct nvkm_disp *, int); - -int tu102_sor_new(struct nvkm_disp *, int); - -int ga102_sor_new(struct nvkm_disp *, int); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c index 762a59f24bbb..916b1d477b0b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp77.c @@ -19,28 +19,56 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_ior_func +mcp77_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = g84_sor_hdmi_ctrl, + }, + .dp = &g94_sor_dp, +}; + +static int +mcp77_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&mcp77_sor, disp, SOR, id, false); +} + +static const struct nvkm_disp_func mcp77_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = &g94_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = g94_sor_cnt, .new = mcp77_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT206_DISP }, + .user = { + {{0,0, G82_DISP_CURSOR }, nvkm_disp_chan_new, & nv50_disp_curs }, + {{0,0, G82_DISP_OVERLAY }, nvkm_disp_chan_new, & nv50_disp_oimm }, + {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT206_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g94_disp_core }, + {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, >200_disp_ovly }, + {} + }, }; int mcp77_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&mcp77_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&mcp77_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c index e5c58aae15de..a5a0b9439374 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/mcp89.c @@ -19,28 +19,70 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "rootnv50.h" -static const struct nv50_disp_func +#include <nvif/class.h> + +static const struct nvkm_ior_func_dp +mcp89_sor_dp = { + .lanes = { 3, 2, 1, 0 }, + .links = g94_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = g94_sor_dp_pattern, + .drive = g94_sor_dp_drive, + .audio = gt215_sor_dp_audio, + .audio_sym = g94_sor_dp_audio_sym, + .activesym = g94_sor_dp_activesym, + .watermark = g94_sor_dp_watermark, +}; + +static const struct nvkm_ior_func +mcp89_sor = { + .state = g94_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, + .hdmi = { + .ctrl = gt215_sor_hdmi_ctrl, + }, + .dp = &mcp89_sor_dp, + .hda = >215_sor_hda, +}; + +static int +mcp89_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&mcp89_sor, disp, SOR, id, true); +} + +static const struct nvkm_disp_func mcp89_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = >215_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = g94_sor_cnt, .new = mcp89_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0,0,GT214_DISP }, + .user = { + {{0,0,GT214_DISP_CURSOR }, nvkm_disp_chan_new, &nv50_disp_curs }, + {{0,0,GT214_DISP_OVERLAY }, nvkm_disp_chan_new, &nv50_disp_oimm }, + {{0,0,GT214_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, & g84_disp_base }, + {{0,0,GT214_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, & g94_disp_core }, + {{0,0,GT214_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, & g84_disp_ovly }, + {} + }, }; int mcp89_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&mcp89_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&mcp89_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c index a12097db2c2a..e4cf11a33969 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv04.c @@ -24,10 +24,56 @@ #include "priv.h" #include "head.h" -static const struct nvkm_disp_oclass * -nv04_disp_root(struct nvkm_disp *disp) +#include <nvif/class.h> + +static void +nv04_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000000); +} + +static void +nv04_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + nvkm_wr32(device, 0x600140 + (head->id * 0x2000) , 0x00000001); +} + +static void +nv04_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + u32 data = nvkm_rd32(device, 0x600868 + (head->id * 0x2000)); + *hline = (data & 0xffff0000) >> 16; + *vline = (data & 0x0000ffff); +} + +static void +nv04_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x0200; + state->vblanks = nvkm_rd32(device, 0x680800 + hoff) & 0x0000ffff; + state->vtotal = nvkm_rd32(device, 0x680804 + hoff) & 0x0000ffff; + state->vblanke = state->vtotal - 1; + state->hblanks = nvkm_rd32(device, 0x680820 + hoff) & 0x0000ffff; + state->htotal = nvkm_rd32(device, 0x680824 + hoff) & 0x0000ffff; + state->hblanke = state->htotal - 1; +} + +static const struct nvkm_head_func +nv04_head = { + .state = nv04_head_state, + .rgpos = nv04_head_rgpos, + .vblank_get = nv04_head_vblank_get, + .vblank_put = nv04_head_vblank_put, +}; + +static int +nv04_head_new(struct nvkm_disp *disp, int id) { - return &nv04_disp_root_oclass; + return nvkm_head_new_(&nv04_head, disp, id); } static void @@ -60,7 +106,8 @@ nv04_disp_intr(struct nvkm_disp *disp) static const struct nvkm_disp_func nv04_disp = { .intr = nv04_disp_intr, - .root = nv04_disp_root, + .root = { 0, 0, NV04_DISP }, + .user = { {} }, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c index 3f20e49070ce..a46e13cc9ff1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.c @@ -21,11 +21,11 @@ * * Authors: Ben Skeggs */ -#include "nv50.h" +#include "priv.h" +#include "chan.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" +#include "outp.h" #include <core/client.h> #include <core/ramht.h> @@ -34,150 +34,948 @@ #include <subdev/bios/init.h> #include <subdev/bios/pll.h> #include <subdev/devinit.h> +#include <subdev/i2c.h> +#include <subdev/mmu.h> #include <subdev/timer.h> -static const struct nvkm_disp_oclass * -nv50_disp_root_(struct nvkm_disp *base) +#include <nvif/class.h> +#include <nvif/unpack.h> + +static void +nv50_pior_clock(struct nvkm_ior *pior) { - return nv50_disp(base)->func->root; + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 poff = nv50_ior_base(pior); + + nvkm_mask(device, 0x614380 + poff, 0x00000707, 0x00000001); } +static int +nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux) +{ + int ret = nvkm_i2c_aux_lnk_ctl(aux, pior->dp.nr, pior->dp.bw, pior->dp.ef); + if (ret) + return ret; + + return 1; +} + +static const struct nvkm_ior_func_dp +nv50_pior_dp = { + .links = nv50_pior_dp_links, +}; + static void -nv50_disp_intr_(struct nvkm_disp *base) +nv50_pior_power_wait(struct nvkm_device *device, u32 poff) { - struct nv50_disp *disp = nv50_disp(base); - disp->func->intr(disp); + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61e004 + poff) & 0x80000000)) + break; + ); } static void -nv50_disp_fini_(struct nvkm_disp *base) +nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu, bool data, bool vsync, bool hsync) { - struct nv50_disp *disp = nv50_disp(base); - disp->func->fini(disp); + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 poff = nv50_ior_base(pior); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; + const u32 field = 0x80000000 | (0x00000101 << shift); + + nv50_pior_power_wait(device, poff); + nvkm_mask(device, 0x61e004 + poff, field, state); + nv50_pior_power_wait(device, poff); } -static int -nv50_disp_init_(struct nvkm_disp *base) +void +nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl) { - struct nv50_disp *disp = nv50_disp(base); - return disp->func->init(disp); + /* GF119 moves this information to per-head methods, which is + * a lot more convenient, and where our shared code expect it. + */ + if (state->head && state == &ior->asy) { + struct nvkm_head *head = nvkm_head_find(ior->disp, __ffs(state->head)); + + if (!WARN_ON(!head)) { + struct nvkm_head_state *state = &head->asy; + switch ((ctrl & 0x000f0000) >> 16) { + case 6: state->or.depth = 30; break; + case 5: state->or.depth = 24; break; + case 2: state->or.depth = 18; break; + case 0: state->or.depth = 18; break; /*XXX*/ + default: + state->or.depth = 18; + WARN_ON(1); + break; + } + } + } } -static void * -nv50_disp_dtor_(struct nvkm_disp *base) +static void +nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) { - struct nv50_disp *disp = nv50_disp(base); + struct nvkm_device *device = pior->disp->engine.subdev.device; + const u32 coff = pior->id * 8 + (state == &pior->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b80 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + state->rgdiv = 1; + switch (state->proto_evo) { + case 0: state->proto = TMDS; break; + default: + state->proto = UNKNOWN; + break; + } - nvkm_ramht_del(&disp->ramht); - nvkm_gpuobj_del(&disp->inst); + state->head = ctrl & 0x00000003; + nv50_pior_depth(pior, state, ctrl); +} - nvkm_event_fini(&disp->uevent); - if (disp->wq) - destroy_workqueue(disp->wq); +static const struct nvkm_ior_func +nv50_pior = { + .state = nv50_pior_state, + .power = nv50_pior_power, + .clock = nv50_pior_clock, + .dp = &nv50_pior_dp, +}; - return disp; +int +nv50_pior_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&nv50_pior, disp, PIOR, id, false); } -static int -nv50_disp_oneinit_(struct nvkm_disp *base) +int +nv50_pior_cnt(struct nvkm_disp *disp, unsigned long *pmask) { - struct nv50_disp *disp = nv50_disp(base); - const struct nv50_disp_func *func = disp->func; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ret, i; + struct nvkm_device *device = disp->engine.subdev.device; - if (func->wndw.cnt) { - disp->wndw.nr = func->wndw.cnt(&disp->base, &disp->wndw.mask); - nvkm_debug(subdev, "Window(s): %d (%08lx)\n", - disp->wndw.nr, disp->wndw.mask); + *pmask = (nvkm_rd32(device, 0x610184) & 0x70000000) >> 28; + return 3; +} + +void +nv50_sor_clock(struct nvkm_ior *sor) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const int div = sor->asy.link == 3; + const u32 soff = nv50_ior_base(sor); + + nvkm_mask(device, 0x614300 + soff, 0x00000707, (div << 8) | div); +} + +static void +nv50_sor_power_wait(struct nvkm_device *device, u32 soff) +{ + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c004 + soff) & 0x80000000)) + break; + ); +} + +void +nv50_sor_power(struct nvkm_ior *sor, bool normal, bool pu, bool data, bool vsync, bool hsync) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; + const u32 field = 0x80000000 | (0x00000001 << shift); + + nv50_sor_power_wait(device, soff); + nvkm_mask(device, 0x61c004 + soff, field, state); + nv50_sor_power_wait(device, soff); + + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) + break; + ); +} + +void +nv50_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b70 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = LVDS; state->link = 1; break; + case 1: state->proto = TMDS; state->link = 1; break; + case 2: state->proto = TMDS; state->link = 2; break; + case 5: state->proto = TMDS; state->link = 3; break; + default: + state->proto = UNKNOWN; + break; } - disp->head.nr = func->head.cnt(&disp->base, &disp->head.mask); - nvkm_debug(subdev, " Head(s): %d (%02lx)\n", - disp->head.nr, disp->head.mask); - for_each_set_bit(i, &disp->head.mask, disp->head.nr) { - ret = func->head.new(&disp->base, i); - if (ret) - return ret; + state->head = ctrl & 0x00000003; +} + +static const struct nvkm_ior_func +nv50_sor = { + .state = nv50_sor_state, + .power = nv50_sor_power, + .clock = nv50_sor_clock, +}; + +static int +nv50_sor_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&nv50_sor, disp, SOR, id, false); +} + +int +nv50_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x03000000) >> 24; + return 2; +} + +static void +nv50_dac_clock(struct nvkm_ior *dac) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + + nvkm_mask(device, 0x614280 + doff, 0x07070707, 0x00000000); +} + +int +nv50_dac_sense(struct nvkm_ior *dac, u32 loadval) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + + dac->func->power(dac, false, true, false, false, false); + + nvkm_wr32(device, 0x61a00c + doff, 0x00100000 | loadval); + mdelay(9); + udelay(500); + loadval = nvkm_mask(device, 0x61a00c + doff, 0xffffffff, 0x00000000); + + dac->func->power(dac, false, false, false, false, false); + if (!(loadval & 0x80000000)) + return -ETIMEDOUT; + + return (loadval & 0x38000000) >> 27; +} + +static void +nv50_dac_power_wait(struct nvkm_device *device, const u32 doff) +{ + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x61a004 + doff) & 0x80000000)) + break; + ); +} + +void +nv50_dac_power(struct nvkm_ior *dac, bool normal, bool pu, bool data, bool vsync, bool hsync) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 doff = nv50_ior_base(dac); + const u32 shift = normal ? 0 : 16; + const u32 state = 0x80000000 | (0x00000040 * ! pu | + 0x00000010 * ! data | + 0x00000004 * ! vsync | + 0x00000001 * ! hsync) << shift; + const u32 field = 0xc0000000 | (0x00000055 << shift); + + nv50_dac_power_wait(device, doff); + nvkm_mask(device, 0x61a004 + doff, field, state); + nv50_dac_power_wait(device, doff); +} + +static void +nv50_dac_state(struct nvkm_ior *dac, struct nvkm_ior_state *state) +{ + struct nvkm_device *device = dac->disp->engine.subdev.device; + const u32 coff = dac->id * 8 + (state == &dac->arm) * 4; + u32 ctrl = nvkm_rd32(device, 0x610b58 + coff); + + state->proto_evo = (ctrl & 0x00000f00) >> 8; + switch (state->proto_evo) { + case 0: state->proto = CRT; break; + default: + state->proto = UNKNOWN; + break; } - if (func->dac.cnt) { - disp->dac.nr = func->dac.cnt(&disp->base, &disp->dac.mask); - nvkm_debug(subdev, " DAC(s): %d (%02lx)\n", - disp->dac.nr, disp->dac.mask); - for_each_set_bit(i, &disp->dac.mask, disp->dac.nr) { - ret = func->dac.new(&disp->base, i); - if (ret) - return ret; + state->head = ctrl & 0x00000003; +} + +static const struct nvkm_ior_func +nv50_dac = { + .state = nv50_dac_state, + .power = nv50_dac_power, + .sense = nv50_dac_sense, + .clock = nv50_dac_clock, +}; + +int +nv50_dac_new(struct nvkm_disp *disp, int id) +{ + return nvkm_ior_new_(&nv50_dac, disp, DAC, id, false); +} + +int +nv50_dac_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + struct nvkm_device *device = disp->engine.subdev.device; + + *pmask = (nvkm_rd32(device, 0x610184) & 0x00700000) >> 20; + return 3; +} + +static void +nv50_head_vblank_put(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x61002c, (4 << head->id), 0); +} + +static void +nv50_head_vblank_get(struct nvkm_head *head) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x61002c, (4 << head->id), (4 << head->id)); +} + +static void +nv50_head_rgclk(struct nvkm_head *head, int div) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + + nvkm_mask(device, 0x614200 + (head->id * 0x800), 0x0000000f, div); +} + +void +nv50_head_rgpos(struct nvkm_head *head, u16 *hline, u16 *vline) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x800; + + /* vline read locks hline. */ + *vline = nvkm_rd32(device, 0x616340 + hoff) & 0x0000ffff; + *hline = nvkm_rd32(device, 0x616344 + hoff) & 0x0000ffff; +} + +static void +nv50_head_state(struct nvkm_head *head, struct nvkm_head_state *state) +{ + struct nvkm_device *device = head->disp->engine.subdev.device; + const u32 hoff = head->id * 0x540 + (state == &head->arm) * 4; + u32 data; + + data = nvkm_rd32(device, 0x610ae8 + hoff); + state->vblanke = (data & 0xffff0000) >> 16; + state->hblanke = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610af0 + hoff); + state->vblanks = (data & 0xffff0000) >> 16; + state->hblanks = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610af8 + hoff); + state->vtotal = (data & 0xffff0000) >> 16; + state->htotal = (data & 0x0000ffff); + data = nvkm_rd32(device, 0x610b00 + hoff); + state->vsynce = (data & 0xffff0000) >> 16; + state->hsynce = (data & 0x0000ffff); + state->hz = (nvkm_rd32(device, 0x610ad0 + hoff) & 0x003fffff) * 1000; +} + +static const struct nvkm_head_func +nv50_head = { + .state = nv50_head_state, + .rgpos = nv50_head_rgpos, + .rgclk = nv50_head_rgclk, + .vblank_get = nv50_head_vblank_get, + .vblank_put = nv50_head_vblank_put, +}; + +int +nv50_head_new(struct nvkm_disp *disp, int id) +{ + return nvkm_head_new_(&nv50_head, disp, id); +} + +int +nv50_head_cnt(struct nvkm_disp *disp, unsigned long *pmask) +{ + *pmask = 3; + return 2; +} + + +static void +nv50_disp_mthd_list(struct nvkm_disp *disp, int debug, u32 base, int c, + const struct nvkm_disp_mthd_list *list, int inst) +{ + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int i; + + for (i = 0; list->data[i].mthd; i++) { + if (list->data[i].addr) { + u32 next = nvkm_rd32(device, list->data[i].addr + base + 0); + u32 prev = nvkm_rd32(device, list->data[i].addr + base + c); + u32 mthd = list->data[i].mthd + (list->mthd * inst); + const char *name = list->data[i].name; + char mods[16]; + + if (prev != next) + snprintf(mods, sizeof(mods), "-> %08x", next); + else + snprintf(mods, sizeof(mods), "%13c", ' '); + + nvkm_printk_(subdev, debug, info, + "\t%04x: %08x %s%s%s\n", + mthd, prev, mods, name ? " // " : "", + name ? name : ""); } } +} - if (func->pior.cnt) { - disp->pior.nr = func->pior.cnt(&disp->base, &disp->pior.mask); - nvkm_debug(subdev, " PIOR(s): %d (%02lx)\n", - disp->pior.nr, disp->pior.mask); - for_each_set_bit(i, &disp->pior.mask, disp->pior.nr) { - ret = func->pior.new(&disp->base, i); - if (ret) - return ret; +void +nv50_disp_chan_mthd(struct nvkm_disp_chan *chan, int debug) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + const struct nvkm_disp_chan_mthd *mthd = chan->mthd; + const struct nvkm_disp_mthd_list *list; + int i, j; + + if (debug > subdev->debug) + return; + if (!mthd) + return; + + for (i = 0; (list = mthd->data[i].mthd) != NULL; i++) { + u32 base = chan->head * mthd->addr; + for (j = 0; j < mthd->data[i].nr; j++, base += list->addr) { + const char *cname = mthd->name; + const char *sname = ""; + char cname_[16], sname_[16]; + + if (mthd->addr) { + snprintf(cname_, sizeof(cname_), "%s %d", + mthd->name, chan->chid.user); + cname = cname_; + } + + if (mthd->data[i].nr > 1) { + snprintf(sname_, sizeof(sname_), " - %s %d", + mthd->data[i].name, j); + sname = sname_; + } + + nvkm_printk_(subdev, debug, info, "%s%s:\n", cname, sname); + nv50_disp_mthd_list(disp, debug, base, mthd->prev, + list, j); } } +} - disp->sor.nr = func->sor.cnt(&disp->base, &disp->sor.mask); - nvkm_debug(subdev, " SOR(s): %d (%02lx)\n", - disp->sor.nr, disp->sor.mask); - for_each_set_bit(i, &disp->sor.mask, disp->sor.nr) { - ret = func->sor.new(&disp->base, i); - if (ret) - return ret; +static void +nv50_disp_chan_uevent_fini(struct nvkm_event *event, int type, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000000 << index); + nvkm_wr32(device, 0x610020, 0x00000001 << index); +} + +static void +nv50_disp_chan_uevent_init(struct nvkm_event *event, int types, int index) +{ + struct nvkm_disp *disp = container_of(event, typeof(*disp), uevent); + struct nvkm_device *device = disp->engine.subdev.device; + nvkm_wr32(device, 0x610020, 0x00000001 << index); + nvkm_mask(device, 0x610028, 0x00000001 << index, 0x00000001 << index); +} + +void +nv50_disp_chan_uevent_send(struct nvkm_disp *disp, int chid) +{ + nvkm_event_send(&disp->uevent, NVKM_DISP_EVENT_CHAN_AWAKEN, chid, NULL, 0); +} + +const struct nvkm_event_func +nv50_disp_chan_uevent = { + .init = nv50_disp_chan_uevent_init, + .fini = nv50_disp_chan_uevent_fini, +}; + +u64 +nv50_disp_chan_user(struct nvkm_disp_chan *chan, u64 *psize) +{ + *psize = 0x1000; + return 0x640000 + (chan->chid.user * 0x1000); +} + +void +nv50_disp_chan_intr(struct nvkm_disp_chan *chan, bool en) +{ + struct nvkm_device *device = chan->disp->engine.subdev.device; + const u32 mask = 0x00010001 << chan->chid.user; + const u32 data = en ? 0x00010000 << chan->chid.user : 0x00000000; + nvkm_mask(device, 0x610028, mask, data); +} + +static void +nv50_disp_pioc_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); } +} - ret = nvkm_gpuobj_new(device, 0x10000, 0x10000, false, NULL, - &disp->inst); - if (ret) - return ret; +static int +nv50_disp_pioc_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_disp *disp = chan->disp; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; - return nvkm_ramht_new(device, func->ramht_size ? func->ramht_size : - 0x1000, 0, disp->inst, &disp->ramht); + nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout0: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; + } + + nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001); + if (nvkm_msec(device, 2000, + u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10)); + if ((tmp & 0x00030000) == 0x00010000) + break; + ) < 0) { + nvkm_error(subdev, "ch %d timeout1: %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; + } + + return 0; } -static const struct nvkm_disp_func -nv50_disp_ = { - .dtor = nv50_disp_dtor_, - .oneinit = nv50_disp_oneinit_, - .init = nv50_disp_init_, - .fini = nv50_disp_fini_, - .intr = nv50_disp_intr_, - .root = nv50_disp_root_, +const struct nvkm_disp_chan_func +nv50_disp_pioc_func = { + .init = nv50_disp_pioc_init, + .fini = nv50_disp_pioc_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, }; int -nv50_disp_new_(const struct nv50_disp_func *func, struct nvkm_device *device, - enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) +nv50_disp_dmac_bind(struct nvkm_disp_chan *chan, struct nvkm_object *object, u32 handle) { - struct nv50_disp *disp; - int ret; + return nvkm_ramht_insert(chan->disp->ramht, object, chan->chid.user, -10, handle, + chan->chid.user << 28 | chan->chid.user); +} - if (!(disp = kzalloc(sizeof(*disp), GFP_KERNEL))) - return -ENOMEM; - disp->func = func; - *pdisp = &disp->base; +static void +nv50_disp_dmac_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* deactivate channel */ + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00001010, 0x00001000); + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d fini timeout, %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + } - ret = nvkm_disp_ctor(&nv50_disp_, device, type, inst, &disp->base); - if (ret) - return ret; + chan->suspend_put = nvkm_rd32(device, 0x640000 + (ctrl * 0x1000)); +} + +static int +nv50_disp_dmac_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ctrl = chan->chid.ctrl; + int user = chan->chid.user; + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610204 + (ctrl * 0x0010), chan->push); + nvkm_wr32(device, 0x610208 + (ctrl * 0x0010), 0x00010000); + nvkm_wr32(device, 0x61020c + (ctrl * 0x0010), ctrl); + nvkm_mask(device, 0x610200 + (ctrl * 0x0010), 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000 + (ctrl * 0x1000), chan->suspend_put); + nvkm_wr32(device, 0x610200 + (ctrl * 0x0010), 0x00000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "ch %d init timeout, %08x\n", user, + nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); + return -EBUSY; + } - disp->wq = create_singlethread_workqueue("nvkm-disp"); - if (!disp->wq) - return -ENOMEM; + return 0; +} - INIT_WORK(&disp->supervisor, func->super); +int +nv50_disp_dmac_push(struct nvkm_disp_chan *chan, u64 object) +{ + chan->memory = nvkm_umem_search(chan->object.client, object); + if (IS_ERR(chan->memory)) + return PTR_ERR(chan->memory); + + if (nvkm_memory_size(chan->memory) < 0x1000) + return -EINVAL; + + switch (nvkm_memory_target(chan->memory)) { + case NVKM_MEM_TARGET_VRAM: chan->push = 0x00000001; break; + case NVKM_MEM_TARGET_NCOH: chan->push = 0x00000002; break; + case NVKM_MEM_TARGET_HOST: chan->push = 0x00000003; break; + default: + return -EINVAL; + } - return nvkm_event_init(func->uevent, 1, ARRAY_SIZE(disp->chan), - &disp->uevent); + chan->push |= nvkm_memory_addr(chan->memory) >> 8; + return 0; } +const struct nvkm_disp_chan_func +nv50_disp_dmac_func = { + .push = nv50_disp_dmac_push, + .init = nv50_disp_dmac_init, + .fini = nv50_disp_dmac_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = nv50_disp_dmac_bind, +}; + +const struct nvkm_disp_chan_user +nv50_disp_curs = { + .func = &nv50_disp_pioc_func, + .ctrl = 7, + .user = 7, +}; + +const struct nvkm_disp_chan_user +nv50_disp_oimm = { + .func = &nv50_disp_pioc_func, + .ctrl = 5, + .user = 5, +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_ovly_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0009a0 }, + { 0x0088, 0x0009c0 }, + { 0x008c, 0x0009c8 }, + { 0x0090, 0x6109b4 }, + { 0x0094, 0x610970 }, + { 0x00a0, 0x610998 }, + { 0x00a4, 0x610964 }, + { 0x00c0, 0x610958 }, + { 0x00e0, 0x6109a8 }, + { 0x00e4, 0x6109d0 }, + { 0x00e8, 0x6109d8 }, + { 0x0100, 0x61094c }, + { 0x0104, 0x610984 }, + { 0x0108, 0x61098c }, + { 0x0800, 0x6109f8 }, + { 0x0808, 0x610a08 }, + { 0x080c, 0x610a10 }, + { 0x0810, 0x610a00 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_ovly_mthd = { + .name = "Overlay", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_ovly_mthd_base }, + {} + } +}; + +static const struct nvkm_disp_chan_user +nv50_disp_ovly = { + .func = &nv50_disp_dmac_func, + .ctrl = 3, + .user = 3, + .mthd = &nv50_disp_ovly_mthd, +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_base_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x0008c4 }, + { 0x0088, 0x0008d0 }, + { 0x008c, 0x0008dc }, + { 0x0090, 0x0008e4 }, + { 0x0094, 0x610884 }, + { 0x00a0, 0x6108a0 }, + { 0x00a4, 0x610878 }, + { 0x00c0, 0x61086c }, + { 0x00e0, 0x610858 }, + { 0x00e4, 0x610860 }, + { 0x00e8, 0x6108ac }, + { 0x00ec, 0x6108b4 }, + { 0x0100, 0x610894 }, + { 0x0110, 0x6108bc }, + { 0x0114, 0x61088c }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_base_mthd_image = { + .mthd = 0x0400, + .addr = 0x000000, + .data = { + { 0x0800, 0x6108f0 }, + { 0x0804, 0x6108fc }, + { 0x0808, 0x61090c }, + { 0x080c, 0x610914 }, + { 0x0810, 0x610904 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_base_mthd = { + .name = "Base", + .addr = 0x000540, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_base_mthd_base }, + { "Image", 2, &nv50_disp_base_mthd_image }, + {} + } +}; + +static const struct nvkm_disp_chan_user +nv50_disp_base = { + .func = &nv50_disp_dmac_func, + .ctrl = 1, + .user = 1, + .mthd = &nv50_disp_base_mthd, +}; + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_base = { + .mthd = 0x0000, + .addr = 0x000000, + .data = { + { 0x0080, 0x000000 }, + { 0x0084, 0x610bb8 }, + { 0x0088, 0x610b9c }, + { 0x008c, 0x000000 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_dac = { + .mthd = 0x0080, + .addr = 0x000008, + .data = { + { 0x0400, 0x610b58 }, + { 0x0404, 0x610bdc }, + { 0x0420, 0x610828 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_sor = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0600, 0x610b70 }, + {} + } +}; + +const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_pior = { + .mthd = 0x0040, + .addr = 0x000008, + .data = { + { 0x0700, 0x610b80 }, + {} + } +}; + +static const struct nvkm_disp_mthd_list +nv50_disp_core_mthd_head = { + .mthd = 0x0400, + .addr = 0x000540, + .data = { + { 0x0800, 0x610ad8 }, + { 0x0804, 0x610ad0 }, + { 0x0808, 0x610a48 }, + { 0x080c, 0x610a78 }, + { 0x0810, 0x610ac0 }, + { 0x0814, 0x610af8 }, + { 0x0818, 0x610b00 }, + { 0x081c, 0x610ae8 }, + { 0x0820, 0x610af0 }, + { 0x0824, 0x610b08 }, + { 0x0828, 0x610b10 }, + { 0x082c, 0x610a68 }, + { 0x0830, 0x610a60 }, + { 0x0834, 0x000000 }, + { 0x0838, 0x610a40 }, + { 0x0840, 0x610a24 }, + { 0x0844, 0x610a2c }, + { 0x0848, 0x610aa8 }, + { 0x084c, 0x610ab0 }, + { 0x0860, 0x610a84 }, + { 0x0864, 0x610a90 }, + { 0x0868, 0x610b18 }, + { 0x086c, 0x610b20 }, + { 0x0870, 0x610ac8 }, + { 0x0874, 0x610a38 }, + { 0x0880, 0x610a58 }, + { 0x0884, 0x610a9c }, + { 0x08a0, 0x610a70 }, + { 0x08a4, 0x610a50 }, + { 0x08a8, 0x610ae0 }, + { 0x08c0, 0x610b28 }, + { 0x08c4, 0x610b30 }, + { 0x08c8, 0x610b40 }, + { 0x08d4, 0x610b38 }, + { 0x08d8, 0x610b48 }, + { 0x08dc, 0x610b50 }, + { 0x0900, 0x610a18 }, + { 0x0904, 0x610ab8 }, + {} + } +}; + +static const struct nvkm_disp_chan_mthd +nv50_disp_core_mthd = { + .name = "Core", + .addr = 0x000000, + .prev = 0x000004, + .data = { + { "Global", 1, &nv50_disp_core_mthd_base }, + { "DAC", 3, &nv50_disp_core_mthd_dac }, + { "SOR", 2, &nv50_disp_core_mthd_sor }, + { "PIOR", 3, &nv50_disp_core_mthd_pior }, + { "HEAD", 2, &nv50_disp_core_mthd_head }, + {} + } +}; + +static void +nv50_disp_core_fini(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* deactivate channel */ + nvkm_mask(device, 0x610200, 0x00000010, 0x00000000); + nvkm_mask(device, 0x610200, 0x00000003, 0x00000000); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200) & 0x001e0000)) + break; + ) < 0) { + nvkm_error(subdev, "core fini: %08x\n", + nvkm_rd32(device, 0x610200)); + } + + chan->suspend_put = nvkm_rd32(device, 0x640000); +} + +static int +nv50_disp_core_init(struct nvkm_disp_chan *chan) +{ + struct nvkm_subdev *subdev = &chan->disp->engine.subdev; + struct nvkm_device *device = subdev->device; + + /* attempt to unstick channel from some unknown state */ + if ((nvkm_rd32(device, 0x610200) & 0x009f0000) == 0x00020000) + nvkm_mask(device, 0x610200, 0x00800000, 0x00800000); + if ((nvkm_rd32(device, 0x610200) & 0x003f0000) == 0x00030000) + nvkm_mask(device, 0x610200, 0x00600000, 0x00600000); + + /* initialise channel for dma command submission */ + nvkm_wr32(device, 0x610204, chan->push); + nvkm_wr32(device, 0x610208, 0x00010000); + nvkm_wr32(device, 0x61020c, 0x00000000); + nvkm_mask(device, 0x610200, 0x00000010, 0x00000010); + nvkm_wr32(device, 0x640000, chan->suspend_put); + nvkm_wr32(device, 0x610200, 0x01000013); + + /* wait for it to go inactive */ + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x610200) & 0x80000000)) + break; + ) < 0) { + nvkm_error(subdev, "core init: %08x\n", + nvkm_rd32(device, 0x610200)); + return -EBUSY; + } + + return 0; +} + +const struct nvkm_disp_chan_func +nv50_disp_core_func = { + .push = nv50_disp_dmac_push, + .init = nv50_disp_core_init, + .fini = nv50_disp_core_fini, + .intr = nv50_disp_chan_intr, + .user = nv50_disp_chan_user, + .bind = nv50_disp_dmac_bind, +}; + +static const struct nvkm_disp_chan_user +nv50_disp_core = { + .func = &nv50_disp_core_func, + .ctrl = 0, + .user = 0, + .mthd = &nv50_disp_core_mthd, +}; + static u32 nv50_disp_super_iedt(struct nvkm_head *head, struct nvkm_outp *outp, u8 *ver, u8 *hdr, u8 *cnt, u8 *len, @@ -278,7 +1076,7 @@ static struct nvkm_ior * nv50_disp_super_ior_asy(struct nvkm_head *head) { struct nvkm_ior *ior; - list_for_each_entry(ior, &head->disp->ior, head) { + list_for_each_entry(ior, &head->disp->iors, head) { if (ior->asy.head & (1 << head->id)) { HEAD_DBG(head, "to %s", ior->name); return ior; @@ -292,7 +1090,7 @@ static struct nvkm_ior * nv50_disp_super_ior_arm(struct nvkm_head *head) { struct nvkm_ior *ior; - list_for_each_entry(ior, &head->disp->ior, head) { + list_for_each_entry(ior, &head->disp->iors, head) { if (ior->arm.head & (1 << head->id)) { HEAD_DBG(head, "on %s", ior->name); return ior; @@ -303,7 +1101,7 @@ nv50_disp_super_ior_arm(struct nvkm_head *head) } void -nv50_disp_super_3_0(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_3_0(struct nvkm_disp *disp, struct nvkm_head *head) { struct nvkm_ior *ior; @@ -346,7 +1144,7 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior) do_div(v, khz); v = v - ((36 / ior->dp.nr) + 3) - 1; - ior->func->dp.audio_sym(ior, head->id, h, v); + ior->func->dp->audio_sym(ior, head->id, h, v); /* watermark / activesym */ link_data_rate = (khz * head->asy.or.depth / 8) / ior->dp.nr; @@ -355,7 +1153,7 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior) link_ratio = link_data_rate * symbol; do_div(link_ratio, linkKBps); - for (TU = 64; ior->func->dp.activesym && TU >= 32; TU--) { + for (TU = 64; ior->func->dp->activesym && TU >= 32; TU--) { /* calculate average number of valid symbols in each TU */ u32 tu_valid = link_ratio * TU; u32 calc, diff; @@ -406,13 +1204,13 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior) } } - if (ior->func->dp.activesym) { + if (ior->func->dp->activesym) { if (!bestTU) { nvkm_error(subdev, "unable to determine dp config\n"); return; } - ior->func->dp.activesym(ior, head->id, bestTU, - bestVTUa, bestVTUf, bestVTUi); + + ior->func->dp->activesym(ior, head->id, bestTU, bestVTUa, bestVTUf, bestVTUi); } else { bestTU = 64; } @@ -424,11 +1222,11 @@ nv50_disp_super_2_2_dp(struct nvkm_head *head, struct nvkm_ior *ior) do_div(unk, symbol); unk += 6; - ior->func->dp.watermark(ior, head->id, unk); + ior->func->dp->watermark(ior, head->id, unk); } void -nv50_disp_super_2_2(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_2_2(struct nvkm_disp *disp, struct nvkm_head *head) { const u32 khz = head->asy.hz / 1000; struct nvkm_outp *outp; @@ -475,9 +1273,9 @@ nv50_disp_super_2_2(struct nv50_disp *disp, struct nvkm_head *head) } void -nv50_disp_super_2_1(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_2_1(struct nvkm_disp *disp, struct nvkm_head *head) { - struct nvkm_devinit *devinit = disp->base.engine.subdev.device->devinit; + struct nvkm_devinit *devinit = disp->engine.subdev.device->devinit; const u32 khz = head->asy.hz / 1000; HEAD_DBG(head, "supervisor 2.1 - %d khz", khz); if (khz) @@ -485,7 +1283,7 @@ nv50_disp_super_2_1(struct nv50_disp *disp, struct nvkm_head *head) } void -nv50_disp_super_2_0(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_2_0(struct nvkm_disp *disp, struct nvkm_head *head) { struct nvkm_outp *outp; struct nvkm_ior *ior; @@ -509,7 +1307,7 @@ nv50_disp_super_2_0(struct nv50_disp *disp, struct nvkm_head *head) } void -nv50_disp_super_1_0(struct nv50_disp *disp, struct nvkm_head *head) +nv50_disp_super_1_0(struct nvkm_disp *disp, struct nvkm_head *head) { struct nvkm_ior *ior; @@ -524,17 +1322,17 @@ nv50_disp_super_1_0(struct nv50_disp *disp, struct nvkm_head *head) } void -nv50_disp_super_1(struct nv50_disp *disp) +nv50_disp_super_1(struct nvkm_disp *disp) { struct nvkm_head *head; struct nvkm_ior *ior; - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { head->func->state(head, &head->arm); head->func->state(head, &head->asy); } - list_for_each_entry(ior, &disp->base.ior, head) { + list_for_each_entry(ior, &disp->iors, head) { ior->func->state(ior, &ior->arm); ior->func->state(ior, &ior->asy); } @@ -543,19 +1341,21 @@ nv50_disp_super_1(struct nv50_disp *disp) void nv50_disp_super(struct work_struct *work) { - struct nv50_disp *disp = - container_of(work, struct nv50_disp, supervisor); - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_disp *disp = container_of(work, struct nvkm_disp, super.work); + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; struct nvkm_head *head; - u32 super = nvkm_rd32(device, 0x610030); + u32 super; + + mutex_lock(&disp->super.mutex); + super = nvkm_rd32(device, 0x610030); - nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super, super); + nvkm_debug(subdev, "supervisor %08x %08x\n", disp->super.pending, super); - if (disp->super & 0x00000010) { + if (disp->super.pending & 0x00000010) { nv50_disp_chan_mthd(disp->chan[0], NV_DBG_DEBUG); nv50_disp_super_1(disp); - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000020 << head->id))) continue; if (!(super & (0x00000080 << head->id))) @@ -563,26 +1363,26 @@ nv50_disp_super(struct work_struct *work) nv50_disp_super_1_0(disp, head); } } else - if (disp->super & 0x00000020) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000020) { + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000080 << head->id))) continue; nv50_disp_super_2_0(disp, head); } - nvkm_outp_route(&disp->base); - list_for_each_entry(head, &disp->base.head, head) { + nvkm_outp_route(disp); + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000200 << head->id))) continue; nv50_disp_super_2_1(disp, head); } - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000080 << head->id))) continue; nv50_disp_super_2_2(disp, head); } } else - if (disp->super & 0x00000040) { - list_for_each_entry(head, &disp->base.head, head) { + if (disp->super.pending & 0x00000040) { + list_for_each_entry(head, &disp->heads, head) { if (!(super & (0x00000080 << head->id))) continue; nv50_disp_super_3_0(disp, head); @@ -590,6 +1390,7 @@ nv50_disp_super(struct work_struct *work) } nvkm_wr32(device, 0x610030, 0x80000000); + mutex_unlock(&disp->super.mutex); } const struct nvkm_enum @@ -611,9 +1412,9 @@ nv50_disp_intr_error_code[] = { }; static void -nv50_disp_intr_error(struct nv50_disp *disp, int chid) +nv50_disp_intr_error(struct nvkm_disp *disp, int chid) { - struct nvkm_subdev *subdev = &disp->base.engine.subdev; + struct nvkm_subdev *subdev = &disp->engine.subdev; struct nvkm_device *device = subdev->device; u32 data = nvkm_rd32(device, 0x610084 + (chid * 0x08)); u32 addr = nvkm_rd32(device, 0x610080 + (chid * 0x08)); @@ -645,9 +1446,9 @@ nv50_disp_intr_error(struct nv50_disp *disp, int chid) } void -nv50_disp_intr(struct nv50_disp *disp) +nv50_disp_intr(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; u32 intr0 = nvkm_rd32(device, 0x610020); u32 intr1 = nvkm_rd32(device, 0x610024); @@ -664,35 +1465,35 @@ nv50_disp_intr(struct nv50_disp *disp) } if (intr1 & 0x00000004) { - nvkm_disp_vblank(&disp->base, 0); + nvkm_disp_vblank(disp, 0); nvkm_wr32(device, 0x610024, 0x00000004); } if (intr1 & 0x00000008) { - nvkm_disp_vblank(&disp->base, 1); + nvkm_disp_vblank(disp, 1); nvkm_wr32(device, 0x610024, 0x00000008); } if (intr1 & 0x00000070) { - disp->super = (intr1 & 0x00000070); - queue_work(disp->wq, &disp->supervisor); - nvkm_wr32(device, 0x610024, disp->super); + disp->super.pending = (intr1 & 0x00000070); + queue_work(disp->super.wq, &disp->super.work); + nvkm_wr32(device, 0x610024, disp->super.pending); } } void -nv50_disp_fini(struct nv50_disp *disp) +nv50_disp_fini(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; /* disable all interrupts */ nvkm_wr32(device, 0x610024, 0x00000000); nvkm_wr32(device, 0x610020, 0x00000000); } int -nv50_disp_init(struct nv50_disp *disp) +nv50_disp_init(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_head *head; u32 tmp; int i; @@ -705,7 +1506,7 @@ nv50_disp_init(struct nv50_disp *disp) nvkm_wr32(device, 0x610184, tmp); /* ... CRTC caps */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { tmp = nvkm_rd32(device, 0x616100 + (head->id * 0x800)); nvkm_wr32(device, 0x610190 + (head->id * 0x10), tmp); tmp = nvkm_rd32(device, 0x616104 + (head->id * 0x800)); @@ -754,23 +1555,89 @@ nv50_disp_init(struct nv50_disp *disp) return 0; } -static const struct nv50_disp_func +int +nv50_disp_oneinit(struct nvkm_disp *disp) +{ + const struct nvkm_disp_func *func = disp->func; + struct nvkm_subdev *subdev = &disp->engine.subdev; + struct nvkm_device *device = subdev->device; + int ret, i; + + if (func->wndw.cnt) { + disp->wndw.nr = func->wndw.cnt(disp, &disp->wndw.mask); + nvkm_debug(subdev, "Window(s): %d (%08lx)\n", disp->wndw.nr, disp->wndw.mask); + } + + disp->head.nr = func->head.cnt(disp, &disp->head.mask); + nvkm_debug(subdev, " Head(s): %d (%02lx)\n", disp->head.nr, disp->head.mask); + for_each_set_bit(i, &disp->head.mask, disp->head.nr) { + ret = func->head.new(disp, i); + if (ret) + return ret; + } + + if (func->dac.cnt) { + disp->dac.nr = func->dac.cnt(disp, &disp->dac.mask); + nvkm_debug(subdev, " DAC(s): %d (%02lx)\n", disp->dac.nr, disp->dac.mask); + for_each_set_bit(i, &disp->dac.mask, disp->dac.nr) { + ret = func->dac.new(disp, i); + if (ret) + return ret; + } + } + + if (func->pior.cnt) { + disp->pior.nr = func->pior.cnt(disp, &disp->pior.mask); + nvkm_debug(subdev, " PIOR(s): %d (%02lx)\n", disp->pior.nr, disp->pior.mask); + for_each_set_bit(i, &disp->pior.mask, disp->pior.nr) { + ret = func->pior.new(disp, i); + if (ret) + return ret; + } + } + + disp->sor.nr = func->sor.cnt(disp, &disp->sor.mask); + nvkm_debug(subdev, " SOR(s): %d (%02lx)\n", disp->sor.nr, disp->sor.mask); + for_each_set_bit(i, &disp->sor.mask, disp->sor.nr) { + ret = func->sor.new(disp, i); + if (ret) + return ret; + } + + ret = nvkm_gpuobj_new(device, 0x10000, 0x10000, false, NULL, &disp->inst); + if (ret) + return ret; + + return nvkm_ramht_new(device, func->ramht_size ? func->ramht_size : + 0x1000, 0, disp->inst, &disp->ramht); +} + +static const struct nvkm_disp_func nv50_disp = { + .oneinit = nv50_disp_oneinit, .init = nv50_disp_init, .fini = nv50_disp_fini, .intr = nv50_disp_intr, - .uevent = &nv50_disp_chan_uevent, .super = nv50_disp_super, - .root = &nv50_disp_root_oclass, + .uevent = &nv50_disp_chan_uevent, .head = { .cnt = nv50_head_cnt, .new = nv50_head_new }, .dac = { .cnt = nv50_dac_cnt, .new = nv50_dac_new }, .sor = { .cnt = nv50_sor_cnt, .new = nv50_sor_new }, .pior = { .cnt = nv50_pior_cnt, .new = nv50_pior_new }, + .root = { 0, 0, NV50_DISP }, + .user = { + {{0,0,NV50_DISP_CURSOR }, nvkm_disp_chan_new, &nv50_disp_curs }, + {{0,0,NV50_DISP_OVERLAY }, nvkm_disp_chan_new, &nv50_disp_oimm }, + {{0,0,NV50_DISP_BASE_CHANNEL_DMA }, nvkm_disp_chan_new, &nv50_disp_base }, + {{0,0,NV50_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &nv50_disp_core }, + {{0,0,NV50_DISP_OVERLAY_CHANNEL_DMA}, nvkm_disp_chan_new, &nv50_disp_ovly }, + {} + } }; int nv50_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&nv50_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&nv50_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h deleted file mode 100644 index 025cacd7c3b0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/nv50.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV50_DISP_H__ -#define __NV50_DISP_H__ -#define nv50_disp(p) container_of((p), struct nv50_disp, base) -#include "priv.h" -struct nvkm_head; - -#include <core/enum.h> - -struct nv50_disp { - const struct nv50_disp_func *func; - struct nvkm_disp base; - - struct workqueue_struct *wq; - struct work_struct supervisor; - u32 super; - - struct nvkm_event uevent; - - struct { - unsigned long mask; - int nr; - } wndw, head, dac; - - struct { - unsigned long mask; - int nr; - u32 lvdsconf; - } sor; - - struct { - unsigned long mask; - int nr; - u8 type[3]; - } pior; - - struct nvkm_gpuobj *inst; - struct nvkm_ramht *ramht; - - struct nv50_disp_chan *chan[81]; -}; - -void nv50_disp_super_1(struct nv50_disp *); -void nv50_disp_super_1_0(struct nv50_disp *, struct nvkm_head *); -void nv50_disp_super_2_0(struct nv50_disp *, struct nvkm_head *); -void nv50_disp_super_2_1(struct nv50_disp *, struct nvkm_head *); -void nv50_disp_super_2_2(struct nv50_disp *, struct nvkm_head *); -void nv50_disp_super_3_0(struct nv50_disp *, struct nvkm_head *); - -int nv50_disp_new_(const struct nv50_disp_func *, struct nvkm_device *, enum nvkm_subdev_type, int, - struct nvkm_disp **); - -struct nv50_disp_func { - int (*init)(struct nv50_disp *); - void (*fini)(struct nv50_disp *); - void (*intr)(struct nv50_disp *); - void (*intr_error)(struct nv50_disp *, int chid); - - const struct nvkm_event_func *uevent; - void (*super)(struct work_struct *); - - const struct nvkm_disp_oclass *root; - - struct { - int (*cnt)(struct nvkm_disp *, unsigned long *mask); - int (*new)(struct nvkm_disp *, int id); - } wndw, head, dac, sor, pior; - - u16 ramht_size; -}; - -int nv50_disp_init(struct nv50_disp *); -void nv50_disp_fini(struct nv50_disp *); -void nv50_disp_intr(struct nv50_disp *); -void nv50_disp_super(struct work_struct *); -extern const struct nvkm_enum nv50_disp_intr_error_type[]; - -int gf119_disp_init(struct nv50_disp *); -void gf119_disp_fini(struct nv50_disp *); -void gf119_disp_intr(struct nv50_disp *); -void gf119_disp_super(struct work_struct *); -void gf119_disp_intr_error(struct nv50_disp *, int); - -void gv100_disp_fini(struct nv50_disp *); -void gv100_disp_intr(struct nv50_disp *); -void gv100_disp_super(struct work_struct *); -int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *); - -int tu102_disp_init(struct nv50_disp *); - -void nv50_disp_dptmds_war_2(struct nv50_disp *, struct dcb_output *); -void nv50_disp_dptmds_war_3(struct nv50_disp *, struct dcb_output *); -void nv50_disp_update_sppll1(struct nv50_disp *); - -extern const struct nvkm_event_func nv50_disp_chan_uevent; -int nv50_disp_chan_uevent_ctor(struct nvkm_object *, void *, u32, - struct nvkm_notify *); -void nv50_disp_chan_uevent_send(struct nv50_disp *, int); - -extern const struct nvkm_event_func gf119_disp_chan_uevent; -extern const struct nvkm_event_func gv100_disp_chan_uevent; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c deleted file mode 100644 index 1ae0bcfc89b9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgf119.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gf119_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&gf119_disp_pioc_func, disp, 9, 9, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c deleted file mode 100644 index 30ffb1008505..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmgp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "channv50.h" - -int -gp102_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&gf119_disp_pioc_func, disp, 9, 13, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c deleted file mode 100644 index 0db99bfe9db9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/oimmnv50.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507b.h> -#include <nvif/unpack.h> - -int -nv50_disp_oimm_new_(const struct nv50_disp_chan_func *func, - struct nv50_disp *disp, int ctrl, int user, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_overlay_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - - nvif_ioctl(parent, "create disp overlay size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp overlay vers %d head %d\n", - args->v0.version, args->v0.head); - if (!nvkm_head_find(&disp->base, args->v0.head)) - return -EINVAL; - head = args->v0.head; - } else - return ret; - - return nv50_disp_chan_new_(func, NULL, disp, ctrl + head, user + head, - head, oclass, pobject); -} - -int -nv50_disp_oimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_oimm_new_(&nv50_disp_pioc_func, disp, 5, 5, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c index 129982fef7ef..6094805fbd63 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.c @@ -35,7 +35,7 @@ nvkm_outp_route(struct nvkm_disp *disp) struct nvkm_outp *outp; struct nvkm_ior *ior; - list_for_each_entry(ior, &disp->ior, head) { + list_for_each_entry(ior, &disp->iors, head) { if ((outp = ior->arm.outp) && ior->arm.outp != ior->asy.outp) { OUTP_DBG(outp, "release %s", ior->name); if (ior->func->route.set) @@ -44,7 +44,7 @@ nvkm_outp_route(struct nvkm_disp *disp) } } - list_for_each_entry(ior, &disp->ior, head) { + list_for_each_entry(ior, &disp->iors, head) { if ((outp = ior->asy.outp)) { OUTP_DBG(outp, "acquire %s", ior->name); if (ior->asy.outp != ior->arm.outp) { @@ -119,8 +119,8 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type, struct nvkm_ior *ior; /* Failing that, a completely unused OR is the next best thing. */ - list_for_each_entry(ior, &outp->disp->ior, head) { - if (!ior->identity && !!ior->func->hda.hpd == hda && + list_for_each_entry(ior, &outp->disp->iors, head) { + if (!ior->identity && ior->hda == hda && !ior->asy.outp && ior->type == type && !ior->arm.outp && (ior->func->route.set || ior->id == __ffs(outp->info.or))) return nvkm_outp_acquire_ior(outp, user, ior); @@ -129,8 +129,8 @@ nvkm_outp_acquire_hda(struct nvkm_outp *outp, enum nvkm_ior_type type, /* Last resort is to assign an OR that's already active on HW, * but will be released during the next modeset. */ - list_for_each_entry(ior, &outp->disp->ior, head) { - if (!ior->identity && !!ior->func->hda.hpd == hda && + list_for_each_entry(ior, &outp->disp->iors, head) { + if (!ior->identity && ior->hda == hda && !ior->asy.outp && ior->type == type && (ior->func->route.set || ior->id == __ffs(outp->info.or))) return nvkm_outp_acquire_ior(outp, user, ior); @@ -168,7 +168,7 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda) /* First preference is to reuse the OR that is currently armed * on HW, if any, in order to prevent unnecessary switching. */ - list_for_each_entry(ior, &outp->disp->ior, head) { + list_for_each_entry(ior, &outp->disp->iors, head) { if (!ior->identity && !ior->asy.outp && ior->arm.outp == outp) { /*XXX: For various complicated reasons, we can't outright switch * the boot-time OR on the first modeset without some fairly @@ -181,7 +181,7 @@ nvkm_outp_acquire(struct nvkm_outp *outp, u8 user, bool hda) * * This warning is to make it obvious if that proves wrong. */ - WARN_ON(hda && !ior->func->hda.hpd); + WARN_ON(hda && !ior->hda); return nvkm_outp_acquire_ior(outp, user, ior); } } @@ -294,13 +294,17 @@ nvkm_outp_del(struct nvkm_outp **poutp) } int -nvkm_outp_ctor(const struct nvkm_outp_func *func, struct nvkm_disp *disp, - int index, struct dcb_output *dcbE, struct nvkm_outp *outp) +nvkm_outp_new_(const struct nvkm_outp_func *func, struct nvkm_disp *disp, + int index, struct dcb_output *dcbE, struct nvkm_outp **poutp) { struct nvkm_i2c *i2c = disp->engine.subdev.device->i2c; + struct nvkm_outp *outp; enum nvkm_ior_proto proto; enum nvkm_ior_type type; + if (!(outp = *poutp = kzalloc(sizeof(*outp), GFP_KERNEL))) + return -ENOMEM; + outp->func = func; outp->disp = disp; outp->index = index; @@ -330,7 +334,5 @@ int nvkm_outp_new(struct nvkm_disp *disp, int index, struct dcb_output *dcbE, struct nvkm_outp **poutp) { - if (!(*poutp = kzalloc(sizeof(**poutp), GFP_KERNEL))) - return -ENOMEM; - return nvkm_outp_ctor(&nvkm_outp, disp, index, dcbE, *poutp); + return nvkm_outp_new_(&nvkm_outp, disp, index, dcbE, poutp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h index ee028d30cfe7..3f3924c41957 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/outp.h @@ -1,10 +1,12 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_OUTP_H__ #define __NVKM_DISP_OUTP_H__ -#include <engine/disp.h> +#include "priv.h" +#include <core/notify.h> #include <subdev/bios.h> #include <subdev/bios/dcb.h> +#include <subdev/bios/dp.h> struct nvkm_outp { const struct nvkm_outp_func *func; @@ -23,12 +25,41 @@ struct nvkm_outp { #define NVKM_OUTP_USER 2 u8 acquired:2; struct nvkm_ior *ior; + + union { + struct { + struct nvbios_dpout info; + u8 version; + + struct nvkm_i2c_aux *aux; + + struct nvkm_notify hpd; + bool present; + u8 lttpr[6]; + u8 lttprs; + u8 dpcd[16]; + + struct { + int dpcd; /* -1, or index into SUPPORTED_LINK_RATES table */ + u32 rate; + } rate[8]; + int rates; + int links; + + struct mutex mutex; + struct { + atomic_t done; + bool mst; + } lt; + } dp; + }; + + struct nvkm_object object; }; -int nvkm_outp_ctor(const struct nvkm_outp_func *, struct nvkm_disp *, - int index, struct dcb_output *, struct nvkm_outp *); -int nvkm_outp_new(struct nvkm_disp *, int index, struct dcb_output *, - struct nvkm_outp **); +int nvkm_outp_new_(const struct nvkm_outp_func *, struct nvkm_disp *, int index, + struct dcb_output *, struct nvkm_outp **); +int nvkm_outp_new(struct nvkm_disp *, int index, struct dcb_output *, struct nvkm_outp **); void nvkm_outp_del(struct nvkm_outp **); void nvkm_outp_init(struct nvkm_outp *); void nvkm_outp_fini(struct nvkm_outp *); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c deleted file mode 100644 index 31b915d48699..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlyg84.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -g84_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x6109a0 }, - { 0x0088, 0x6109c0 }, - { 0x008c, 0x6109c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -g84_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &g84_disp_ovly_mthd_base }, - {} - } -}; - -int -g84_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, &g84_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c deleted file mode 100644 index 83fd534c44da..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygf119.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gf119_disp_ovly_mthd_base = { - .mthd = 0x0000, - .data = { - { 0x0080, 0x665080 }, - { 0x0084, 0x665084 }, - { 0x0088, 0x665088 }, - { 0x008c, 0x66508c }, - { 0x0090, 0x665090 }, - { 0x0094, 0x665094 }, - { 0x00a0, 0x6650a0 }, - { 0x00a4, 0x6650a4 }, - { 0x00b0, 0x6650b0 }, - { 0x00b4, 0x6650b4 }, - { 0x00b8, 0x6650b8 }, - { 0x00c0, 0x6650c0 }, - { 0x00e0, 0x6650e0 }, - { 0x00e4, 0x6650e4 }, - { 0x00e8, 0x6650e8 }, - { 0x0100, 0x665100 }, - { 0x0104, 0x665104 }, - { 0x0108, 0x665108 }, - { 0x010c, 0x66510c }, - { 0x0110, 0x665110 }, - { 0x0118, 0x665118 }, - { 0x011c, 0x66511c }, - { 0x0120, 0x665120 }, - { 0x0124, 0x665124 }, - { 0x0130, 0x665130 }, - { 0x0134, 0x665134 }, - { 0x0138, 0x665138 }, - { 0x013c, 0x66513c }, - { 0x0140, 0x665140 }, - { 0x0144, 0x665144 }, - { 0x0148, 0x665148 }, - { 0x014c, 0x66514c }, - { 0x0150, 0x665150 }, - { 0x0154, 0x665154 }, - { 0x0158, 0x665158 }, - { 0x015c, 0x66515c }, - { 0x0160, 0x665160 }, - { 0x0164, 0x665164 }, - { 0x0168, 0x665168 }, - { 0x016c, 0x66516c }, - { 0x0400, 0x665400 }, - { 0x0408, 0x665408 }, - { 0x040c, 0x66540c }, - { 0x0410, 0x665410 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gf119_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gf119_disp_ovly_mthd_base }, - {} - } -}; - -int -gf119_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gf119_disp_dmac_func, &gf119_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c deleted file mode 100644 index a7acacbc92c1..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygk104.c +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gk104_disp_ovly_mthd_base = { - .mthd = 0x0000, - .data = { - { 0x0080, 0x665080 }, - { 0x0084, 0x665084 }, - { 0x0088, 0x665088 }, - { 0x008c, 0x66508c }, - { 0x0090, 0x665090 }, - { 0x0094, 0x665094 }, - { 0x00a0, 0x6650a0 }, - { 0x00a4, 0x6650a4 }, - { 0x00b0, 0x6650b0 }, - { 0x00b4, 0x6650b4 }, - { 0x00b8, 0x6650b8 }, - { 0x00c0, 0x6650c0 }, - { 0x00c4, 0x6650c4 }, - { 0x00e0, 0x6650e0 }, - { 0x00e4, 0x6650e4 }, - { 0x00e8, 0x6650e8 }, - { 0x0100, 0x665100 }, - { 0x0104, 0x665104 }, - { 0x0108, 0x665108 }, - { 0x010c, 0x66510c }, - { 0x0110, 0x665110 }, - { 0x0118, 0x665118 }, - { 0x011c, 0x66511c }, - { 0x0120, 0x665120 }, - { 0x0124, 0x665124 }, - { 0x0130, 0x665130 }, - { 0x0134, 0x665134 }, - { 0x0138, 0x665138 }, - { 0x013c, 0x66513c }, - { 0x0140, 0x665140 }, - { 0x0144, 0x665144 }, - { 0x0148, 0x665148 }, - { 0x014c, 0x66514c }, - { 0x0150, 0x665150 }, - { 0x0154, 0x665154 }, - { 0x0158, 0x665158 }, - { 0x015c, 0x66515c }, - { 0x0160, 0x665160 }, - { 0x0164, 0x665164 }, - { 0x0168, 0x665168 }, - { 0x016c, 0x66516c }, - { 0x0400, 0x665400 }, - { 0x0404, 0x665404 }, - { 0x0408, 0x665408 }, - { 0x040c, 0x66540c }, - { 0x0410, 0x665410 }, - {} - } -}; - -const struct nv50_disp_chan_mthd -gk104_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x001000, - .prev = -0x020000, - .data = { - { "Global", 1, &gk104_disp_ovly_mthd_base }, - {} - } -}; - -int -gk104_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gf119_disp_dmac_func, &gk104_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c deleted file mode 100644 index e0eca6ea914c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygp102.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -int -gp102_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&gp102_disp_dmac_func, &gk104_disp_ovly_mthd, - disp, 5, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c deleted file mode 100644 index dc60cd00dc16..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlygt200.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" - -static const struct nv50_disp_mthd_list -gt200_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x6109a0 }, - { 0x0088, 0x6109c0 }, - { 0x008c, 0x6109c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00b0, 0x610c98 }, - { 0x00b4, 0x610ca4 }, - { 0x00b8, 0x610cac }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gt200_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, >200_disp_ovly_mthd_base }, - {} - } -}; - -int -gt200_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, >200_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c deleted file mode 100644 index 6974c12c4518..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ovlynv50.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "head.h" - -#include <core/client.h> - -#include <nvif/cl507e.h> -#include <nvif/unpack.h> - -int -nv50_disp_ovly_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nv50_disp_overlay_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int head, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create disp overlay channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create disp overlay channel dma vers %d " - "pushbuf %016llx head %d\n", - args->v0.version, args->v0.pushbuf, args->v0.head); - if (!nvkm_head_find(&disp->base, args->v0.head)) - return -EINVAL; - push = args->v0.pushbuf; - head = args->v0.head; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + head, - head, push, oclass, pobject); -} - -static const struct nv50_disp_mthd_list -nv50_disp_ovly_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0080, 0x000000 }, - { 0x0084, 0x0009a0 }, - { 0x0088, 0x0009c0 }, - { 0x008c, 0x0009c8 }, - { 0x0090, 0x6109b4 }, - { 0x0094, 0x610970 }, - { 0x00a0, 0x610998 }, - { 0x00a4, 0x610964 }, - { 0x00c0, 0x610958 }, - { 0x00e0, 0x6109a8 }, - { 0x00e4, 0x6109d0 }, - { 0x00e8, 0x6109d8 }, - { 0x0100, 0x61094c }, - { 0x0104, 0x610984 }, - { 0x0108, 0x61098c }, - { 0x0800, 0x6109f8 }, - { 0x0808, 0x610a08 }, - { 0x080c, 0x610a10 }, - { 0x0810, 0x610a00 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -nv50_disp_ovly_mthd = { - .name = "Overlay", - .addr = 0x000540, - .prev = 0x000004, - .data = { - { "Global", 1, &nv50_disp_ovly_mthd_base }, - {} - } -}; - -int -nv50_disp_ovly_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return nv50_disp_ovly_new_(&nv50_disp_dmac_func, &nv50_disp_ovly_mthd, - disp, 3, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c deleted file mode 100644 index 5296e7bee813..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocgf119.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "rootnv50.h" - -#include <subdev/timer.h> - -static void -gf119_disp_pioc_fini(struct nv50_disp_chan *chan) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_mask(device, 0x610490 + (ctrl * 0x10), 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610490 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d fini: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - } -} - -static int -gf119_disp_pioc_init(struct nv50_disp_chan *chan) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - /* activate channel */ - nvkm_wr32(device, 0x610490 + (ctrl * 0x10), 0x00000001); - if (nvkm_msec(device, 2000, - u32 tmp = nvkm_rd32(device, 0x610490 + (ctrl * 0x10)); - if ((tmp & 0x00030000) == 0x00010000) - break; - ) < 0) { - nvkm_error(subdev, "ch %d init: %08x\n", user, - nvkm_rd32(device, 0x610490 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -gf119_disp_pioc_func = { - .init = gf119_disp_pioc_init, - .fini = gf119_disp_pioc_fini, - .intr = gf119_disp_chan_intr, - .user = nv50_disp_chan_user, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c deleted file mode 100644 index 4faed6fce682..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piocnv50.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "channv50.h" -#include "rootnv50.h" - -#include <subdev/timer.h> - -static void -nv50_disp_pioc_fini(struct nv50_disp_chan *chan) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_mask(device, 0x610200 + (ctrl * 0x10), 0x00000001, 0x00000000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - } -} - -static int -nv50_disp_pioc_init(struct nv50_disp_chan *chan) -{ - struct nv50_disp *disp = chan->disp; - struct nvkm_subdev *subdev = &disp->base.engine.subdev; - struct nvkm_device *device = subdev->device; - int ctrl = chan->chid.ctrl; - int user = chan->chid.user; - - nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00002000); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x610200 + (ctrl * 0x10)) & 0x00030000)) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout0: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - nvkm_wr32(device, 0x610200 + (ctrl * 0x10), 0x00000001); - if (nvkm_msec(device, 2000, - u32 tmp = nvkm_rd32(device, 0x610200 + (ctrl * 0x10)); - if ((tmp & 0x00030000) == 0x00010000) - break; - ) < 0) { - nvkm_error(subdev, "ch %d timeout1: %08x\n", user, - nvkm_rd32(device, 0x610200 + (ctrl * 0x10))); - return -EBUSY; - } - - return 0; -} - -const struct nv50_disp_chan_func -nv50_disp_pioc_func = { - .init = nv50_disp_pioc_init, - .fini = nv50_disp_pioc_fini, - .intr = nv50_disp_chan_intr, - .user = nv50_disp_chan_user, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c deleted file mode 100644 index e997a207f546..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/piornv50.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "ior.h" -#include "head.h" - -#include <subdev/i2c.h> -#include <subdev/timer.h> - -static void -nv50_pior_clock(struct nvkm_ior *pior) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 poff = nv50_ior_base(pior); - nvkm_mask(device, 0x614380 + poff, 0x00000707, 0x00000001); -} - -static int -nv50_pior_dp_links(struct nvkm_ior *pior, struct nvkm_i2c_aux *aux) -{ - int ret = nvkm_i2c_aux_lnk_ctl(aux, pior->dp.nr, pior->dp.bw, - pior->dp.ef); - if (ret) - return ret; - return 1; -} - -static void -nv50_pior_power_wait(struct nvkm_device *device, u32 poff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61e004 + poff) & 0x80000000)) - break; - ); -} - -static void -nv50_pior_power(struct nvkm_ior *pior, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 poff = nv50_ior_base(pior); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; - const u32 field = 0x80000000 | (0x00000101 << shift); - - nv50_pior_power_wait(device, poff); - nvkm_mask(device, 0x61e004 + poff, field, state); - nv50_pior_power_wait(device, poff); -} - -void -nv50_pior_depth(struct nvkm_ior *ior, struct nvkm_ior_state *state, u32 ctrl) -{ - /* GF119 moves this information to per-head methods, which is - * a lot more convenient, and where our shared code expect it. - */ - if (state->head && state == &ior->asy) { - struct nvkm_head *head = - nvkm_head_find(ior->disp, __ffs(state->head)); - if (!WARN_ON(!head)) { - struct nvkm_head_state *state = &head->asy; - switch ((ctrl & 0x000f0000) >> 16) { - case 6: state->or.depth = 30; break; - case 5: state->or.depth = 24; break; - case 2: state->or.depth = 18; break; - case 0: state->or.depth = 18; break; /*XXX*/ - default: - state->or.depth = 18; - WARN_ON(1); - break; - } - } - } -} - -static void -nv50_pior_state(struct nvkm_ior *pior, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = pior->disp->engine.subdev.device; - const u32 coff = pior->id * 8 + (state == &pior->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b80 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - state->rgdiv = 1; - switch (state->proto_evo) { - case 0: state->proto = TMDS; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; - nv50_pior_depth(pior, state, ctrl); -} - -static const struct nvkm_ior_func -nv50_pior = { - .state = nv50_pior_state, - .power = nv50_pior_power, - .clock = nv50_pior_clock, - .dp = { - .links = nv50_pior_dp_links, - }, -}; - -int -nv50_pior_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_pior, disp, PIOR, id); -} - -int -nv50_pior_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x70000000) >> 28; - return 3; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h index ec57d8b6bce9..cb25dfe849f0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/priv.h @@ -1,8 +1,12 @@ /* SPDX-License-Identifier: MIT */ #ifndef __NVKM_DISP_PRIV_H__ #define __NVKM_DISP_PRIV_H__ +#define nvkm_udisp(p) container_of((p), struct nvkm_disp, client.object) #include <engine/disp.h> -#include "outp.h" +#include <core/enum.h> +struct nvkm_head; +struct nvkm_outp; +struct dcb_output; int nvkm_disp_ctor(const struct nvkm_disp_func *, struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_disp *); @@ -11,22 +15,75 @@ int nvkm_disp_new_(const struct nvkm_disp_func *, struct nvkm_device *, enum nvk void nvkm_disp_vblank(struct nvkm_disp *, int head); struct nvkm_disp_func { - void *(*dtor)(struct nvkm_disp *); int (*oneinit)(struct nvkm_disp *); int (*init)(struct nvkm_disp *); void (*fini)(struct nvkm_disp *); void (*intr)(struct nvkm_disp *); + void (*intr_error)(struct nvkm_disp *, int chid); - const struct nvkm_disp_oclass *(*root)(struct nvkm_disp *); + void (*super)(struct work_struct *); + + const struct nvkm_event_func *uevent; + + struct { + int (*cnt)(struct nvkm_disp *, unsigned long *mask); + int (*new)(struct nvkm_disp *, int id); + } wndw, head, dac, sor, pior; + + u16 ramht_size; + + const struct nvkm_sclass root; + + struct nvkm_disp_user { + struct nvkm_sclass base; + int (*ctor)(const struct nvkm_oclass *, void *argv, u32 argc, + struct nvkm_object **); + const struct nvkm_disp_chan_user *chan; + } user[]; }; int nvkm_disp_ntfy(struct nvkm_object *, u32, struct nvkm_event **); +int nv04_disp_mthd(struct nvkm_object *, u32, void *, u32); +int nv50_disp_root_mthd_(struct nvkm_object *, u32, void *, u32); -extern const struct nvkm_disp_oclass nv04_disp_root_oclass; +int nv50_disp_oneinit(struct nvkm_disp *); +int nv50_disp_init(struct nvkm_disp *); +void nv50_disp_fini(struct nvkm_disp *); +void nv50_disp_intr(struct nvkm_disp *); +extern const struct nvkm_enum nv50_disp_intr_error_type[]; +void nv50_disp_super(struct work_struct *); +void nv50_disp_super_1(struct nvkm_disp *); +void nv50_disp_super_1_0(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_0(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_1(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_2_2(struct nvkm_disp *, struct nvkm_head *); +void nv50_disp_super_3_0(struct nvkm_disp *, struct nvkm_head *); -struct nvkm_disp_oclass { - int (*ctor)(struct nvkm_disp *, const struct nvkm_oclass *, - void *data, u32 size, struct nvkm_object **); - struct nvkm_sclass base; -}; +int gf119_disp_init(struct nvkm_disp *); +void gf119_disp_fini(struct nvkm_disp *); +void gf119_disp_intr(struct nvkm_disp *); +void gf119_disp_super(struct work_struct *); +void gf119_disp_intr_error(struct nvkm_disp *, int); + +void gv100_disp_fini(struct nvkm_disp *); +void gv100_disp_intr(struct nvkm_disp *); +void gv100_disp_super(struct work_struct *); +int gv100_disp_wndw_cnt(struct nvkm_disp *, unsigned long *); +int gv100_disp_caps_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); + +int tu102_disp_init(struct nvkm_disp *); + +void nv50_disp_dptmds_war_2(struct nvkm_disp *, struct dcb_output *); +void nv50_disp_dptmds_war_3(struct nvkm_disp *, struct dcb_output *); +void nv50_disp_update_sppll1(struct nvkm_disp *); + +extern const struct nvkm_event_func nv50_disp_chan_uevent; +void nv50_disp_chan_uevent_send(struct nvkm_disp *, int); + +extern const struct nvkm_event_func gf119_disp_chan_uevent; +extern const struct nvkm_event_func gv100_disp_chan_uevent; + +int nvkm_udisp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_uconn_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); +int nvkm_uoutp_new(const struct nvkm_oclass *, void *, u32, struct nvkm_object **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c deleted file mode 100644 index 1ed371fd7ddf..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootg84.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -g84_disp_root = { - .user = { - {{0,0,G82_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0,G82_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,G82_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, - {{0,0,G82_DISP_CORE_CHANNEL_DMA }, g84_disp_core_new }, - {{0,0,G82_DISP_OVERLAY_CHANNEL_DMA}, g84_disp_ovly_new }, - {} - }, -}; - -static int -g84_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&g84_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -g84_disp_root_oclass = { - .base.oclass = G82_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = g84_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c deleted file mode 100644 index fe011165dc02..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgf119.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gf119_disp_root = { - .user = { - {{0,0,GF110_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GF110_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GF110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GF110_DISP_CORE_CHANNEL_DMA }, gf119_disp_core_new }, - {{0,0,GF110_DISP_OVERLAY_CONTROL_DMA}, gf119_disp_ovly_new }, - {} - }, -}; - -static int -gf119_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gf119_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gf119_disp_root_oclass = { - .base.oclass = GF110_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gf119_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c deleted file mode 100644 index 9e8ffd348b50..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk104.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gk104_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK104_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GK104_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gk104_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gk104_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gk104_disp_root_oclass = { - .base.oclass = GK104_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gk104_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c deleted file mode 100644 index dc85cc1c9490..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgk110.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gk110_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GK110_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gk110_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gk110_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gk110_disp_root_oclass = { - .base.oclass = GK110_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gk110_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c deleted file mode 100644 index e0181ca08840..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm107.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gm107_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GM107_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gm107_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gm107_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gm107_disp_root_oclass = { - .base.oclass = GM107_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gm107_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c deleted file mode 100644 index e5e590e19f62..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgm200.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gm200_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GM200_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gm200_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gm200_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gm200_disp_root_oclass = { - .base.oclass = GM200_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gm200_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c deleted file mode 100644 index 762a1a922e05..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp100.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2015 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gp100_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gf119_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gf119_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gf119_disp_base_new }, - {{0,0,GP100_DISP_CORE_CHANNEL_DMA }, gk104_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gk104_disp_ovly_new }, - {} - }, -}; - -static int -gp100_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gp100_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gp100_disp_root_oclass = { - .base.oclass = GP100_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gp100_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c deleted file mode 100644 index c7f00946c9af..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgp102.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gp102_disp_root = { - .user = { - {{0,0,GK104_DISP_CURSOR }, gp102_disp_curs_new }, - {{0,0,GK104_DISP_OVERLAY }, gp102_disp_oimm_new }, - {{0,0,GK110_DISP_BASE_CHANNEL_DMA }, gp102_disp_base_new }, - {{0,0,GP102_DISP_CORE_CHANNEL_DMA }, gp102_disp_core_new }, - {{0,0,GK104_DISP_OVERLAY_CONTROL_DMA}, gp102_disp_ovly_new }, - {} - }, -}; - -static int -gp102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gp102_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gp102_disp_root_oclass = { - .base.oclass = GP102_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gp102_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c deleted file mode 100644 index a6963654087c..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt200.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gt200_disp_root = { - .user = { - {{0,0, G82_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0, G82_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,GT200_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, - {{0,0,GT200_DISP_CORE_CHANNEL_DMA }, g84_disp_core_new }, - {{0,0,GT200_DISP_OVERLAY_CHANNEL_DMA}, gt200_disp_ovly_new }, - {} - }, -}; - -static int -gt200_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(>200_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gt200_disp_root_oclass = { - .base.oclass = GT200_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gt200_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c deleted file mode 100644 index 4fe0a3ae8891..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgt215.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gt215_disp_root = { - .user = { - {{0,0,GT214_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0,GT214_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,GT214_DISP_BASE_CHANNEL_DMA }, g84_disp_base_new }, - {{0,0,GT214_DISP_CORE_CHANNEL_DMA }, g94_disp_core_new }, - {{0,0,GT214_DISP_OVERLAY_CHANNEL_DMA}, g84_disp_ovly_new }, - {} - }, -}; - -static int -gt215_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(>215_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gt215_disp_root_oclass = { - .base.oclass = GT214_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gt215_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c deleted file mode 100644 index 47efb48d769a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootgv100.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -gv100_disp_root = { - .user = { - {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, - {{0,0,GV100_DISP_CURSOR }, gv100_disp_curs_new }, - {{0,0,GV100_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, - {{0,0,GV100_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, - {{0,0,GV100_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, - {} - }, -}; - -static int -gv100_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&gv100_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -gv100_disp_root_oclass = { - .base.oclass = GV100_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = gv100_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c index 7f3e2554a83d..9acaec5c271e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv04.c @@ -21,25 +21,18 @@ * * Authors: Ben Skeggs */ -#define nv04_disp_root(p) container_of((p), struct nv04_disp_root, object) #include "priv.h" #include "head.h" #include <core/client.h> -#include <nvif/class.h> #include <nvif/cl0046.h> #include <nvif/unpack.h> -struct nv04_disp_root { - struct nvkm_object object; - struct nvkm_disp *disp; -}; - -static int +int nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) { - struct nv04_disp_root *root = nv04_disp_root(object); + struct nvkm_disp *disp = nvkm_disp(object->engine); union { struct nv04_disp_mthd_v0 v0; } *args = data; @@ -55,7 +48,7 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) } else return ret; - if (!(head = nvkm_head_find(root->disp, id))) + if (!(head = nvkm_head_find(disp, id))) return -ENXIO; switch (mthd) { @@ -67,32 +60,3 @@ nv04_disp_mthd(struct nvkm_object *object, u32 mthd, void *data, u32 size) return -EINVAL; } - -static const struct nvkm_object_func -nv04_disp_root = { - .mthd = nv04_disp_mthd, - .ntfy = nvkm_disp_ntfy, -}; - -static int -nv04_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nv04_disp_root *root; - - if (!(root = kzalloc(sizeof(*root), GFP_KERNEL))) - return -ENOMEM; - root->disp = disp; - *pobject = &root->object; - - nvkm_object_ctor(&nv04_disp_root, oclass, &root->object); - return 0; -} - -const struct nvkm_disp_oclass -nv04_disp_root_oclass = { - .base.oclass = NV04_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = nv04_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c index ecde98dd2454..0af45ccd140c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.c @@ -21,11 +21,10 @@ * * Authors: Ben Skeggs */ -#include "rootnv50.h" -#include "channv50.h" -#include "dp.h" +#include "chan.h" #include "head.h" #include "ior.h" +#include "outp.h" #include <core/client.h> @@ -33,15 +32,14 @@ #include <nvif/cl5070.h> #include <nvif/unpack.h> -static int +int nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) { union { struct nv50_disp_mthd_v0 v0; struct nv50_disp_mthd_v1 v1; } *args = data; - struct nv50_disp_root *root = nv50_disp_root(object); - struct nv50_disp *disp = root->disp; + struct nvkm_disp *disp = nvkm_udisp(object); struct nvkm_outp *temp, *outp = NULL; struct nvkm_head *head; u16 type, mask = 0; @@ -69,11 +67,11 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } else return ret; - if (!(head = nvkm_head_find(&disp->base, hidx))) + if (!(head = nvkm_head_find(disp, hidx))) return -ENXIO; if (mask) { - list_for_each_entry(temp, &disp->base.outp, head) { + list_for_each_entry(temp, &disp->outps, head) { if ((temp->info.hasht == type) && (temp->info.hashm & mask) == mask) { outp = temp; @@ -111,27 +109,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) case NV50_DISP_MTHD_V1_RELEASE: nvkm_outp_release(outp, NVKM_OUTP_USER); return 0; - case NV50_DISP_MTHD_V1_DAC_LOAD: { - union { - struct nv50_disp_dac_load_v0 v0; - } *args = data; - int ret = -ENOSYS; - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - if (args->v0.data & 0xfff00000) - return -EINVAL; - ret = nvkm_outp_acquire(outp, NVKM_OUTP_PRIV, false); - if (ret) - return ret; - ret = outp->ior->func->sense(outp->ior, args->v0.data); - nvkm_outp_release(outp, NVKM_OUTP_PRIV); - if (ret < 0) - return ret; - args->v0.load = ret; - return 0; - } else - return ret; - } - break; case NV50_DISP_MTHD_V1_SOR_HDA_ELD: { union { struct nv50_disp_sor_hda_eld_v0 v0; @@ -148,18 +125,18 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } else return ret; - if (!ior->func->hda.hpd) + if (!ior->hda) return -ENODEV; if (size && args->v0.data[0]) { if (outp->info.type == DCB_OUTPUT_DP) - ior->func->dp.audio(ior, hidx, true); - ior->func->hda.hpd(ior, hidx, true); - ior->func->hda.eld(ior, hidx, data, size); + ior->func->dp->audio(ior, hidx, true); + ior->func->hda->hpd(ior, hidx, true); + ior->func->hda->eld(ior, hidx, data, size); } else { if (outp->info.type == DCB_OUTPUT_DP) - ior->func->dp.audio(ior, hidx, false); - ior->func->hda.hpd(ior, hidx, false); + ior->func->dp->audio(ior, hidx, false); + ior->func->hda->hpd(ior, hidx, false); } return 0; @@ -227,7 +204,6 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) } break; case NV50_DISP_MTHD_V1_SOR_DP_MST_LINK: { - struct nvkm_dp *dp = nvkm_dp(outp); union { struct nv50_disp_sor_dp_mst_link_v0 v0; } *args = data; @@ -236,7 +212,7 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { nvif_ioctl(object, "disp sor dp mst link vers %d state %d\n", args->v0.version, args->v0.state); - dp->lt.mst = !!args->v0.state; + outp->dp.lt.mst = !!args->v0.state; return 0; } else return ret; @@ -254,9 +230,9 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) args->v0.version, args->v0.start_slot, args->v0.num_slots, args->v0.pbn, args->v0.aligned_pbn); - if (!outp->ior->func->dp.vcpi) + if (!outp->ior->func->dp->vcpi) return -ENODEV; - outp->ior->func->dp.vcpi(outp->ior, hidx, + outp->ior->func->dp->vcpi(outp->ior, hidx, args->v0.start_slot, args->v0.num_slots, args->v0.pbn, @@ -272,89 +248,3 @@ nv50_disp_root_mthd_(struct nvkm_object *object, u32 mthd, void *data, u32 size) return -EINVAL; } - -static int -nv50_disp_root_child_new_(const struct nvkm_oclass *oclass, - void *argv, u32 argc, struct nvkm_object **pobject) -{ - struct nv50_disp *disp = nv50_disp_root(oclass->parent)->disp; - const struct nv50_disp_user *user = oclass->priv; - return user->ctor(oclass, argv, argc, disp, pobject); -} - -static int -nv50_disp_root_child_get_(struct nvkm_object *object, int index, - struct nvkm_oclass *sclass) -{ - struct nv50_disp_root *root = nv50_disp_root(object); - - if (root->func->user[index].ctor) { - sclass->base = root->func->user[index].base; - sclass->priv = root->func->user + index; - sclass->ctor = nv50_disp_root_child_new_; - return 0; - } - - return -EINVAL; -} - -static void * -nv50_disp_root_dtor_(struct nvkm_object *object) -{ - struct nv50_disp_root *root = nv50_disp_root(object); - return root; -} - -static const struct nvkm_object_func -nv50_disp_root_ = { - .dtor = nv50_disp_root_dtor_, - .mthd = nv50_disp_root_mthd_, - .ntfy = nvkm_disp_ntfy, - .sclass = nv50_disp_root_child_get_, -}; - -int -nv50_disp_root_new_(const struct nv50_disp_root_func *func, - struct nvkm_disp *base, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - struct nv50_disp *disp = nv50_disp(base); - struct nv50_disp_root *root; - - if (!(root = kzalloc(sizeof(*root), GFP_KERNEL))) - return -ENOMEM; - *pobject = &root->object; - - nvkm_object_ctor(&nv50_disp_root_, oclass, &root->object); - root->func = func; - root->disp = disp; - return 0; -} - -static const struct nv50_disp_root_func -nv50_disp_root = { - .user = { - {{0,0,NV50_DISP_CURSOR }, nv50_disp_curs_new }, - {{0,0,NV50_DISP_OVERLAY }, nv50_disp_oimm_new }, - {{0,0,NV50_DISP_BASE_CHANNEL_DMA }, nv50_disp_base_new }, - {{0,0,NV50_DISP_CORE_CHANNEL_DMA }, nv50_disp_core_new }, - {{0,0,NV50_DISP_OVERLAY_CHANNEL_DMA}, nv50_disp_ovly_new }, - {} - }, -}; - -static int -nv50_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&nv50_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -nv50_disp_root_oclass = { - .base.oclass = NV50_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = nv50_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h deleted file mode 100644 index 27bb170d0293..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/rootnv50.h +++ /dev/null @@ -1,45 +0,0 @@ -/* SPDX-License-Identifier: MIT */ -#ifndef __NV50_DISP_ROOT_H__ -#define __NV50_DISP_ROOT_H__ -#define nv50_disp_root(p) container_of((p), struct nv50_disp_root, object) -#include <core/object.h> -#include "nv50.h" - -struct nv50_disp_root { - const struct nv50_disp_root_func *func; - struct nv50_disp *disp; - struct nvkm_object object; -}; - -struct nv50_disp_root_func { - int blah; - struct nv50_disp_user { - struct nvkm_sclass base; - int (*ctor)(const struct nvkm_oclass *, void *argv, u32 argc, - struct nv50_disp *, struct nvkm_object **); - } user[]; -}; - -int nv50_disp_root_new_(const struct nv50_disp_root_func *, struct nvkm_disp *, - const struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); - -int gv100_disp_caps_new(const struct nvkm_oclass *, void *, u32, - struct nv50_disp *, struct nvkm_object **); - -extern const struct nvkm_disp_oclass nv50_disp_root_oclass; -extern const struct nvkm_disp_oclass g84_disp_root_oclass; -extern const struct nvkm_disp_oclass g94_disp_root_oclass; -extern const struct nvkm_disp_oclass gt200_disp_root_oclass; -extern const struct nvkm_disp_oclass gt215_disp_root_oclass; -extern const struct nvkm_disp_oclass gf119_disp_root_oclass; -extern const struct nvkm_disp_oclass gk104_disp_root_oclass; -extern const struct nvkm_disp_oclass gk110_disp_root_oclass; -extern const struct nvkm_disp_oclass gm107_disp_root_oclass; -extern const struct nvkm_disp_oclass gm200_disp_root_oclass; -extern const struct nvkm_disp_oclass gp100_disp_root_oclass; -extern const struct nvkm_disp_oclass gp102_disp_root_oclass; -extern const struct nvkm_disp_oclass gv100_disp_root_oclass; -extern const struct nvkm_disp_oclass tu102_disp_root_oclass; -extern const struct nvkm_disp_oclass ga102_disp_root_oclass; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu102.c deleted file mode 100644 index d8719d38b98a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/roottu102.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "rootnv50.h" -#include "channv50.h" - -#include <nvif/class.h> - -static const struct nv50_disp_root_func -tu102_disp_root = { - .user = { - {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, - {{0,0,TU102_DISP_CURSOR }, gv100_disp_curs_new }, - {{0,0,TU102_DISP_WINDOW_IMM_CHANNEL_DMA}, gv100_disp_wimm_new }, - {{0,0,TU102_DISP_CORE_CHANNEL_DMA }, gv100_disp_core_new }, - {{0,0,TU102_DISP_WINDOW_CHANNEL_DMA }, gv100_disp_wndw_new }, - {} - }, -}; - -static int -tu102_disp_root_new(struct nvkm_disp *disp, const struct nvkm_oclass *oclass, - void *data, u32 size, struct nvkm_object **pobject) -{ - return nv50_disp_root_new_(&tu102_disp_root, disp, oclass, - data, size, pobject); -} - -const struct nvkm_disp_oclass -tu102_disp_root_oclass = { - .base.oclass = TU102_DISP, - .base.minver = -1, - .base.maxver = -1, - .ctor = tu102_disp_root_new, -}; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c deleted file mode 100644 index ec3a7db08118..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg84.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -static const struct nvkm_ior_func -g84_sor = { - .state = nv50_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = g84_hdmi_ctrl, - }, -}; - -int -g84_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&g84_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c deleted file mode 100644 index 56b8f4411988..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorg94.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -g94_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - nvkm_mask(device, 0x61c128 + loff, 0x0000003f, watermark); -} - -void -g94_sor_dp_activesym(struct nvkm_ior *sor, int head, - u8 TU, u8 VTUa, u8 VTUf, u8 VTUi) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - nvkm_mask(device, 0x61c10c + loff, 0x000001fc, TU << 2); - nvkm_mask(device, 0x61c128 + loff, 0x010f7f00, VTUa << 24 | - VTUf << 16 | - VTUi << 8); -} - -void -g94_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - nvkm_mask(device, 0x61c1e8 + soff, 0x0000ffff, h); - nvkm_mask(device, 0x61c1ec + soff, 0x00ffffff, v); -} - -void -g94_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[3]; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x0000ff00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); -} - -void -g94_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - u32 data; - - switch (pattern) { - case 0: data = 0x00001000; break; - case 1: data = 0x01000000; break; - case 2: data = 0x02000000; break; - default: - WARN_ON(1); - return; - } - - nvkm_mask(device, 0x61c10c + loff, 0x0f001000, data); -} - -void -g94_sor_dp_power(struct nvkm_ior *sor, int nr) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 mask = 0, i; - - for (i = 0; i < nr; i++) - mask |= 1 << sor->func->dp.lanes[i]; - - nvkm_mask(device, 0x61c130 + loff, 0x0000000f, mask); - nvkm_mask(device, 0x61c034 + soff, 0x80000000, 0x80000000); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c034 + soff) & 0x80000000)) - break; - ); -} - -int -g94_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.ef) - dpctrl |= 0x00004000; - if (sor->dp.bw > 0x06) - clksor |= 0x00040000; - - nvkm_mask(device, 0x614300 + soff, 0x000c0000, clksor); - nvkm_mask(device, 0x61c10c + loff, 0x001f4000, dpctrl); - return 0; -} - -static bool -g94_sor_war_needed(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - if (sor->asy.proto == TMDS) { - switch (nvkm_rd32(device, 0x614300 + soff) & 0x00030000) { - case 0x00000000: - case 0x00030000: - return true; - default: - break; - } - } - return false; -} - -static void -g94_sor_war_update_sppll1(struct nvkm_disp *disp) -{ - struct nvkm_device *device = disp->engine.subdev.device; - struct nvkm_ior *ior; - bool used = false; - u32 clksor; - - list_for_each_entry(ior, &disp->ior, head) { - if (ior->type != SOR) - continue; - - clksor = nvkm_rd32(device, 0x614300 + nv50_ior_base(ior)); - switch (clksor & 0x03000000) { - case 0x02000000: - case 0x03000000: - used = true; - break; - default: - break; - } - } - - if (used) - return; - - nvkm_mask(device, 0x00e840, 0x80000000, 0x00000000); -} - -static void -g94_sor_war_3(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 sorpwr; - - if (!g94_sor_war_needed(sor)) - return; - - sorpwr = nvkm_rd32(device, 0x61c004 + soff); - if (sorpwr & 0x00000001) { - u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); - u32 pd_pc = (seqctl & 0x00000f00) >> 8; - u32 pu_pc = seqctl & 0x0000000f; - - nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x1f008000); - - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); - nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000000); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); - - nvkm_wr32(device, 0x61c040 + soff + pd_pc * 4, 0x00002000); - nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f000000); - } - - nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000000); - nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x00000000); - - if (sorpwr & 0x00000001) { - nvkm_mask(device, 0x61c004 + soff, 0x80000001, 0x80000001); - } - - g94_sor_war_update_sppll1(sor->disp); -} - -static void -g94_sor_war_2(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - - if (!g94_sor_war_needed(sor)) - return; - - nvkm_mask(device, 0x00e840, 0x80000000, 0x80000000); - nvkm_mask(device, 0x614300 + soff, 0x03000000, 0x03000000); - nvkm_mask(device, 0x61c10c + soff, 0x00000001, 0x00000001); - - nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x00000000); - nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x14000000); - nvkm_usec(device, 400, NVKM_DELAY); - nvkm_mask(device, 0x61c008 + soff, 0xff000000, 0x00000000); - nvkm_mask(device, 0x61c00c + soff, 0x0f000000, 0x01000000); - - if (nvkm_rd32(device, 0x61c004 + soff) & 0x00000001) { - u32 seqctl = nvkm_rd32(device, 0x61c030 + soff); - u32 pu_pc = seqctl & 0x0000000f; - nvkm_wr32(device, 0x61c040 + soff + pu_pc * 4, 0x1f008000); - } -} - -void -g94_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610794 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; - nv50_pior_depth(sor, state, ctrl); -} - -static const struct nvkm_ior_func -g94_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .war_2 = g94_sor_war_2, - .war_3 = g94_sor_war_3, - .dp = { - .lanes = { 2, 1, 0, 3}, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, -}; - -int -g94_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&g94_sor, disp, SOR, id); -} - -int -g94_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x0f000000) >> 24; - return 4; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c deleted file mode 100644 index d2c05f5c4aa0..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorga102.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2021 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -#include <subdev/timer.h> - -static int -ga102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - switch (sor->dp.bw) { - case 0x06: clksor |= 0x00000000; break; - case 0x0a: clksor |= 0x00040000; break; - case 0x14: clksor |= 0x00080000; break; - case 0x1e: clksor |= 0x000c0000; break; - case 0x08: clksor |= 0x00100000; break; - case 0x09: clksor |= 0x00140000; break; - case 0x0c: clksor |= 0x00180000; break; - case 0x10: clksor |= 0x001c0000; break; - default: - WARN_ON(1); - return -EINVAL; - } - - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.mst) - dpctrl |= 0x40000000; - if (sor->dp.ef) - dpctrl |= 0x00004000; - - nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); - - /*XXX*/ - nvkm_msec(device, 40, NVKM_DELAY); - nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000); - nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001); - - nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); - return 0; -} - -static void -ga102_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - u32 div2 = 0; - if (sor->asy.proto == TMDS) { - if (sor->tmds.high_speed) - div2 = 1; - } - nvkm_wr32(device, 0x00ec08 + (sor->id * 0x10), 0x00000000); - nvkm_wr32(device, 0x00ec04 + (sor->id * 0x10), div2); -} - -static const struct nvkm_ior_func -ga102_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = ga102_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = ga102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -ga102_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = ga102_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = ga102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -ga102_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda = nvkm_rd32(device, 0x08a15c); - if (hda & BIT(id)) - return nvkm_ior_new_(&ga102_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&ga102_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c deleted file mode 100644 index c431e0b9fc11..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgf119.c +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -gf119_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616610 + hoff, 0x0800003f, 0x08000000 | watermark); -} - -void -gf119_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616620 + hoff, 0x0000ffff, h); - nvkm_mask(device, 0x616624 + hoff, 0x00ffffff, v); -} - -void -gf119_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x616618 + hoff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x616618 + hoff) & 0x80000000)) - break; - ); -} - -void -gf119_sor_dp_vcpi(struct nvkm_ior *sor, int head, - u8 slot, u8 slot_nr, u16 pbn, u16 aligned) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - - nvkm_mask(device, 0x616588 + hoff, 0x00003f3f, (slot_nr << 8) | slot); - nvkm_mask(device, 0x61658c + hoff, 0xffffffff, (aligned << 16) | pbn); -} - -void -gf119_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[4]; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x0000ff00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x0000ff00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); - data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); - nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); -} - -void -gf119_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 data; - - switch (pattern) { - case 0: data = 0x10101010; break; - case 1: data = 0x01010101; break; - case 2: data = 0x02020202; break; - case 3: data = 0x03030303; break; - default: - WARN_ON(1); - return; - } - - nvkm_mask(device, 0x61c110 + soff, 0x1f1f1f1f, data); -} - -int -gf119_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - clksor |= sor->dp.bw << 18; - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.mst) - dpctrl |= 0x40000000; - if (sor->dp.ef) - dpctrl |= 0x00004000; - - nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); - nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); - return 0; -} - -void -gf119_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 div1 = sor->asy.link == 3; - u32 div2 = sor->asy.link == 3; - if (sor->asy.proto == TMDS) { - const u32 speed = sor->tmds.high_speed ? 0x14 : 0x0a; - nvkm_mask(device, 0x612300 + soff, 0x007c0000, speed << 18); - if (sor->tmds.high_speed) - div2 = 1; - } - nvkm_mask(device, 0x612300 + soff, 0x00000707, (div2 << 8) | div1); -} - -void -gf119_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = (state == &sor->asy) * 0x20000 + sor->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x640200 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x0000000f; -} - -static const struct nvkm_ior_func -gf119_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gf119_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gf119_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gf119_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gf119_sor, disp, SOR, id); -} - -int -gf119_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x612004) & 0x0000ff00) >> 8; - return 8; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c deleted file mode 100644 index 0c0925680790..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgk104.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -static const struct nvkm_ior_func -gk104_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gf119_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gk104_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gk104_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c deleted file mode 100644 index 3696bfd3bfd7..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm107.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2016 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs <bskeggs@redhat.com> - */ -#include "ior.h" - -void -gm107_sor_dp_pattern(struct nvkm_ior *sor, int pattern) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - u32 mask = 0x1f1f1f1f, data; - - switch (pattern) { - case 0: data = 0x10101010; break; - case 1: data = 0x01010101; break; - case 2: data = 0x02020202; break; - case 3: data = 0x03030303; break; - case 4: data = 0x1b1b1b1b; break; - default: - WARN_ON(1); - return; - } - - if (sor->asy.link & 1) - nvkm_mask(device, 0x61c110 + soff, mask, data); - else - nvkm_mask(device, 0x61c12c + soff, mask, data); -} - -static const struct nvkm_ior_func -gm107_sor = { - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gf119_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -int -gm107_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&gm107_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c deleted file mode 100644 index 4dd7f382968e..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgm200.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -void -gm200_sor_dp_drive(struct nvkm_ior *sor, int ln, int pc, int dc, int pe, int pu) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 loff = nv50_sor_link(sor); - const u32 shift = sor->func->dp.lanes[ln] * 8; - u32 data[4]; - - pu &= 0x0f; - - data[0] = nvkm_rd32(device, 0x61c118 + loff) & ~(0x000000ff << shift); - data[1] = nvkm_rd32(device, 0x61c120 + loff) & ~(0x000000ff << shift); - data[2] = nvkm_rd32(device, 0x61c130 + loff); - if ((data[2] & 0x00000f00) < (pu << 8) || ln == 0) - data[2] = (data[2] & ~0x00000f00) | (pu << 8); - nvkm_wr32(device, 0x61c118 + loff, data[0] | (dc << shift)); - nvkm_wr32(device, 0x61c120 + loff, data[1] | (pe << shift)); - nvkm_wr32(device, 0x61c130 + loff, data[2]); - data[3] = nvkm_rd32(device, 0x61c13c + loff) & ~(0x000000ff << shift); - nvkm_wr32(device, 0x61c13c + loff, data[3] | (pc << shift)); -} - -void -gm200_sor_route_set(struct nvkm_outp *outp, struct nvkm_ior *ior) -{ - struct nvkm_device *device = outp->disp->engine.subdev.device; - const u32 moff = __ffs(outp->info.or) * 0x100; - const u32 sor = ior ? ior->id + 1 : 0; - u32 link = ior ? (ior->asy.link == 2) : 0; - - if (outp->info.sorconf.link & 1) { - nvkm_mask(device, 0x612308 + moff, 0x0000001f, link << 4 | sor); - link++; - } - - if (outp->info.sorconf.link & 2) - nvkm_mask(device, 0x612388 + moff, 0x0000001f, link << 4 | sor); -} - -int -gm200_sor_route_get(struct nvkm_outp *outp, int *link) -{ - struct nvkm_device *device = outp->disp->engine.subdev.device; - const int sublinks = outp->info.sorconf.link; - int lnk[2], sor[2], m, s; - - for (*link = 0, m = __ffs(outp->info.or) * 2, s = 0; s < 2; m++, s++) { - if (sublinks & BIT(s)) { - u32 data = nvkm_rd32(device, 0x612308 + (m * 0x80)); - lnk[s] = (data & 0x00000010) >> 4; - sor[s] = (data & 0x0000000f); - if (!sor[s]) - return -1; - *link |= lnk[s]; - } - } - - if (sublinks == 3) { - if (sor[0] != sor[1] || WARN_ON(lnk[0] || !lnk[1])) - return -1; - } - - return ((sublinks & 1) ? sor[0] : sor[1]) - 1; -} - -static const struct nvkm_ior_func -gm200_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gm200_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, -}; - -int -gm200_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x101034); - - if (hda & BIT(id)) - return nvkm_ior_new_(&gm200_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gm200_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c deleted file mode 100644 index c54f88317a07..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgp100.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2020 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -static const struct nvkm_ior_func -gp100_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gf119_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gp100_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gf119_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gk104_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = gf119_sor_dp_vcpi, - .audio = gf119_sor_dp_audio, - .audio_sym = gf119_sor_dp_audio_sym, - .watermark = gf119_sor_dp_watermark, - }, -}; - -int -gp100_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x10ebb0) >> 8; - - if (hda & BIT(id)) - return nvkm_ior_new_(&gp100_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gp100_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c deleted file mode 100644 index 54d134d4ca1d..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgt215.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -gt215_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x61c1e0 + soff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c1e0 + soff) & 0x80000000)) - break; - ); -} - -static const struct nvkm_ior_func -gt215_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = gt215_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3 }, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio = gt215_sor_dp_audio, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, - .hda = { - .hpd = gt215_hda_hpd, - .eld = gt215_hda_eld, - }, -}; - -int -gt215_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(>215_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c deleted file mode 100644 index 4441187e8ec9..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sorgv100.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -gv100_sor_dp_watermark(struct nvkm_ior *sor, int head, u8 watermark) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616550 + hoff, 0x0c00003f, 0x08000000 | watermark); -} - -void -gv100_sor_dp_audio_sym(struct nvkm_ior *sor, int head, u16 h, u32 v) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - nvkm_mask(device, 0x616568 + hoff, 0x0000ffff, h); - nvkm_mask(device, 0x61656c + hoff, 0x00ffffff, v); -} - -void -gv100_sor_dp_audio(struct nvkm_ior *sor, int head, bool enable) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = 0x800 * head; - const u32 data = 0x80000000 | (0x00000001 * enable); - const u32 mask = 0x8000000d; - nvkm_mask(device, 0x616560 + hoff, mask, data); - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x616560 + hoff) & 0x80000000)) - break; - ); -} - -void -gv100_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = (state == &sor->arm) * 0x8000 + sor->id * 0x20; - u32 ctrl = nvkm_rd32(device, 0x680300 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - case 8: state->proto = DP; state->link = 1; break; - case 9: state->proto = DP; state->link = 2; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x000000ff; -} - -static const struct nvkm_ior_func -gv100_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -gv100_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = gf119_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -gv100_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda; - - if (!((hda = nvkm_rd32(device, 0x08a15c)) & 0x40000000)) - hda = nvkm_rd32(device, 0x118fb0) >> 8; - - if (hda & BIT(id)) - return nvkm_ior_new_(&gv100_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&gv100_sor, disp, SOR, id); -} - -int -gv100_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610060) & 0x0000ff00) >> 8; - return (nvkm_rd32(device, 0x610074) & 0x00000f00) >> 8; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c deleted file mode 100644 index 8a70dd25b13a..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp77.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -static const struct nvkm_ior_func -mcp77_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = g84_hdmi_ctrl, - }, - .dp = { - .lanes = { 2, 1, 0, 3}, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, -}; - -int -mcp77_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&mcp77_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c deleted file mode 100644 index eac9c5be9166..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sormcp89.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2017 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -static const struct nvkm_ior_func -mcp89_sor = { - .state = g94_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, - .hdmi = { - .ctrl = gt215_hdmi_ctrl, - }, - .dp = { - .lanes = { 3, 2, 1, 0 }, - .links = g94_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = g94_sor_dp_pattern, - .drive = g94_sor_dp_drive, - .audio = gt215_sor_dp_audio, - .audio_sym = g94_sor_dp_audio_sym, - .activesym = g94_sor_dp_activesym, - .watermark = g94_sor_dp_watermark, - }, - .hda = { - .hpd = gt215_hda_hpd, - .eld = gt215_hda_eld, - }, -}; - -int -mcp89_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&mcp89_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c deleted file mode 100644 index b4729f8798af..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sornv50.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: Ben Skeggs - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -nv50_sor_clock(struct nvkm_ior *sor) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const int div = sor->asy.link == 3; - const u32 soff = nv50_ior_base(sor); - nvkm_mask(device, 0x614300 + soff, 0x00000707, (div << 8) | div); -} - -static void -nv50_sor_power_wait(struct nvkm_device *device, u32 soff) -{ - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c004 + soff) & 0x80000000)) - break; - ); -} - -void -nv50_sor_power(struct nvkm_ior *sor, bool normal, bool pu, - bool data, bool vsync, bool hsync) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 shift = normal ? 0 : 16; - const u32 state = 0x80000000 | (0x00000001 * !!pu) << shift; - const u32 field = 0x80000000 | (0x00000001 << shift); - - nv50_sor_power_wait(device, soff); - nvkm_mask(device, 0x61c004 + soff, field, state); - nv50_sor_power_wait(device, soff); - - nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x61c030 + soff) & 0x10000000)) - break; - ); -} - -void -nv50_sor_state(struct nvkm_ior *sor, struct nvkm_ior_state *state) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 coff = sor->id * 8 + (state == &sor->arm) * 4; - u32 ctrl = nvkm_rd32(device, 0x610b70 + coff); - - state->proto_evo = (ctrl & 0x00000f00) >> 8; - switch (state->proto_evo) { - case 0: state->proto = LVDS; state->link = 1; break; - case 1: state->proto = TMDS; state->link = 1; break; - case 2: state->proto = TMDS; state->link = 2; break; - case 5: state->proto = TMDS; state->link = 3; break; - default: - state->proto = UNKNOWN; - break; - } - - state->head = ctrl & 0x00000003; -} - -static const struct nvkm_ior_func -nv50_sor = { - .state = nv50_sor_state, - .power = nv50_sor_power, - .clock = nv50_sor_clock, -}; - -int -nv50_sor_new(struct nvkm_disp *disp, int id) -{ - return nvkm_ior_new_(&nv50_sor, disp, SOR, id); -} - -int -nv50_sor_cnt(struct nvkm_disp *disp, unsigned long *pmask) -{ - struct nvkm_device *device = disp->engine.subdev.device; - *pmask = (nvkm_rd32(device, 0x610184) & 0x03000000) >> 24; - return 2; -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c deleted file mode 100644 index 0cf9e8752d25..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/sortu102.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "ior.h" - -#include <subdev/timer.h> - -void -tu102_sor_dp_vcpi(struct nvkm_ior *sor, int head, - u8 slot, u8 slot_nr, u16 pbn, u16 aligned) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 hoff = head * 0x800; - - nvkm_mask(device, 0x61657c + hoff, 0xffffffff, (aligned << 16) | pbn); - nvkm_mask(device, 0x616578 + hoff, 0x00003f3f, (slot_nr << 8) | slot); -} - -static int -tu102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) -{ - struct nvkm_device *device = sor->disp->engine.subdev.device; - const u32 soff = nv50_ior_base(sor); - const u32 loff = nv50_sor_link(sor); - u32 dpctrl = 0x00000000; - u32 clksor = 0x00000000; - - clksor |= sor->dp.bw << 18; - dpctrl |= ((1 << sor->dp.nr) - 1) << 16; - if (sor->dp.mst) - dpctrl |= 0x40000000; - if (sor->dp.ef) - dpctrl |= 0x00004000; - - nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); - - /*XXX*/ - nvkm_msec(device, 40, NVKM_DELAY); - nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000); - nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001); - - nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); - return 0; -} - -static const struct nvkm_ior_func -tu102_sor_hda = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = tu102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, - .hda = { - .hpd = gf119_hda_hpd, - .eld = gf119_hda_eld, - .device_entry = gv100_hda_device_entry, - }, -}; - -static const struct nvkm_ior_func -tu102_sor = { - .route = { - .get = gm200_sor_route_get, - .set = gm200_sor_route_set, - }, - .state = gv100_sor_state, - .power = nv50_sor_power, - .clock = gf119_sor_clock, - .hdmi = { - .ctrl = gv100_hdmi_ctrl, - .scdc = gm200_hdmi_scdc, - }, - .dp = { - .lanes = { 0, 1, 2, 3 }, - .links = tu102_sor_dp_links, - .power = g94_sor_dp_power, - .pattern = gm107_sor_dp_pattern, - .drive = gm200_sor_dp_drive, - .vcpi = tu102_sor_dp_vcpi, - .audio = gv100_sor_dp_audio, - .audio_sym = gv100_sor_dp_audio_sym, - .watermark = gv100_sor_dp_watermark, - }, -}; - -int -tu102_sor_new(struct nvkm_disp *disp, int id) -{ - struct nvkm_device *device = disp->engine.subdev.device; - u32 hda = nvkm_rd32(device, 0x08a15c); - if (hda & BIT(id)) - return nvkm_ior_new_(&tu102_sor_hda, disp, SOR, id); - return nvkm_ior_new_(&tu102_sor, disp, SOR, id); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c index f5f8dc8e8f35..e4ad1a6f6c88 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/tu102.c @@ -19,19 +19,96 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ -#include "nv50.h" +#include "chan.h" +#include "priv.h" #include "head.h" #include "ior.h" -#include "channv50.h" -#include "rootnv50.h" #include <core/gpuobj.h> #include <subdev/timer.h> +#include <nvif/class.h> + +void +tu102_sor_dp_vcpi(struct nvkm_ior *sor, int head, u8 slot, u8 slot_nr, u16 pbn, u16 aligned) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 hoff = head * 0x800; + + nvkm_mask(device, 0x61657c + hoff, 0xffffffff, (aligned << 16) | pbn); + nvkm_mask(device, 0x616578 + hoff, 0x00003f3f, (slot_nr << 8) | slot); +} + +static int +tu102_sor_dp_links(struct nvkm_ior *sor, struct nvkm_i2c_aux *aux) +{ + struct nvkm_device *device = sor->disp->engine.subdev.device; + const u32 soff = nv50_ior_base(sor); + const u32 loff = nv50_sor_link(sor); + u32 dpctrl = 0x00000000; + u32 clksor = 0x00000000; + + clksor |= sor->dp.bw << 18; + dpctrl |= ((1 << sor->dp.nr) - 1) << 16; + if (sor->dp.mst) + dpctrl |= 0x40000000; + if (sor->dp.ef) + dpctrl |= 0x00004000; + + nvkm_mask(device, 0x612300 + soff, 0x007c0000, clksor); + + /*XXX*/ + nvkm_msec(device, 40, NVKM_DELAY); + nvkm_mask(device, 0x612300 + soff, 0x00030000, 0x00010000); + nvkm_mask(device, 0x61c10c + loff, 0x00000003, 0x00000001); + + nvkm_mask(device, 0x61c10c + loff, 0x401f4000, dpctrl); + return 0; +} + +static const struct nvkm_ior_func_dp +tu102_sor_dp = { + .lanes = { 0, 1, 2, 3 }, + .links = tu102_sor_dp_links, + .power = g94_sor_dp_power, + .pattern = gm107_sor_dp_pattern, + .drive = gm200_sor_dp_drive, + .vcpi = tu102_sor_dp_vcpi, + .audio = gv100_sor_dp_audio, + .audio_sym = gv100_sor_dp_audio_sym, + .watermark = gv100_sor_dp_watermark, +}; + +static const struct nvkm_ior_func +tu102_sor = { + .route = { + .get = gm200_sor_route_get, + .set = gm200_sor_route_set, + }, + .state = gv100_sor_state, + .power = nv50_sor_power, + .clock = gf119_sor_clock, + .hdmi = { + .ctrl = gv100_sor_hdmi_ctrl, + .scdc = gm200_sor_hdmi_scdc, + }, + .dp = &tu102_sor_dp, + .hda = &gv100_sor_hda, +}; + +static int +tu102_sor_new(struct nvkm_disp *disp, int id) +{ + struct nvkm_device *device = disp->engine.subdev.device; + u32 hda = nvkm_rd32(device, 0x08a15c); + + return nvkm_ior_new_(&tu102_sor, disp, SOR, id, hda & BIT(id)); +} + int -tu102_disp_init(struct nv50_disp *disp) +tu102_disp_init(struct nvkm_disp *disp) { - struct nvkm_device *device = disp->base.engine.subdev.device; + struct nvkm_device *device = disp->engine.subdev.device; struct nvkm_head *head; int i, j; u32 tmp; @@ -58,7 +135,7 @@ tu102_disp_init(struct nv50_disp *disp) } /* Head capabilities. */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const int id = head->id; /* RG. */ @@ -119,7 +196,7 @@ tu102_disp_init(struct nv50_disp *disp) nvkm_wr32(device, 0x611da4, 0x00000000); /* EN. */ /* HEAD_TIMING(n): VBLANK. */ - list_for_each_entry(head, &disp->base.head, head) { + list_for_each_entry(head, &disp->heads, head) { const u32 hoff = head->id * 4; nvkm_wr32(device, 0x611cc0 + hoff, 0x00000004); /* MSK. */ nvkm_wr32(device, 0x611d80 + hoff, 0x00000000); /* EN. */ @@ -131,23 +208,32 @@ tu102_disp_init(struct nv50_disp *disp) return 0; } -static const struct nv50_disp_func +static const struct nvkm_disp_func tu102_disp = { + .oneinit = nv50_disp_oneinit, .init = tu102_disp_init, .fini = gv100_disp_fini, .intr = gv100_disp_intr, - .uevent = &gv100_disp_chan_uevent, .super = gv100_disp_super, - .root = &tu102_disp_root_oclass, + .uevent = &gv100_disp_chan_uevent, .wndw = { .cnt = gv100_disp_wndw_cnt }, .head = { .cnt = gv100_head_cnt, .new = gv100_head_new }, .sor = { .cnt = gv100_sor_cnt, .new = tu102_sor_new }, .ramht_size = 0x2000, + .root = { 0, 0,TU102_DISP }, + .user = { + {{-1,-1,GV100_DISP_CAPS }, gv100_disp_caps_new }, + {{ 0, 0,TU102_DISP_CURSOR }, nvkm_disp_chan_new, &gv100_disp_curs }, + {{ 0, 0,TU102_DISP_WINDOW_IMM_CHANNEL_DMA}, nvkm_disp_wndw_new, &gv100_disp_wimm }, + {{ 0, 0,TU102_DISP_CORE_CHANNEL_DMA }, nvkm_disp_core_new, &gv100_disp_core }, + {{ 0, 0,TU102_DISP_WINDOW_CHANNEL_DMA }, nvkm_disp_wndw_new, &gv100_disp_wndw }, + {} + }, }; int tu102_disp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_disp **pdisp) { - return nv50_disp_new_(&tu102_disp, device, type, inst, pdisp); + return nvkm_disp_new_(&tu102_disp, device, type, inst, pdisp); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c new file mode 100644 index 000000000000..fd9f18144c26 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uconn.c @@ -0,0 +1,117 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#define nvkm_uconn(p) container_of((p), struct nvkm_conn, object) +#include "conn.h" + +#include <subdev/gpio.h> + +#include <nvif/if0011.h> + +static int +nvkm_uconn_mthd_hpd_status(struct nvkm_conn *conn, void *argv, u32 argc) +{ + struct nvkm_gpio *gpio = conn->disp->engine.subdev.device->gpio; + union nvif_conn_hpd_status_args *args = argv; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + args->v0.support = gpio && conn->info.hpd != DCB_GPIO_UNUSED; + args->v0.present = 0; + + if (args->v0.support) { + int ret = nvkm_gpio_get(gpio, 0, DCB_GPIO_UNUSED, conn->info.hpd); + + if (WARN_ON(ret < 0)) { + args->v0.support = false; + return 0; + } + + args->v0.present = ret; + } + + return 0; +} + +static int +nvkm_uconn_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_conn *conn = nvkm_uconn(object); + + switch (mthd) { + case NVIF_CONN_V0_HPD_STATUS: return nvkm_uconn_mthd_hpd_status(conn, argv, argc); + default: + break; + } + + return -EINVAL; +} + +static void * +nvkm_uconn_dtor(struct nvkm_object *object) +{ + struct nvkm_conn *conn = nvkm_uconn(object); + struct nvkm_disp *disp = conn->disp; + + spin_lock(&disp->client.lock); + conn->object.func = NULL; + spin_unlock(&disp->client.lock); + return NULL; +} + +static const struct nvkm_object_func +nvkm_uconn = { + .dtor = nvkm_uconn_dtor, + .mthd = nvkm_uconn_mthd, +}; + +int +nvkm_uconn_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + struct nvkm_conn *cont, *conn = NULL; + union nvif_conn_args *args = argv; + int ret; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + list_for_each_entry(cont, &disp->conns, head) { + if (cont->index == args->v0.id) { + conn = cont; + break; + } + } + + if (!conn) + return -EINVAL; + + ret = -EBUSY; + spin_lock(&disp->client.lock); + if (!conn->object.func) { + nvkm_object_ctor(&nvkm_uconn, oclass, &conn->object); + *pobject = &conn->object; + ret = 0; + } + spin_unlock(&disp->client.lock); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c new file mode 100644 index 000000000000..0841e7ce0343 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/udisp.c @@ -0,0 +1,115 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "priv.h" +#include "conn.h" +#include "outp.h" + +#include <nvif/class.h> +#include <nvif/if0010.h> + +static int +nvkm_udisp_sclass(struct nvkm_object *object, int index, struct nvkm_oclass *sclass) +{ + struct nvkm_disp *disp = nvkm_udisp(object); + + if (index-- == 0) { + sclass->base = (struct nvkm_sclass) { 0, 0, NVIF_CLASS_CONN }; + sclass->ctor = nvkm_uconn_new; + return 0; + } + + if (index-- == 0) { + sclass->base = (struct nvkm_sclass) { 0, 0, NVIF_CLASS_OUTP }; + sclass->ctor = nvkm_uoutp_new; + return 0; + } + + if (disp->func->user[index].ctor) { + sclass->base = disp->func->user[index].base; + sclass->ctor = disp->func->user[index].ctor; + return 0; + } + + return -EINVAL; +} + +static int +nvkm_udisp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_disp *disp = nvkm_udisp(object); + + if (disp->engine.subdev.device->card_type >= NV_50) + return nv50_disp_root_mthd_(object, mthd, argv, argc); + + return nv04_disp_mthd(object, mthd, argv, argc); +} + +static void * +nvkm_udisp_dtor(struct nvkm_object *object) +{ + struct nvkm_disp *disp = nvkm_udisp(object); + + spin_lock(&disp->client.lock); + if (object == &disp->client.object) + disp->client.object.func = NULL; + spin_unlock(&disp->client.lock); + return NULL; +} + +static const struct nvkm_object_func +nvkm_udisp = { + .dtor = nvkm_udisp_dtor, + .mthd = nvkm_udisp_mthd, + .ntfy = nvkm_disp_ntfy, + .sclass = nvkm_udisp_sclass, +}; + +int +nvkm_udisp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_disp(oclass->engine); + struct nvkm_conn *conn; + struct nvkm_outp *outp; + union nvif_disp_args *args = argv; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + spin_lock(&disp->client.lock); + if (disp->client.object.func) { + spin_unlock(&disp->client.lock); + return -EBUSY; + } + nvkm_object_ctor(&nvkm_udisp, oclass, &disp->client.object); + *pobject = &disp->client.object; + spin_unlock(&disp->client.lock); + + args->v0.conn_mask = 0; + list_for_each_entry(conn, &disp->conns, head) + args->v0.conn_mask |= BIT(conn->index); + + args->v0.outp_mask = 0; + list_for_each_entry(outp, &disp->outps, head) + args->v0.outp_mask |= BIT(outp->index); + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c new file mode 100644 index 000000000000..abedb3e86361 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/uoutp.c @@ -0,0 +1,129 @@ +/* + * Copyright 2021 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#define nvkm_uoutp(p) container_of((p), struct nvkm_outp, object) +#include "outp.h" +#include "ior.h" + +#include <nvif/if0012.h> + +static int +nvkm_uoutp_mthd_load_detect(struct nvkm_outp *outp, void *argv, u32 argc) +{ + union nvif_outp_load_detect_args *args = argv; + int ret; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + ret = nvkm_outp_acquire(outp, NVKM_OUTP_PRIV, false); + if (ret == 0) { + if (outp->ior->func->sense) { + ret = outp->ior->func->sense(outp->ior, args->v0.data); + args->v0.load = ret < 0 ? 0 : ret; + } else { + ret = -EINVAL; + } + nvkm_outp_release(outp, NVKM_OUTP_PRIV); + } + + return ret; +} + +static int +nvkm_uoutp_mthd_noacquire(struct nvkm_outp *outp, u32 mthd, void *argv, u32 argc) +{ + switch (mthd) { + case NVIF_OUTP_V0_LOAD_DETECT: return nvkm_uoutp_mthd_load_detect(outp, argv, argc); + default: + break; + } + + return 1; +} + +static int +nvkm_uoutp_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_outp *outp = nvkm_uoutp(object); + struct nvkm_disp *disp = outp->disp; + int ret; + + mutex_lock(&disp->super.mutex); + + ret = nvkm_uoutp_mthd_noacquire(outp, mthd, argv, argc); + if (ret <= 0) + goto done; + +done: + mutex_unlock(&disp->super.mutex); + return ret; +} + +static void * +nvkm_uoutp_dtor(struct nvkm_object *object) +{ + struct nvkm_outp *outp = nvkm_uoutp(object); + struct nvkm_disp *disp = outp->disp; + + spin_lock(&disp->client.lock); + outp->object.func = NULL; + spin_unlock(&disp->client.lock); + return NULL; +} + +static const struct nvkm_object_func +nvkm_uoutp = { + .dtor = nvkm_uoutp_dtor, + .mthd = nvkm_uoutp_mthd, +}; + +int +nvkm_uoutp_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, struct nvkm_object **pobject) +{ + struct nvkm_disp *disp = nvkm_udisp(oclass->parent); + struct nvkm_outp *outt, *outp = NULL; + union nvif_outp_args *args = argv; + int ret; + + if (argc != sizeof(args->v0) || args->v0.version != 0) + return -ENOSYS; + + list_for_each_entry(outt, &disp->outps, head) { + if (outt->index == args->v0.id) { + outp = outt; + break; + } + } + + if (!outp) + return -EINVAL; + + ret = -EBUSY; + spin_lock(&disp->client.lock); + if (!outp->object.func) { + nvkm_object_ctor(&nvkm_uoutp, oclass, &outp->object); + *pobject = &outp->object; + ret = 0; + } + spin_unlock(&disp->client.lock); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c deleted file mode 100644 index bb4db6351ddf..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wimmgv100.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "channv50.h" - -#include <core/client.h> - -#include <nvif/clc37b.h> -#include <nvif/unpack.h> - -static void -gv100_disp_wimm_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00000001 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611da8, mask, data); -} - -static const struct nv50_disp_chan_func -gv100_disp_wimm = { - .init = gv100_disp_dmac_init, - .fini = gv100_disp_dmac_fini, - .intr = gv100_disp_wimm_intr, - .user = gv100_disp_chan_user, -}; - -static int -gv100_disp_wimm_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nvc37b_window_imm_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int wndw, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create window imm channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create window imm channel dma vers %d " - "pushbuf %016llx index %d\n", - args->v0.version, args->v0.pushbuf, args->v0.index); - if (!(disp->wndw.mask & BIT(args->v0.index))) - return -EINVAL; - push = args->v0.pushbuf; - wndw = args->v0.index; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + wndw, - wndw, push, oclass, pobject); -} - -int -gv100_disp_wimm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return gv100_disp_wimm_new_(&gv100_disp_wimm, NULL, disp, 33, - oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c deleted file mode 100644 index e635247d794f..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/wndwgv100.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright 2018 Red Hat Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ -#include "channv50.h" - -#include <core/client.h> - -#include <nvif/clc37e.h> -#include <nvif/unpack.h> - -static const struct nv50_disp_mthd_list -gv100_disp_wndw_mthd_base = { - .mthd = 0x0000, - .addr = 0x000000, - .data = { - { 0x0200, 0x690200 }, - { 0x020c, 0x69020c }, - { 0x0210, 0x690210 }, - { 0x0214, 0x690214 }, - { 0x0218, 0x690218 }, - { 0x021c, 0x69021c }, - { 0x0220, 0x690220 }, - { 0x0224, 0x690224 }, - { 0x0228, 0x690228 }, - { 0x022c, 0x69022c }, - { 0x0230, 0x690230 }, - { 0x0234, 0x690234 }, - { 0x0238, 0x690238 }, - { 0x0240, 0x690240 }, - { 0x0244, 0x690244 }, - { 0x0248, 0x690248 }, - { 0x024c, 0x69024c }, - { 0x0250, 0x690250 }, - { 0x0254, 0x690254 }, - { 0x0260, 0x690260 }, - { 0x0264, 0x690264 }, - { 0x0268, 0x690268 }, - { 0x026c, 0x69026c }, - { 0x0270, 0x690270 }, - { 0x0274, 0x690274 }, - { 0x0280, 0x690280 }, - { 0x0284, 0x690284 }, - { 0x0288, 0x690288 }, - { 0x028c, 0x69028c }, - { 0x0290, 0x690290 }, - { 0x0298, 0x690298 }, - { 0x029c, 0x69029c }, - { 0x02a0, 0x6902a0 }, - { 0x02a4, 0x6902a4 }, - { 0x02a8, 0x6902a8 }, - { 0x02ac, 0x6902ac }, - { 0x02b0, 0x6902b0 }, - { 0x02b4, 0x6902b4 }, - { 0x02b8, 0x6902b8 }, - { 0x02bc, 0x6902bc }, - { 0x02c0, 0x6902c0 }, - { 0x02c4, 0x6902c4 }, - { 0x02c8, 0x6902c8 }, - { 0x02cc, 0x6902cc }, - { 0x02d0, 0x6902d0 }, - { 0x02d4, 0x6902d4 }, - { 0x02d8, 0x6902d8 }, - { 0x02dc, 0x6902dc }, - { 0x02e0, 0x6902e0 }, - { 0x02e4, 0x6902e4 }, - { 0x02e8, 0x6902e8 }, - { 0x02ec, 0x6902ec }, - { 0x02f0, 0x6902f0 }, - { 0x02f4, 0x6902f4 }, - { 0x02f8, 0x6902f8 }, - { 0x02fc, 0x6902fc }, - { 0x0300, 0x690300 }, - { 0x0304, 0x690304 }, - { 0x0308, 0x690308 }, - { 0x0310, 0x690310 }, - { 0x0314, 0x690314 }, - { 0x0318, 0x690318 }, - { 0x031c, 0x69031c }, - { 0x0320, 0x690320 }, - { 0x0324, 0x690324 }, - { 0x0328, 0x690328 }, - { 0x032c, 0x69032c }, - { 0x033c, 0x69033c }, - { 0x0340, 0x690340 }, - { 0x0344, 0x690344 }, - { 0x0348, 0x690348 }, - { 0x034c, 0x69034c }, - { 0x0350, 0x690350 }, - { 0x0354, 0x690354 }, - { 0x0358, 0x690358 }, - { 0x0364, 0x690364 }, - { 0x0368, 0x690368 }, - { 0x036c, 0x69036c }, - { 0x0370, 0x690370 }, - { 0x0374, 0x690374 }, - { 0x0380, 0x690380 }, - {} - } -}; - -static const struct nv50_disp_chan_mthd -gv100_disp_wndw_mthd = { - .name = "Window", - .addr = 0x001000, - .prev = 0x000800, - .data = { - { "Global", 1, &gv100_disp_wndw_mthd_base }, - {} - } -}; - -static void -gv100_disp_wndw_intr(struct nv50_disp_chan *chan, bool en) -{ - struct nvkm_device *device = chan->disp->base.engine.subdev.device; - const u32 mask = 0x00000001 << chan->head; - const u32 data = en ? mask : 0; - nvkm_mask(device, 0x611da4, mask, data); -} - -static const struct nv50_disp_chan_func -gv100_disp_wndw = { - .init = gv100_disp_dmac_init, - .fini = gv100_disp_dmac_fini, - .intr = gv100_disp_wndw_intr, - .user = gv100_disp_chan_user, - .bind = gv100_disp_dmac_bind, -}; - -static int -gv100_disp_wndw_new_(const struct nv50_disp_chan_func *func, - const struct nv50_disp_chan_mthd *mthd, - struct nv50_disp *disp, int chid, - const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nvkm_object **pobject) -{ - union { - struct nvc37e_window_channel_dma_v0 v0; - } *args = argv; - struct nvkm_object *parent = oclass->parent; - int wndw, ret = -ENOSYS; - u64 push; - - nvif_ioctl(parent, "create window channel dma size %d\n", argc); - if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create window channel dma vers %d " - "pushbuf %016llx index %d\n", - args->v0.version, args->v0.pushbuf, args->v0.index); - if (!(disp->wndw.mask & BIT(args->v0.index))) - return -EINVAL; - push = args->v0.pushbuf; - wndw = args->v0.index; - } else - return ret; - - return nv50_disp_dmac_new_(func, mthd, disp, chid + wndw, - wndw, push, oclass, pobject); -} - -int -gv100_disp_wndw_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, - struct nv50_disp *disp, struct nvkm_object **pobject) -{ - return gv100_disp_wndw_new_(&gv100_disp_wndw, &gv100_disp_wndw_mthd, - disp, 1, oclass, argv, argc, pobject); -} diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index 3626469c4cc2..cdb154c8b866 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -738,7 +738,7 @@ static int generic_edp_panel_probe(struct device *dev, struct panel_edp *panel) of_property_read_u32(dev->of_node, "hpd-reliable-delay-ms", &reliable_ms); desc->delay.hpd_reliable = reliable_ms; of_property_read_u32(dev->of_node, "hpd-absent-delay-ms", &absent_ms); - desc->delay.hpd_reliable = absent_ms; + desc->delay.hpd_absent = absent_ms; /* Power the panel on so we can read the EDID */ ret = pm_runtime_get_sync(dev); diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index 194af7f607a6..5110cd9b2425 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -101,8 +101,7 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) return 0; } - ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names, - pfdev->comp->num_supplies); + ret = devm_pm_opp_set_regulators(dev, pfdev->comp->supply_names); if (ret) { /* Continue if the optional regulator is missing */ if (ret != -ENODEV) { diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index c58075bc096e..2fa5afe21288 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -433,8 +433,8 @@ static int panfrost_ioctl_madvise(struct drm_device *dev, void *data, if (args->retained) { if (args->madv == PANFROST_MADV_DONTNEED) - list_add_tail(&bo->base.madv_list, - &pfdev->shrinker_list); + list_move_tail(&bo->base.madv_list, + &pfdev->shrinker_list); else if (args->madv == PANFROST_MADV_WILLNEED) list_del_init(&bo->base.madv_list); } @@ -626,24 +626,29 @@ static int panfrost_remove(struct platform_device *pdev) return 0; } -static const char * const default_supplies[] = { "mali" }; +/* + * The OPP core wants the supply names to be NULL terminated, but we need the + * correct num_supplies value for regulator core. Hence, we NULL terminate here + * and then initialize num_supplies with ARRAY_SIZE - 1. + */ +static const char * const default_supplies[] = { "mali", NULL }; static const struct panfrost_compatible default_data = { - .num_supplies = ARRAY_SIZE(default_supplies), + .num_supplies = ARRAY_SIZE(default_supplies) - 1, .supply_names = default_supplies, .num_pm_domains = 1, /* optional */ .pm_domain_names = NULL, }; static const struct panfrost_compatible amlogic_data = { - .num_supplies = ARRAY_SIZE(default_supplies), + .num_supplies = ARRAY_SIZE(default_supplies) - 1, .supply_names = default_supplies, .vendor_quirk = panfrost_gpu_amlogic_quirk, }; -static const char * const mediatek_mt8183_supplies[] = { "mali", "sram" }; +static const char * const mediatek_mt8183_supplies[] = { "mali", "sram", NULL }; static const char * const mediatek_mt8183_pm_domains[] = { "core0", "core1", "core2" }; static const struct panfrost_compatible mediatek_mt8183_data = { - .num_supplies = ARRAY_SIZE(mediatek_mt8183_supplies), + .num_supplies = ARRAY_SIZE(mediatek_mt8183_supplies) - 1, .supply_names = mediatek_mt8183_supplies, .num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains), .pm_domain_names = mediatek_mt8183_pm_domains, diff --git a/drivers/gpu/drm/panfrost/panfrost_mmu.c b/drivers/gpu/drm/panfrost/panfrost_mmu.c index d3f82b26a631..b285a8001b1d 100644 --- a/drivers/gpu/drm/panfrost/panfrost_mmu.c +++ b/drivers/gpu/drm/panfrost/panfrost_mmu.c @@ -518,7 +518,7 @@ err_map: err_pages: drm_gem_shmem_put_pages(&bo->base); err_bo: - drm_gem_object_put(&bo->base.base); + panfrost_gem_mapping_put(bomapping); return ret; } diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.c b/drivers/gpu/drm/rcar-du/rcar_cmm.c index 382d53f8a22e..e2a67dda4658 100644 --- a/drivers/gpu/drm/rcar-du/rcar_cmm.c +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * rcar_cmm.c -- R-Car Display Unit Color Management Module + * R-Car Display Unit Color Management Module * * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org> */ diff --git a/drivers/gpu/drm/rcar-du/rcar_cmm.h b/drivers/gpu/drm/rcar-du/rcar_cmm.h index b5f7ec6db04a..628072acc98b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_cmm.h +++ b/drivers/gpu/drm/rcar-du/rcar_cmm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_cmm.h -- R-Car Display Unit Color Management Module + * R-Car Display Unit Color Management Module * * Copyright (C) 2019 Jacopo Mondi <jacopo+renesas@jmondi.org> */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c index f361a604337f..621bbccb95d4 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * rcar_du_crtc.c -- R-Car Display Unit CRTCs + * R-Car Display Unit CRTCs * * Copyright (C) 2013-2015 Renesas Electronics Corporation * @@ -300,6 +300,11 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) | DSMR_DIPM_DISP | DSMR_CSPM; rcar_du_crtc_write(rcrtc, DSMR, dsmr); + /* + * When the CMM is enabled, an additional offset of 25 pixels must be + * subtracted from the HDS (horizontal display start) and HDE + * (horizontal display end) registers. + */ hdse_offset = 19; if (rcrtc->group->cmms_mask & BIT(rcrtc->index % 2)) hdse_offset += 25; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h index 66e8839db708..d0f38a8b3561 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_du_crtc.h -- R-Car Display Unit CRTCs + * R-Car Display Unit CRTCs * * Copyright (C) 2013-2015 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 957ea97541d5..70d85610d720 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * rcar_du_drv.c -- R-Car Display Unit DRM driver + * R-Car Display Unit DRM driver * * Copyright (C) 2013-2015 Renesas Electronics Corporation * @@ -55,6 +55,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7743_info = { }, }, .num_lvds = 1, + .num_rpf = 4, }; static const struct rcar_du_device_info rzg1_du_r8a7745_info = { @@ -77,6 +78,7 @@ static const struct rcar_du_device_info rzg1_du_r8a7745_info = { .port = 1, }, }, + .num_rpf = 4, }; static const struct rcar_du_device_info rzg1_du_r8a77470_info = { @@ -104,6 +106,7 @@ static const struct rcar_du_device_info rzg1_du_r8a77470_info = { .port = 2, }, }, + .num_rpf = 4, }; static const struct rcar_du_device_info rcar_du_r8a774a1_info = { @@ -133,6 +136,7 @@ static const struct rcar_du_device_info rcar_du_r8a774a1_info = { }, }, .num_lvds = 1, + .num_rpf = 5, .dpll_mask = BIT(1), }; @@ -163,6 +167,7 @@ static const struct rcar_du_device_info rcar_du_r8a774b1_info = { }, }, .num_lvds = 1, + .num_rpf = 5, .dpll_mask = BIT(1), }; @@ -190,6 +195,7 @@ static const struct rcar_du_device_info rcar_du_r8a774c0_info = { }, }, .num_lvds = 2, + .num_rpf = 4, .lvds_clk_mask = BIT(1) | BIT(0), }; @@ -220,6 +226,7 @@ static const struct rcar_du_device_info rcar_du_r8a774e1_info = { }, }, .num_lvds = 1, + .num_rpf = 5, .dpll_mask = BIT(1), }; @@ -272,6 +279,7 @@ static const struct rcar_du_device_info rcar_du_r8a7790_info = { }, }, .num_lvds = 2, + .num_rpf = 4, }; /* M2-W (r8a7791) and M2-N (r8a7793) are identical */ @@ -297,6 +305,7 @@ static const struct rcar_du_device_info rcar_du_r8a7791_info = { }, }, .num_lvds = 1, + .num_rpf = 4, }; static const struct rcar_du_device_info rcar_du_r8a7792_info = { @@ -317,6 +326,7 @@ static const struct rcar_du_device_info rcar_du_r8a7792_info = { .port = 1, }, }, + .num_rpf = 4, }; static const struct rcar_du_device_info rcar_du_r8a7794_info = { @@ -340,6 +350,7 @@ static const struct rcar_du_device_info rcar_du_r8a7794_info = { .port = 1, }, }, + .num_rpf = 4, }; static const struct rcar_du_device_info rcar_du_r8a7795_info = { @@ -373,6 +384,7 @@ static const struct rcar_du_device_info rcar_du_r8a7795_info = { }, }, .num_lvds = 1, + .num_rpf = 5, .dpll_mask = BIT(2) | BIT(1), }; @@ -403,6 +415,7 @@ static const struct rcar_du_device_info rcar_du_r8a7796_info = { }, }, .num_lvds = 1, + .num_rpf = 5, .dpll_mask = BIT(1), }; @@ -433,6 +446,7 @@ static const struct rcar_du_device_info rcar_du_r8a77965_info = { }, }, .num_lvds = 1, + .num_rpf = 5, .dpll_mask = BIT(1), }; @@ -459,6 +473,7 @@ static const struct rcar_du_device_info rcar_du_r8a77970_info = { }, }, .num_lvds = 1, + .num_rpf = 5, }; static const struct rcar_du_device_info rcar_du_r8a7799x_info = { @@ -486,6 +501,7 @@ static const struct rcar_du_device_info rcar_du_r8a7799x_info = { }, }, .num_lvds = 2, + .num_rpf = 5, .lvds_clk_mask = BIT(1) | BIT(0), }; @@ -505,6 +521,7 @@ static const struct rcar_du_device_info rcar_du_r8a779a0_info = { .port = 1, }, }, + .num_rpf = 5, .dsi_clk_mask = BIT(1) | BIT(0), }; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h index 101f42df86ea..bfad7775d9a1 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_du_drv.h -- R-Car Display Unit DRM driver + * R-Car Display Unit DRM driver * * Copyright (C) 2013-2015 Renesas Electronics Corporation * @@ -69,6 +69,7 @@ struct rcar_du_output_routing { * @channels_mask: bit mask of available DU channels * @routes: array of CRTC to output routes, indexed by output (RCAR_DU_OUTPUT_*) * @num_lvds: number of internal LVDS encoders + * @num_rpf: number of RPFs in VSP * @dpll_mask: bit mask of DU channels equipped with a DPLL * @dsi_clk_mask: bitmask of channels that can use the DSI clock as dot clock * @lvds_clk_mask: bitmask of channels that can use the LVDS clock as dot clock @@ -80,6 +81,7 @@ struct rcar_du_device_info { unsigned int channels_mask; struct rcar_du_output_routing routes[RCAR_DU_OUTPUT_MAX]; unsigned int num_lvds; + unsigned int num_rpf; unsigned int dpll_mask; unsigned int dsi_clk_mask; unsigned int lvds_clk_mask; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c index abf8022eb884..60d6be78323b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * rcar_du_encoder.c -- R-Car Display Unit Encoder + * R-Car Display Unit Encoder * * Copyright (C) 2013-2014 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h index 73560563fb31..e5ec8fbb3979 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_encoder.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_encoder.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_du_encoder.h -- R-Car Display Unit Encoder + * R-Car Display Unit Encoder * * Copyright (C) 2013-2014 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index 8665a1dd2186..1fe8581577ed 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * rcar_du_group.c -- R-Car Display Unit Channels Pair + * R-Car Display Unit Channels Pair * * Copyright (C) 2013-2015 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h index e9906609c635..55649ad86a10 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_du_group.c -- R-Car Display Unit Planes and CRTCs Group + * R-Car Display Unit Planes and CRTCs Group * * Copyright (C) 2013-2014 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c index 0f09e1ee0390..761451ee5263 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * rcar_du_kms.c -- R-Car Display Unit Mode Setting + * R-Car Display Unit Mode Setting * * Copyright (C) 2013-2015 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.h b/drivers/gpu/drm/rcar-du/rcar_du_kms.h index 789154e19535..f31afeeee05a 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_kms.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_du_kms.h -- R-Car Display Unit Mode Setting + * R-Car Display Unit Mode Setting * * Copyright (C) 2013-2014 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c index e98b76db703a..501d79367e3e 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * rcar_du_plane.c -- R-Car Display Unit Planes + * R-Car Display Unit Planes * * Copyright (C) 2013-2015 Renesas Electronics Corporation * @@ -512,6 +512,18 @@ static void rcar_du_plane_setup_format_gen3(struct rcar_du_group *rgrp, rcar_du_plane_write(rgrp, index, PnDDCR4, state->format->edf | PnDDCR4_CODE); + + /* + * On Gen3, some DU channels have two planes, each being wired to a + * separate VSPD instance. The DU can then blend two planes. While + * this feature isn't used by the driver, issues related to alpha + * blending (such as incorrect colors or planes being invisible) may + * still occur if the PnALPHAR register has a stale value. Set the + * register to 0 to avoid this. + */ + + /* TODO: Check if alpha-blending should be disabled in PnMR. */ + rcar_du_plane_write(rgrp, index, PnALPHAR, 0); } static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h index 81bbf207ad0e..f9893d7d6dfc 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_du_plane.h -- R-Car Display Unit Planes + * R-Car Display Unit Planes * * Copyright (C) 2013-2014 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_regs.h b/drivers/gpu/drm/rcar-du/rcar_du_regs.h index 1cdaa51eb9ac..c1bcb0e8b5b4 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_regs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * rcar_du_regs.h -- R-Car Display Unit Registers Definitions + * R-Car Display Unit Registers Definitions * * Copyright (C) 2013-2015 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c index e778fd52f890..dbc68cdabcff 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0+ /* - * rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor + * R-Car Display Unit VSP-Based Compositor * * Copyright (C) 2015 Renesas Electronics Corporation * @@ -407,11 +407,7 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, if (ret < 0) return ret; - /* - * The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to - * 4 RPFs. - */ - num_planes = rcdu->info->gen >= 3 ? 5 : 4; + num_planes = rcdu->info->num_rpf; vsp->planes = kcalloc(num_planes, sizeof(*vsp->planes), GFP_KERNEL); if (!vsp->planes) @@ -437,14 +433,9 @@ int rcar_du_vsp_init(struct rcar_du_vsp *vsp, struct device_node *np, drm_plane_helper_add(&plane->plane, &rcar_du_vsp_plane_helper_funcs); - if (type == DRM_PLANE_TYPE_PRIMARY) { - drm_plane_create_zpos_immutable_property(&plane->plane, - 0); - } else { - drm_plane_create_alpha_property(&plane->plane); - drm_plane_create_zpos_property(&plane->plane, 1, 1, - num_planes - 1); - } + drm_plane_create_alpha_property(&plane->plane); + drm_plane_create_zpos_property(&plane->plane, i, 0, + num_planes - 1); vsp->num_planes++; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h index 9b4724159378..67630f0b6599 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_vsp.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_vsp.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor + * R-Car Display Unit VSP-Based Compositor * * Copyright (C) 2015 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c index 4fd6067f6fb4..25f50a297c11 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_writeback.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * rcar_du_writeback.c -- R-Car Display Unit Writeback Support + * R-Car Display Unit Writeback Support * * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com> */ diff --git a/drivers/gpu/drm/rcar-du/rcar_du_writeback.h b/drivers/gpu/drm/rcar-du/rcar_du_writeback.h index fa87ebf8d21f..a71c9c08cafa 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_writeback.h +++ b/drivers/gpu/drm/rcar-du/rcar_du_writeback.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0+ */ /* - * rcar_du_writeback.h -- R-Car Display Unit Writeback Support + * R-Car Display Unit Writeback Support * * Copyright (C) 2019 Laurent Pinchart <laurent.pinchart@ideasonboard.com> */ diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.c b/drivers/gpu/drm/rcar-du/rcar_lvds.c index 830aac0a2cb4..d85aa4bc7f84 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.c +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * rcar_lvds.c -- R-Car LVDS Encoder + * R-Car LVDS Encoder * * Copyright (C) 2013-2018 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds.h b/drivers/gpu/drm/rcar-du/rcar_lvds.h index eb7c6ef03b00..3097bf749bec 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds.h +++ b/drivers/gpu/drm/rcar-du/rcar_lvds.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * rcar_lvds.h -- R-Car LVDS Encoder + * R-Car LVDS Encoder * * Copyright (C) 2013-2018 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h index 87149f2f8056..ab0406a27d33 100644 --- a/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_lvds_regs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * rcar_lvds_regs.h -- R-Car LVDS Interface Registers Definitions + * R-Car LVDS Interface Registers Definitions * * Copyright (C) 2013-2015 Renesas Electronics Corporation * diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c index 31ed285073e0..62f7eb84ab01 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * rcar_mipi_dsi.c -- R-Car MIPI DSI Encoder + * R-Car MIPI DSI Encoder * * Copyright (C) 2020 Renesas Electronics Corporation */ diff --git a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h index 0e7a9274749f..2eaca54636f3 100644 --- a/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h +++ b/drivers/gpu/drm/rcar-du/rcar_mipi_dsi_regs.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * rcar_mipi_dsi_regs.h -- R-Car MIPI DSI Interface Registers Definitions + * R-Car MIPI DSI Interface Registers Definitions * * Copyright (C) 2020 Renesas Electronics Corporation */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 67d38f53d3e5..13ed33e74457 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -23,6 +23,14 @@ #include <drm/drm_probe_helper.h> #include <drm/drm_vblank.h> +#if defined(CONFIG_ARM_DMA_USE_IOMMU) +#include <asm/dma-iommu.h> +#else +#define arm_iommu_detach_device(...) ({ }) +#define arm_iommu_release_mapping(...) ({ }) +#define to_dma_iommu_mapping(dev) NULL +#endif + #include "rockchip_drm_drv.h" #include "rockchip_drm_fb.h" #include "rockchip_drm_gem.h" @@ -49,6 +57,15 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev, if (!private->domain) return 0; + if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) { + struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev); + + if (mapping) { + arm_iommu_detach_device(dev); + arm_iommu_release_mapping(mapping); + } + } + ret = iommu_attach_device(private->domain, dev); if (ret) { DRM_DEV_ERROR(dev, "Failed to attach iommu device\n"); diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 77f80b0d3a5e..5a3e3b78cd9e 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -352,7 +352,7 @@ static int ssd130x_init(struct ssd130x_device *ssd130x) /* Set precharge period in number of ticks from the internal clock */ precharge = (SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep1) | - SSD130X_SET_PRECHARGE_PERIOD1_SET(ssd130x->prechargep2)); + SSD130X_SET_PRECHARGE_PERIOD2_SET(ssd130x->prechargep2)); ret = ssd130x_write_cmd(ssd130x, 2, SSD130X_SET_PRECHARGE_PERIOD, precharge); if (ret < 0) return ret; diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c index 768242a78e2b..5422363690e7 100644 --- a/drivers/gpu/drm/tiny/simpledrm.c +++ b/drivers/gpu/drm/tiny/simpledrm.c @@ -627,7 +627,7 @@ static const struct drm_connector_funcs simpledrm_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static int +static enum drm_mode_status simpledrm_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe, const struct drm_display_mode *mode) { |