diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-11-21 11:33:10 +0100 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2017-11-21 14:17:56 +0100 |
commit | 70c5f93669249886b151812076509f30569aff80 (patch) | |
tree | 05dce785f3a70e022b91016c87e4092f143a2fef /drivers | |
parent | c83ecfa5851f4d35be88f32dabb3a53f51cf5c32 (diff) | |
parent | f150891fd9878ef0d9197c4e8451ce67c3bdd014 (diff) | |
download | linux-70c5f93669249886b151812076509f30569aff80.tar.bz2 |
Merge airlied/drm-next into drm-misc-next
Bake in the conflict between the drm_print.h extraction and the
addition of DRM_DEBUG_LEASES since we lost it a few too many times.
Also fix a new use of drm_plane_helper_check_state in msm to follow
Ville's conversion in
commit a01cb8ba3f6282934cff65e89ab36b18b14cbe27
Author: Ville Syrjälä <ville.syrjala@linux.intel.com>
Date: Wed Nov 1 22:16:19 2017 +0200
drm: Move drm_plane_helper_check_state() into drm_atomic_helper.c
Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
1143 files changed, 52796 insertions, 52282 deletions
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index 9565d572f8dd..de56394dd161 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -1178,12 +1178,44 @@ dev_put: return ret; } +static bool __init iort_enable_acs(struct acpi_iort_node *iort_node) +{ + if (iort_node->type == ACPI_IORT_NODE_PCI_ROOT_COMPLEX) { + struct acpi_iort_node *parent; + struct acpi_iort_id_mapping *map; + int i; + + map = ACPI_ADD_PTR(struct acpi_iort_id_mapping, iort_node, + iort_node->mapping_offset); + + for (i = 0; i < iort_node->mapping_count; i++, map++) { + if (!map->output_reference) + continue; + + parent = ACPI_ADD_PTR(struct acpi_iort_node, + iort_table, map->output_reference); + /* + * If we detect a RC->SMMU mapping, make sure + * we enable ACS on the system. + */ + if ((parent->type == ACPI_IORT_NODE_SMMU) || + (parent->type == ACPI_IORT_NODE_SMMU_V3)) { + pci_request_acs(); + return true; + } + } + } + + return false; +} + static void __init iort_init_platform_devices(void) { struct acpi_iort_node *iort_node, *iort_end; struct acpi_table_iort *iort; struct fwnode_handle *fwnode; int i, ret; + bool acs_enabled = false; /* * iort_table and iort both point to the start of IORT table, but @@ -1203,6 +1235,9 @@ static void __init iort_init_platform_devices(void) return; } + if (!acs_enabled) + acs_enabled = iort_enable_acs(iort_node); + if ((iort_node->type == ACPI_IORT_NODE_SMMU) || (iort_node->type == ACPI_IORT_NODE_SMMU_V3)) { diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 3fb8ff513461..e26ea209b63e 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -571,10 +571,9 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data, * } * } * - * Calling this function with index %2 return %-ENOENT and with index %3 - * returns the last entry. If the property does not contain any more values - * %-ENODATA is returned. The NULL entry must be single integer and - * preferably contain value %0. + * Calling this function with index %2 or index %3 return %-ENOENT. If the + * property does not contain any more values %-ENOENT is returned. The NULL + * entry must be single integer and preferably contain value %0. * * Return: %0 on success, negative error code on failure. */ @@ -590,11 +589,11 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, data = acpi_device_data_of_node(fwnode); if (!data) - return -EINVAL; + return -ENOENT; ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj); if (ret) - return ret; + return ret == -EINVAL ? -ENOENT : -EINVAL; /* * The simplest case is when the value is a single reference. Just @@ -606,7 +605,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ret = acpi_bus_get_device(obj->reference.handle, &device); if (ret) - return ret; + return ret == -ENODEV ? -EINVAL : ret; args->adev = device; args->nargs = 0; @@ -622,8 +621,10 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, * The index argument is then used to determine which reference * the caller wants (along with the arguments). */ - if (obj->type != ACPI_TYPE_PACKAGE || index >= obj->package.count) - return -EPROTO; + if (obj->type != ACPI_TYPE_PACKAGE) + return -EINVAL; + if (index >= obj->package.count) + return -ENOENT; element = obj->package.elements; end = element + obj->package.count; @@ -635,7 +636,7 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, ret = acpi_bus_get_device(element->reference.handle, &device); if (ret) - return -ENODEV; + return -EINVAL; nargs = 0; element++; @@ -649,11 +650,11 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, else if (type == ACPI_TYPE_LOCAL_REFERENCE) break; else - return -EPROTO; + return -EINVAL; } if (nargs > MAX_ACPI_REFERENCE_ARGS) - return -EPROTO; + return -EINVAL; if (idx == index) { args->adev = device; @@ -670,13 +671,13 @@ int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode, return -ENOENT; element++; } else { - return -EPROTO; + return -EINVAL; } idx++; } - return -ENODATA; + return -ENOENT; } EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference); diff --git a/drivers/android/binder.c b/drivers/android/binder.c index d055b3f2a207..fddf76ef5bd6 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2217,7 +2217,7 @@ static void binder_transaction_buffer_release(struct binder_proc *proc, debug_id, (u64)fda->num_fds); continue; } - fd_array = (u32 *)(parent_buffer + fda->parent_offset); + fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset); for (fd_index = 0; fd_index < fda->num_fds; fd_index++) task_close_fd(proc, fd_array[fd_index]); } break; @@ -2326,7 +2326,6 @@ static int binder_translate_handle(struct flat_binder_object *fp, (u64)node->ptr); binder_node_unlock(node); } else { - int ret; struct binder_ref_data dest_rdata; binder_node_unlock(node); @@ -2442,7 +2441,7 @@ static int binder_translate_fd_array(struct binder_fd_array_object *fda, */ parent_buffer = parent->buffer - binder_alloc_get_user_buffer_offset(&target_proc->alloc); - fd_array = (u32 *)(parent_buffer + fda->parent_offset); + fd_array = (u32 *)(parent_buffer + (uintptr_t)fda->parent_offset); if (!IS_ALIGNED((unsigned long)fd_array, sizeof(u32))) { binder_user_error("%d:%d parent offset not aligned correctly.\n", proc->pid, thread->pid); @@ -2508,7 +2507,7 @@ static int binder_fixup_parent(struct binder_transaction *t, proc->pid, thread->pid); return -EINVAL; } - parent_buffer = (u8 *)(parent->buffer - + parent_buffer = (u8 *)((uintptr_t)parent->buffer - binder_alloc_get_user_buffer_offset( &target_proc->alloc)); *(binder_uintptr_t *)(parent_buffer + bp->parent_offset) = bp->buffer; @@ -2583,6 +2582,48 @@ static bool binder_proc_transaction(struct binder_transaction *t, return true; } +/** + * binder_get_node_refs_for_txn() - Get required refs on node for txn + * @node: struct binder_node for which to get refs + * @proc: returns @node->proc if valid + * @error: if no @proc then returns BR_DEAD_REPLY + * + * User-space normally keeps the node alive when creating a transaction + * since it has a reference to the target. The local strong ref keeps it + * alive if the sending process dies before the target process processes + * the transaction. If the source process is malicious or has a reference + * counting bug, relying on the local strong ref can fail. + * + * Since user-space can cause the local strong ref to go away, we also take + * a tmpref on the node to ensure it survives while we are constructing + * the transaction. We also need a tmpref on the proc while we are + * constructing the transaction, so we take that here as well. + * + * Return: The target_node with refs taken or NULL if no @node->proc is NULL. + * Also sets @proc if valid. If the @node->proc is NULL indicating that the + * target proc has died, @error is set to BR_DEAD_REPLY + */ +static struct binder_node *binder_get_node_refs_for_txn( + struct binder_node *node, + struct binder_proc **procp, + uint32_t *error) +{ + struct binder_node *target_node = NULL; + + binder_node_inner_lock(node); + if (node->proc) { + target_node = node; + binder_inc_node_nilocked(node, 1, 0, NULL); + binder_inc_node_tmpref_ilocked(node); + node->proc->tmp_ref++; + *procp = node->proc; + } else + *error = BR_DEAD_REPLY; + binder_node_inner_unlock(node); + + return target_node; +} + static void binder_transaction(struct binder_proc *proc, struct binder_thread *thread, struct binder_transaction_data *tr, int reply, @@ -2686,43 +2727,35 @@ static void binder_transaction(struct binder_proc *proc, ref = binder_get_ref_olocked(proc, tr->target.handle, true); if (ref) { - binder_inc_node(ref->node, 1, 0, NULL); - target_node = ref->node; - } - binder_proc_unlock(proc); - if (target_node == NULL) { + target_node = binder_get_node_refs_for_txn( + ref->node, &target_proc, + &return_error); + } else { binder_user_error("%d:%d got transaction to invalid handle\n", - proc->pid, thread->pid); + proc->pid, thread->pid); return_error = BR_FAILED_REPLY; - return_error_param = -EINVAL; - return_error_line = __LINE__; - goto err_invalid_target_handle; } + binder_proc_unlock(proc); } else { mutex_lock(&context->context_mgr_node_lock); target_node = context->binder_context_mgr_node; - if (target_node == NULL) { + if (target_node) + target_node = binder_get_node_refs_for_txn( + target_node, &target_proc, + &return_error); + else return_error = BR_DEAD_REPLY; - mutex_unlock(&context->context_mgr_node_lock); - return_error_line = __LINE__; - goto err_no_context_mgr_node; - } - binder_inc_node(target_node, 1, 0, NULL); mutex_unlock(&context->context_mgr_node_lock); } - e->to_node = target_node->debug_id; - binder_node_lock(target_node); - target_proc = target_node->proc; - if (target_proc == NULL) { - binder_node_unlock(target_node); - return_error = BR_DEAD_REPLY; + if (!target_node) { + /* + * return_error is set above + */ + return_error_param = -EINVAL; return_error_line = __LINE__; goto err_dead_binder; } - binder_inner_proc_lock(target_proc); - target_proc->tmp_ref++; - binder_inner_proc_unlock(target_proc); - binder_node_unlock(target_node); + e->to_node = target_node->debug_id; if (security_binder_transaction(proc->tsk, target_proc->tsk) < 0) { return_error = BR_FAILED_REPLY; @@ -3072,6 +3105,8 @@ static void binder_transaction(struct binder_proc *proc, if (target_thread) binder_thread_dec_tmpref(target_thread); binder_proc_dec_tmpref(target_proc); + if (target_node) + binder_dec_node_tmpref(target_node); /* * write barrier to synchronize with initialization * of log entry @@ -3083,6 +3118,7 @@ static void binder_transaction(struct binder_proc *proc, err_dead_proc_or_thread: return_error = BR_DEAD_REPLY; return_error_line = __LINE__; + binder_dequeue_work(proc, tcomplete); err_translate_failed: err_bad_object_type: err_bad_offset: @@ -3090,6 +3126,8 @@ err_bad_parent: err_copy_data_failed: trace_binder_transaction_failed_buffer_release(t->buffer); binder_transaction_buffer_release(target_proc, t->buffer, offp); + if (target_node) + binder_dec_node_tmpref(target_node); target_node = NULL; t->buffer->transaction = NULL; binder_alloc_free_buf(&target_proc->alloc, t->buffer); @@ -3104,13 +3142,14 @@ err_bad_call_stack: err_empty_call_stack: err_dead_binder: err_invalid_target_handle: -err_no_context_mgr_node: if (target_thread) binder_thread_dec_tmpref(target_thread); if (target_proc) binder_proc_dec_tmpref(target_proc); - if (target_node) + if (target_node) { binder_dec_node(target_node, 1, 0); + binder_dec_node_tmpref(target_node); + } binder_debug(BINDER_DEBUG_FAILED_TRANSACTION, "%d:%d transaction failed %d/%d, size %lld-%lld line %d\n", @@ -3623,12 +3662,6 @@ static void binder_stat_br(struct binder_proc *proc, } } -static int binder_has_thread_work(struct binder_thread *thread) -{ - return !binder_worklist_empty(thread->proc, &thread->todo) || - thread->looper_need_return; -} - static int binder_put_node_cmd(struct binder_proc *proc, struct binder_thread *thread, void __user **ptrp, @@ -4258,12 +4291,9 @@ static unsigned int binder_poll(struct file *filp, binder_inner_proc_unlock(thread->proc); - if (binder_has_work(thread, wait_for_proc_work)) - return POLLIN; - poll_wait(filp, &thread->wait, wait); - if (binder_has_thread_work(thread)) + if (binder_has_work(thread, wait_for_proc_work)) return POLLIN; return 0; diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 8fe165844e47..c2819a3d58a6 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -215,17 +215,12 @@ static int binder_update_page_range(struct binder_alloc *alloc, int allocate, } } - if (!vma && need_mm) - mm = get_task_mm(alloc->tsk); + if (!vma && need_mm && mmget_not_zero(alloc->vma_vm_mm)) + mm = alloc->vma_vm_mm; if (mm) { down_write(&mm->mmap_sem); vma = alloc->vma; - if (vma && mm != alloc->vma_vm_mm) { - pr_err("%d: vma mm and task mm mismatch\n", - alloc->pid); - vma = NULL; - } } if (!vma && need_mm) { @@ -565,7 +560,7 @@ static void binder_delete_free_buffer(struct binder_alloc *alloc, binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC, "%d: merge free, buffer %pK do not share page with %pK or %pK\n", alloc->pid, buffer->data, - prev->data, next->data); + prev->data, next ? next->data : NULL); binder_update_page_range(alloc, 0, buffer_start_page(buffer), buffer_start_page(buffer) + PAGE_SIZE, NULL); @@ -720,6 +715,7 @@ int binder_alloc_mmap_handler(struct binder_alloc *alloc, barrier(); alloc->vma = vma; alloc->vma_vm_mm = vma->vm_mm; + mmgrab(alloc->vma_vm_mm); return 0; @@ -795,6 +791,8 @@ void binder_alloc_deferred_release(struct binder_alloc *alloc) vfree(alloc->buffer); } mutex_unlock(&alloc->mutex); + if (alloc->vma_vm_mm) + mmdrop(alloc->vma_vm_mm); binder_alloc_debug(BINDER_DEBUG_OPEN_CLOSE, "%s: %d buffers %d, pages %d\n", @@ -889,7 +887,6 @@ int binder_alloc_get_allocated_count(struct binder_alloc *alloc) void binder_alloc_vma_close(struct binder_alloc *alloc) { WRITE_ONCE(alloc->vma, NULL); - WRITE_ONCE(alloc->vma_vm_mm, NULL); } /** @@ -913,6 +910,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item, struct binder_alloc *alloc; uintptr_t page_addr; size_t index; + struct vm_area_struct *vma; alloc = page->alloc; if (!mutex_trylock(&alloc->mutex)) @@ -923,16 +921,22 @@ enum lru_status binder_alloc_free_page(struct list_head *item, index = page - alloc->pages; page_addr = (uintptr_t)alloc->buffer + index * PAGE_SIZE; - if (alloc->vma) { - mm = get_task_mm(alloc->tsk); - if (!mm) - goto err_get_task_mm_failed; + vma = alloc->vma; + if (vma) { + if (!mmget_not_zero(alloc->vma_vm_mm)) + goto err_mmget; + mm = alloc->vma_vm_mm; if (!down_write_trylock(&mm->mmap_sem)) goto err_down_write_mmap_sem_failed; + } + + list_lru_isolate(lru, item); + spin_unlock(lock); + if (vma) { trace_binder_unmap_user_start(alloc, index); - zap_page_range(alloc->vma, + zap_page_range(vma, page_addr + alloc->user_buffer_offset, PAGE_SIZE); @@ -950,14 +954,13 @@ enum lru_status binder_alloc_free_page(struct list_head *item, trace_binder_unmap_kernel_end(alloc, index); - list_lru_isolate(lru, item); - + spin_lock(lock); mutex_unlock(&alloc->mutex); - return LRU_REMOVED; + return LRU_REMOVED_RETRY; err_down_write_mmap_sem_failed: - mmput(mm); -err_get_task_mm_failed: + mmput_async(mm); +err_mmget: err_page_already_freed: mutex_unlock(&alloc->mutex); err_get_alloc_mutex_failed: @@ -996,7 +999,6 @@ struct shrinker binder_shrinker = { */ void binder_alloc_init(struct binder_alloc *alloc) { - alloc->tsk = current->group_leader; alloc->pid = current->group_leader->pid; mutex_init(&alloc->mutex); INIT_LIST_HEAD(&alloc->buffers); diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index a3a3602c689c..2dd33b6df104 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -100,7 +100,6 @@ struct binder_lru_page { */ struct binder_alloc { struct mutex mutex; - struct task_struct *tsk; struct vm_area_struct *vma; struct mm_struct *vma_vm_mm; void *buffer; diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index cb9b0e9090e3..9f78bb03bb76 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -621,8 +621,11 @@ static void ahci_pci_save_initial_config(struct pci_dev *pdev, static int ahci_pci_reset_controller(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); + int rc; - ahci_reset_controller(host); + rc = ahci_reset_controller(host); + if (rc) + return rc; if (pdev->vendor == PCI_VENDOR_ID_INTEL) { struct ahci_host_priv *hpriv = host->private_data; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 8401c3b5be92..b702c20fbc2b 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -492,6 +492,7 @@ static const struct ich_laptop ich_laptop[] = { { 0x27DF, 0x152D, 0x0778 }, /* ICH7 on unknown Intel */ { 0x24CA, 0x1025, 0x0061 }, /* ICH4 on ACER Aspire 2023WLMi */ { 0x24CA, 0x1025, 0x003d }, /* ICH4 on ACER TM290 */ + { 0x24CA, 0x10CF, 0x11AB }, /* ICH4M on Fujitsu-Siemens Lifebook S6120 */ { 0x266F, 0x1025, 0x0066 }, /* ICH6 on ACER Aspire 1694WLMi */ { 0x2653, 0x1043, 0x82D8 }, /* ICH6M on Asus Eee 701 */ { 0x27df, 0x104d, 0x900e }, /* ICH7 on Sony TZ-90 */ diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 1945a8ea2099..ee4c1ec9dca0 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3234,19 +3234,19 @@ static const struct ata_timing ata_timing[] = { }; #define ENOUGH(v, unit) (((v)-1)/(unit)+1) -#define EZ(v, unit) ((v)?ENOUGH(v, unit):0) +#define EZ(v, unit) ((v)?ENOUGH(((v) * 1000), unit):0) static void ata_timing_quantize(const struct ata_timing *t, struct ata_timing *q, int T, int UT) { - q->setup = EZ(t->setup * 1000, T); - q->act8b = EZ(t->act8b * 1000, T); - q->rec8b = EZ(t->rec8b * 1000, T); - q->cyc8b = EZ(t->cyc8b * 1000, T); - q->active = EZ(t->active * 1000, T); - q->recover = EZ(t->recover * 1000, T); - q->dmack_hold = EZ(t->dmack_hold * 1000, T); - q->cycle = EZ(t->cycle * 1000, T); - q->udma = EZ(t->udma * 1000, UT); + q->setup = EZ(t->setup, T); + q->act8b = EZ(t->act8b, T); + q->rec8b = EZ(t->rec8b, T); + q->cyc8b = EZ(t->cyc8b, T); + q->active = EZ(t->active, T); + q->recover = EZ(t->recover, T); + q->dmack_hold = EZ(t->dmack_hold, T); + q->cycle = EZ(t->cycle, T); + q->udma = EZ(t->udma, UT); } void ata_timing_merge(const struct ata_timing *a, const struct ata_timing *b, diff --git a/drivers/auxdisplay/charlcd.c b/drivers/auxdisplay/charlcd.c index cfeb049a01ef..642afd88870b 100644 --- a/drivers/auxdisplay/charlcd.c +++ b/drivers/auxdisplay/charlcd.c @@ -647,18 +647,25 @@ static ssize_t charlcd_write(struct file *file, const char __user *buf, static int charlcd_open(struct inode *inode, struct file *file) { struct charlcd_priv *priv = to_priv(the_charlcd); + int ret; + ret = -EBUSY; if (!atomic_dec_and_test(&charlcd_available)) - return -EBUSY; /* open only once at a time */ + goto fail; /* open only once at a time */ + ret = -EPERM; if (file->f_mode & FMODE_READ) /* device is write-only */ - return -EPERM; + goto fail; if (priv->must_clear) { charlcd_clear_display(&priv->lcd); priv->must_clear = false; } return nonseekable_open(inode, file); + + fail: + atomic_inc(&charlcd_available); + return ret; } static int charlcd_release(struct inode *inode, struct file *file) diff --git a/drivers/auxdisplay/panel.c b/drivers/auxdisplay/panel.c index df126dcdaf18..6911acd896d9 100644 --- a/drivers/auxdisplay/panel.c +++ b/drivers/auxdisplay/panel.c @@ -1105,14 +1105,21 @@ static ssize_t keypad_read(struct file *file, static int keypad_open(struct inode *inode, struct file *file) { + int ret; + + ret = -EBUSY; if (!atomic_dec_and_test(&keypad_available)) - return -EBUSY; /* open only once at a time */ + goto fail; /* open only once at a time */ + ret = -EPERM; if (file->f_mode & FMODE_WRITE) /* device is read-only */ - return -EPERM; + goto fail; keypad_buflen = 0; /* flush the buffer on opening */ return 0; + fail: + atomic_inc(&keypad_available); + return ret; } static int keypad_release(struct inode *inode, struct file *file) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 41be9ff7d70a..6df7d6676a48 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -166,11 +166,11 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu) } #ifdef CONFIG_CPU_FREQ -static cpumask_var_t cpus_to_visit; -static void parsing_done_workfn(struct work_struct *work); -static DECLARE_WORK(parsing_done_work, parsing_done_workfn); +static cpumask_var_t cpus_to_visit __initdata; +static void __init parsing_done_workfn(struct work_struct *work); +static __initdata DECLARE_WORK(parsing_done_work, parsing_done_workfn); -static int +static int __init init_cpu_capacity_callback(struct notifier_block *nb, unsigned long val, void *data) @@ -206,7 +206,7 @@ init_cpu_capacity_callback(struct notifier_block *nb, return 0; } -static struct notifier_block init_cpu_capacity_notifier = { +static struct notifier_block init_cpu_capacity_notifier __initdata = { .notifier_call = init_cpu_capacity_callback, }; @@ -232,7 +232,7 @@ static int __init register_cpufreq_notifier(void) } core_initcall(register_cpufreq_notifier); -static void parsing_done_workfn(struct work_struct *work) +static void __init parsing_done_workfn(struct work_struct *work) { cpufreq_unregister_notifier(&init_cpu_capacity_notifier, CPUFREQ_POLICY_NOTIFIER); diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 321cd7b4d817..227bac5f1191 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c @@ -377,7 +377,8 @@ int register_cpu(struct cpu *cpu, int num) per_cpu(cpu_sys_devices, num) = &cpu->dev; register_cpu_under_node(num, cpu_to_node(num)); - dev_pm_qos_expose_latency_limit(&cpu->dev, 0); + dev_pm_qos_expose_latency_limit(&cpu->dev, + PM_QOS_RESUME_LATENCY_NO_CONSTRAINT); return 0; } diff --git a/drivers/base/node.c b/drivers/base/node.c index 3855902f2c5b..aae2402f3791 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -27,13 +27,21 @@ static struct bus_type node_subsys = { static ssize_t node_read_cpumap(struct device *dev, bool list, char *buf) { + ssize_t n; + cpumask_var_t mask; struct node *node_dev = to_node(dev); - const struct cpumask *mask = cpumask_of_node(node_dev->dev.id); /* 2008/04/07: buf currently PAGE_SIZE, need 9 chars per 32 bits. */ BUILD_BUG_ON((NR_CPUS/32 * 9) > (PAGE_SIZE-1)); - return cpumap_print_to_pagebuf(list, buf, mask); + if (!alloc_cpumask_var(&mask, GFP_KERNEL)) + return 0; + + cpumask_and(mask, cpumask_of_node(node_dev->dev.id), cpu_online_mask); + n = cpumap_print_to_pagebuf(list, buf, mask); + free_cpumask_var(mask); + + return n; } static inline ssize_t node_read_cpumask(struct device *dev, diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d1bd99271066..9045c5f3734e 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -868,7 +868,8 @@ static ssize_t driver_override_store(struct device *dev, struct platform_device *pdev = to_platform_device(dev); char *driver_override, *old, *cp; - if (count > PATH_MAX) + /* We need to keep extra room for a newline */ + if (count >= (PAGE_SIZE - 1)) return -EINVAL; driver_override = kstrndup(buf, count, GFP_KERNEL); diff --git a/drivers/base/power/domain_governor.c b/drivers/base/power/domain_governor.c index 281f949c5ffe..51751cc8c9e6 100644 --- a/drivers/base/power/domain_governor.c +++ b/drivers/base/power/domain_governor.c @@ -14,23 +14,20 @@ static int dev_update_qos_constraint(struct device *dev, void *data) { s64 *constraint_ns_p = data; - s32 constraint_ns = -1; + s64 constraint_ns = -1; if (dev->power.subsys_data && dev->power.subsys_data->domain_data) constraint_ns = dev_gpd_data(dev)->td.effective_constraint_ns; - if (constraint_ns < 0) { + if (constraint_ns < 0) constraint_ns = dev_pm_qos_read_value(dev); - constraint_ns *= NSEC_PER_USEC; - } - if (constraint_ns == 0) + + if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) return 0; - /* - * constraint_ns cannot be negative here, because the device has been - * suspended. - */ - if (constraint_ns < *constraint_ns_p || *constraint_ns_p == 0) + constraint_ns *= NSEC_PER_USEC; + + if (constraint_ns < *constraint_ns_p || *constraint_ns_p < 0) *constraint_ns_p = constraint_ns; return 0; @@ -63,10 +60,14 @@ static bool default_suspend_ok(struct device *dev) spin_unlock_irqrestore(&dev->power.lock, flags); - if (constraint_ns < 0) + if (constraint_ns == 0) return false; - constraint_ns *= NSEC_PER_USEC; + if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) + constraint_ns = -1; + else + constraint_ns *= NSEC_PER_USEC; + /* * We can walk the children without any additional locking, because * they all have been suspended at this point and their @@ -76,14 +77,19 @@ static bool default_suspend_ok(struct device *dev) device_for_each_child(dev, &constraint_ns, dev_update_qos_constraint); - if (constraint_ns > 0) { - constraint_ns -= td->suspend_latency_ns + - td->resume_latency_ns; - if (constraint_ns == 0) - return false; + if (constraint_ns < 0) { + /* The children have no constraints. */ + td->effective_constraint_ns = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; + td->cached_suspend_ok = true; + } else { + constraint_ns -= td->suspend_latency_ns + td->resume_latency_ns; + if (constraint_ns > 0) { + td->effective_constraint_ns = constraint_ns; + td->cached_suspend_ok = true; + } else { + td->effective_constraint_ns = 0; + } } - td->effective_constraint_ns = constraint_ns; - td->cached_suspend_ok = constraint_ns >= 0; /* * The children have been suspended already, so we don't need to take @@ -145,13 +151,14 @@ static bool __default_power_down_ok(struct dev_pm_domain *pd, td = &to_gpd_data(pdd)->td; constraint_ns = td->effective_constraint_ns; /* default_suspend_ok() need not be called before us. */ - if (constraint_ns < 0) { + if (constraint_ns < 0) constraint_ns = dev_pm_qos_read_value(pdd->dev); - constraint_ns *= NSEC_PER_USEC; - } - if (constraint_ns == 0) + + if (constraint_ns == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) continue; + constraint_ns *= NSEC_PER_USEC; + /* * constraint_ns cannot be negative here, because the device has * been suspended. diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 277d43a83f53..7d29286d9313 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -189,7 +189,7 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) plist_head_init(&c->list); c->target_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; c->default_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; - c->no_constraint_value = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE; + c->no_constraint_value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; c->type = PM_QOS_MIN; c->notifiers = n; diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 7bcf80fa9ada..13e015905543 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -253,7 +253,7 @@ static int rpm_check_suspend_allowed(struct device *dev) || (dev->power.request_pending && dev->power.request == RPM_REQ_RESUME)) retval = -EAGAIN; - else if (__dev_pm_qos_read_value(dev) < 0) + else if (__dev_pm_qos_read_value(dev) == 0) retval = -EPERM; else if (dev->power.runtime_status == RPM_SUSPENDED) retval = 1; diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 156ab57bca77..632077f05c57 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -218,7 +218,14 @@ static ssize_t pm_qos_resume_latency_show(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%d\n", dev_pm_qos_requested_resume_latency(dev)); + s32 value = dev_pm_qos_requested_resume_latency(dev); + + if (value == 0) + return sprintf(buf, "n/a\n"); + else if (value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) + value = 0; + + return sprintf(buf, "%d\n", value); } static ssize_t pm_qos_resume_latency_store(struct device *dev, @@ -228,11 +235,21 @@ static ssize_t pm_qos_resume_latency_store(struct device *dev, s32 value; int ret; - if (kstrtos32(buf, 0, &value)) - return -EINVAL; + if (!kstrtos32(buf, 0, &value)) { + /* + * Prevent users from writing negative or "no constraint" values + * directly. + */ + if (value < 0 || value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) + return -EINVAL; - if (value < 0) + if (value == 0) + value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT; + } else if (!strcmp(buf, "n/a") || !strcmp(buf, "n/a\n")) { + value = 0; + } else { return -EINVAL; + } ret = dev_pm_qos_update_request(dev->power.qos->resume_latency_req, value); diff --git a/drivers/base/property.c b/drivers/base/property.c index d0b65bbe7e15..7ed99c1b2a8b 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c @@ -21,6 +21,7 @@ #include <linux/phy.h> struct property_set { + struct device *dev; struct fwnode_handle fwnode; const struct property_entry *properties; }; @@ -682,6 +683,10 @@ EXPORT_SYMBOL_GPL(fwnode_property_match_string); * Caller is responsible to call fwnode_handle_put() on the returned * args->fwnode pointer. * + * Returns: %0 on success + * %-ENOENT when the index is out of bounds, the index has an empty + * reference or the property was not found + * %-EINVAL on parse error */ int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode, const char *prop, const char *nargs_prop, @@ -891,6 +896,7 @@ static struct property_set *pset_copy_set(const struct property_set *pset) void device_remove_properties(struct device *dev) { struct fwnode_handle *fwnode; + struct property_set *pset; fwnode = dev_fwnode(dev); if (!fwnode) @@ -900,16 +906,16 @@ void device_remove_properties(struct device *dev) * the pset. If there is no real firmware node (ACPI/DT) primary * will hold the pset. */ - if (is_pset_node(fwnode)) { + pset = to_pset_node(fwnode); + if (pset) { set_primary_fwnode(dev, NULL); - pset_free_set(to_pset_node(fwnode)); } else { - fwnode = fwnode->secondary; - if (!IS_ERR(fwnode) && is_pset_node(fwnode)) { + pset = to_pset_node(fwnode->secondary); + if (pset && dev == pset->dev) set_secondary_fwnode(dev, NULL); - pset_free_set(to_pset_node(fwnode)); - } } + if (pset && dev == pset->dev) + pset_free_set(pset); } EXPORT_SYMBOL_GPL(device_remove_properties); @@ -938,6 +944,7 @@ int device_add_properties(struct device *dev, p->fwnode.ops = &pset_fwnode_ops; set_secondary_fwnode(dev, &p->fwnode); + p->dev = dev; return 0; } EXPORT_SYMBOL_GPL(device_add_properties); diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 4a438b8abe27..2dfe99b328f8 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -17,7 +17,7 @@ if BLK_DEV config BLK_DEV_NULL_BLK tristate "Null test block driver" - depends on CONFIGFS_FS + select CONFIGFS_FS config BLK_DEV_FD tristate "Normal floppy disk support" diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 3684e21d543f..9adfb5445f8d 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -243,7 +243,6 @@ static void nbd_size_set(struct nbd_device *nbd, loff_t blocksize, struct nbd_config *config = nbd->config; config->blksize = blocksize; config->bytesize = blocksize * nr_blocks; - nbd_size_update(nbd); } static void nbd_complete_rq(struct request *req) @@ -387,6 +386,15 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send, return result; } +/* + * Different settings for sk->sk_sndtimeo can result in different return values + * if there is a signal pending when we enter sendmsg, because reasons? + */ +static inline int was_interrupted(int result) +{ + return result == -ERESTARTSYS || result == -EINTR; +} + /* always call with the tx_lock held */ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) { @@ -459,7 +467,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index) result = sock_xmit(nbd, index, 1, &from, (type == NBD_CMD_WRITE) ? MSG_MORE : 0, &sent); if (result <= 0) { - if (result == -ERESTARTSYS) { + if (was_interrupted(result)) { /* If we havne't sent anything we can just return BUSY, * however if we have sent something we need to make * sure we only allow this req to be sent until we are @@ -503,7 +511,7 @@ send_pages: } result = sock_xmit(nbd, index, 1, &from, flags, &sent); if (result <= 0) { - if (result == -ERESTARTSYS) { + if (was_interrupted(result)) { /* We've already sent the header, we * have no choice but to set pending and * return BUSY. @@ -820,9 +828,13 @@ static blk_status_t nbd_queue_rq(struct blk_mq_hw_ctx *hctx, * appropriate. */ ret = nbd_handle_cmd(cmd, hctx->queue_num); + if (ret < 0) + ret = BLK_STS_IOERR; + else if (!ret) + ret = BLK_STS_OK; complete(&cmd->send_complete); - return ret < 0 ? BLK_STS_IOERR : BLK_STS_OK; + return ret; } static int nbd_add_socket(struct nbd_device *nbd, unsigned long arg, @@ -1090,6 +1102,7 @@ static int nbd_start_device(struct nbd_device *nbd) args->index = i; queue_work(recv_workqueue, &args->work); } + nbd_size_update(nbd); return error; } diff --git a/drivers/block/skd_main.c b/drivers/block/skd_main.c index 7cedb4295e9d..64d0fc17c174 100644 --- a/drivers/block/skd_main.c +++ b/drivers/block/skd_main.c @@ -2604,7 +2604,7 @@ static void *skd_alloc_dma(struct skd_device *skdev, struct kmem_cache *s, return NULL; *dma_handle = dma_map_single(dev, buf, s->size, dir); if (dma_mapping_error(dev, *dma_handle)) { - kfree(buf); + kmem_cache_free(s, buf); buf = NULL; } return buf; diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 2981c27d3aae..f149d3e61234 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -766,27 +766,6 @@ static void zram_slot_unlock(struct zram *zram, u32 index) bit_spin_unlock(ZRAM_ACCESS, &zram->table[index].value); } -static bool zram_same_page_read(struct zram *zram, u32 index, - struct page *page, - unsigned int offset, unsigned int len) -{ - zram_slot_lock(zram, index); - if (unlikely(!zram_get_handle(zram, index) || - zram_test_flag(zram, index, ZRAM_SAME))) { - void *mem; - - zram_slot_unlock(zram, index); - mem = kmap_atomic(page); - zram_fill_page(mem + offset, len, - zram_get_element(zram, index)); - kunmap_atomic(mem); - return true; - } - zram_slot_unlock(zram, index); - - return false; -} - static void zram_meta_free(struct zram *zram, u64 disksize) { size_t num_pages = disksize >> PAGE_SHIFT; @@ -884,11 +863,20 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index, zram_slot_unlock(zram, index); } - if (zram_same_page_read(zram, index, page, 0, PAGE_SIZE)) - return 0; - zram_slot_lock(zram, index); handle = zram_get_handle(zram, index); + if (!handle || zram_test_flag(zram, index, ZRAM_SAME)) { + unsigned long value; + void *mem; + + value = handle ? zram_get_element(zram, index) : 0; + mem = kmap_atomic(page); + zram_fill_page(mem, PAGE_SIZE, value); + kunmap_atomic(mem); + zram_slot_unlock(zram, index); + return 0; + } + size = zram_get_obj_size(zram, index); src = zs_map_object(zram->mem_pool, handle, ZS_MM_RO); diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index c7f396903184..70db4d5638a6 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -720,7 +720,7 @@ mvebu_mbus_default_setup_cpu_target(struct mvebu_mbus_state *mbus) if (mbus->hw_io_coherency) w->mbus_attr |= ATTR_HW_COHERENCY; w->base = base & DDR_BASE_CS_LOW_MASK; - w->size = (size | ~DDR_SIZE_MASK) + 1; + w->size = (u64)(size | ~DDR_SIZE_MASK) + 1; } } mvebu_mbus_dram_info.num_cs = cs; diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c index c834f5abfc49..4c10456f8a32 100644 --- a/drivers/clk/clk-bulk.c +++ b/drivers/clk/clk-bulk.c @@ -105,6 +105,7 @@ err: return ret; } +EXPORT_SYMBOL_GPL(clk_bulk_prepare); #endif /* CONFIG_HAVE_CLK_PREPARE */ diff --git a/drivers/clk/rockchip/clk-rk3128.c b/drivers/clk/rockchip/clk-rk3128.c index 62d7854e4b87..5970a50671b9 100644 --- a/drivers/clk/rockchip/clk-rk3128.c +++ b/drivers/clk/rockchip/clk-rk3128.c @@ -315,13 +315,13 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { RK2928_CLKGATE_CON(10), 8, GFLAGS), GATE(SCLK_PVTM_CORE, "clk_pvtm_core", "xin24m", 0, - RK2928_CLKGATE_CON(10), 8, GFLAGS), + RK2928_CLKGATE_CON(10), 0, GFLAGS), GATE(SCLK_PVTM_GPU, "clk_pvtm_gpu", "xin24m", 0, - RK2928_CLKGATE_CON(10), 8, GFLAGS), + RK2928_CLKGATE_CON(10), 1, GFLAGS), GATE(SCLK_PVTM_FUNC, "clk_pvtm_func", "xin24m", 0, - RK2928_CLKGATE_CON(10), 8, GFLAGS), + RK2928_CLKGATE_CON(10), 2, GFLAGS), GATE(SCLK_MIPI_24M, "clk_mipi_24m", "xin24m", CLK_IGNORE_UNUSED, - RK2928_CLKGATE_CON(10), 8, GFLAGS), + RK2928_CLKGATE_CON(2), 15, GFLAGS), COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0, RK2928_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 6, DFLAGS, @@ -541,7 +541,7 @@ static struct rockchip_clk_branch common_clk_branches[] __initdata = { GATE(0, "pclk_grf", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 4, GFLAGS), GATE(0, "pclk_mipiphy", "pclk_cpu", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(5), 0, GFLAGS), - GATE(0, "pclk_pmu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 2, GFLAGS), + GATE(0, "pclk_pmu", "pclk_pmu_pre", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS), GATE(0, "pclk_pmu_niu", "pclk_pmu_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(9), 3, GFLAGS), /* PD_MMC */ @@ -577,6 +577,8 @@ static const char *const rk3128_critical_clocks[] __initconst = { "aclk_peri", "hclk_peri", "pclk_peri", + "pclk_pmu", + "sclk_timer5", }; static struct rockchip_clk_provider *__init rk3128_common_clk_init(struct device_node *np) diff --git a/drivers/clk/samsung/clk-exynos4.c b/drivers/clk/samsung/clk-exynos4.c index e40b77583c47..d8d3cb67b402 100644 --- a/drivers/clk/samsung/clk-exynos4.c +++ b/drivers/clk/samsung/clk-exynos4.c @@ -294,6 +294,18 @@ static const struct samsung_clk_reg_dump src_mask_suspend_e4210[] = { #define PLL_ENABLED (1 << 31) #define PLL_LOCKED (1 << 29) +static void exynos4_clk_enable_pll(u32 reg) +{ + u32 pll_con = readl(reg_base + reg); + pll_con |= PLL_ENABLED; + writel(pll_con, reg_base + reg); + + while (!(pll_con & PLL_LOCKED)) { + cpu_relax(); + pll_con = readl(reg_base + reg); + } +} + static void exynos4_clk_wait_for_pll(u32 reg) { u32 pll_con; @@ -315,6 +327,9 @@ static int exynos4_clk_suspend(void) samsung_clk_save(reg_base, exynos4_save_pll, ARRAY_SIZE(exynos4_clk_pll_regs)); + exynos4_clk_enable_pll(EPLL_CON0); + exynos4_clk_enable_pll(VPLL_CON0); + if (exynos4_soc == EXYNOS4210) { samsung_clk_save(reg_base, exynos4_save_soc, ARRAY_SIZE(exynos4210_clk_save)); diff --git a/drivers/clocksource/cs5535-clockevt.c b/drivers/clocksource/cs5535-clockevt.c index a1df588343f2..1de8cac99a0e 100644 --- a/drivers/clocksource/cs5535-clockevt.c +++ b/drivers/clocksource/cs5535-clockevt.c @@ -117,7 +117,8 @@ static irqreturn_t mfgpt_tick(int irq, void *dev_id) /* Turn off the clock (and clear the event) */ disable_timer(cs5535_event_clock); - if (clockevent_state_shutdown(&cs5535_clockevent)) + if (clockevent_state_detached(&cs5535_clockevent) || + clockevent_state_shutdown(&cs5535_clockevent)) return IRQ_HANDLED; /* Clear the counter */ diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 48eaf2879228..aa390404e85f 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c @@ -298,8 +298,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) data->needs_update = 0; } - /* resume_latency is 0 means no restriction */ - if (resume_latency && resume_latency < latency_req) + if (resume_latency < latency_req && + resume_latency != PM_QOS_RESUME_LATENCY_NO_CONSTRAINT) latency_req = resume_latency; /* Special case when user has set very strict latency requirement */ diff --git a/drivers/crypto/axis/artpec6_crypto.c b/drivers/crypto/axis/artpec6_crypto.c index d9fbbf01062b..0f9754e07719 100644 --- a/drivers/crypto/axis/artpec6_crypto.c +++ b/drivers/crypto/axis/artpec6_crypto.c @@ -349,8 +349,6 @@ struct artpec6_crypto_aead_req_ctx { /* The crypto framework makes it hard to avoid this global. */ static struct device *artpec6_crypto_dev; -static struct dentry *dbgfs_root; - #ifdef CONFIG_FAULT_INJECTION static DECLARE_FAULT_ATTR(artpec6_crypto_fail_status_read); static DECLARE_FAULT_ATTR(artpec6_crypto_fail_dma_array_full); @@ -2984,6 +2982,8 @@ struct dbgfs_u32 { char *desc; }; +static struct dentry *dbgfs_root; + static void artpec6_crypto_init_debugfs(void) { dbgfs_root = debugfs_create_dir("artpec6_crypto", NULL); diff --git a/drivers/crypto/stm32/stm32-hash.c b/drivers/crypto/stm32/stm32-hash.c index b585ce54a802..4835dd4a9e50 100644 --- a/drivers/crypto/stm32/stm32-hash.c +++ b/drivers/crypto/stm32/stm32-hash.c @@ -553,9 +553,9 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) { struct stm32_hash_request_ctx *rctx = ahash_request_ctx(hdev->req); struct scatterlist sg[1], *tsg; - int err = 0, len = 0, reg, ncp; + int err = 0, len = 0, reg, ncp = 0; unsigned int i; - const u32 *buffer = (const u32 *)rctx->buffer; + u32 *buffer = (void *)rctx->buffer; rctx->sg = hdev->req->src; rctx->total = hdev->req->nbytes; @@ -620,10 +620,13 @@ static int stm32_hash_dma_send(struct stm32_hash_dev *hdev) reg |= HASH_CR_DMAA; stm32_hash_write(hdev, HASH_CR, reg); - for (i = 0; i < DIV_ROUND_UP(ncp, sizeof(u32)); i++) - stm32_hash_write(hdev, HASH_DIN, buffer[i]); - - stm32_hash_set_nblw(hdev, ncp); + if (ncp) { + memset(buffer + ncp, 0, + DIV_ROUND_UP(ncp, sizeof(u32)) - ncp); + writesl(hdev->io_base + HASH_DIN, buffer, + DIV_ROUND_UP(ncp, sizeof(u32))); + } + stm32_hash_set_nblw(hdev, DIV_ROUND_UP(ncp, sizeof(u32))); reg = stm32_hash_read(hdev, HASH_STR); reg |= HASH_STR_DCAL; stm32_hash_write(hdev, HASH_STR, reg); diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 66fb40d0ebdb..03830634e141 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -383,7 +383,7 @@ err_put_fd: return err; } -static void sync_fill_fence_info(struct dma_fence *fence, +static int sync_fill_fence_info(struct dma_fence *fence, struct sync_fence_info *info) { strlcpy(info->obj_name, fence->ops->get_timeline_name(fence), @@ -399,6 +399,8 @@ static void sync_fill_fence_info(struct dma_fence *fence, test_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags) ? ktime_to_ns(fence->timestamp) : ktime_set(0, 0); + + return info->status; } static long sync_file_ioctl_fence_info(struct sync_file *sync_file, @@ -424,8 +426,12 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, * sync_fence_info and return the actual number of fences on * info->num_fences. */ - if (!info.num_fences) + if (!info.num_fences) { + info.status = dma_fence_is_signaled(sync_file->fence); goto no_fences; + } else { + info.status = 1; + } if (info.num_fences < num_fences) return -EINVAL; @@ -435,8 +441,10 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (!fence_info) return -ENOMEM; - for (i = 0; i < num_fences; i++) - sync_fill_fence_info(fences[i], &fence_info[i]); + for (i = 0; i < num_fences; i++) { + int status = sync_fill_fence_info(fences[i], &fence_info[i]); + info.status = info.status <= 0 ? info.status : status; + } if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info, size)) { @@ -446,7 +454,6 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, no_fences: sync_file_get_name(sync_file, info.name, sizeof(info.name)); - info.status = dma_fence_is_signaled(sync_file->fence); info.num_fences = num_fences; if (copy_to_user((void __user *)arg, &info, sizeof(info))) diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c index 32905d5606ac..55f9c62ee54b 100644 --- a/drivers/dma/altera-msgdma.c +++ b/drivers/dma/altera-msgdma.c @@ -212,11 +212,12 @@ struct msgdma_device { static struct msgdma_sw_desc *msgdma_get_descriptor(struct msgdma_device *mdev) { struct msgdma_sw_desc *desc; + unsigned long flags; - spin_lock_bh(&mdev->lock); + spin_lock_irqsave(&mdev->lock, flags); desc = list_first_entry(&mdev->free_list, struct msgdma_sw_desc, node); list_del(&desc->node); - spin_unlock_bh(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, flags); INIT_LIST_HEAD(&desc->tx_list); @@ -306,13 +307,14 @@ static dma_cookie_t msgdma_tx_submit(struct dma_async_tx_descriptor *tx) struct msgdma_device *mdev = to_mdev(tx->chan); struct msgdma_sw_desc *new; dma_cookie_t cookie; + unsigned long flags; new = tx_to_desc(tx); - spin_lock_bh(&mdev->lock); + spin_lock_irqsave(&mdev->lock, flags); cookie = dma_cookie_assign(tx); list_add_tail(&new->node, &mdev->pending_list); - spin_unlock_bh(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, flags); return cookie; } @@ -336,17 +338,18 @@ msgdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst, struct msgdma_extended_desc *desc; size_t copy; u32 desc_cnt; + unsigned long irqflags; desc_cnt = DIV_ROUND_UP(len, MSGDMA_MAX_TRANS_LEN); - spin_lock_bh(&mdev->lock); + spin_lock_irqsave(&mdev->lock, irqflags); if (desc_cnt > mdev->desc_free_cnt) { - spin_unlock_bh(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, irqflags); dev_dbg(mdev->dev, "mdev %p descs are not available\n", mdev); return NULL; } mdev->desc_free_cnt -= desc_cnt; - spin_unlock_bh(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, irqflags); do { /* Allocate and populate the descriptor */ @@ -397,18 +400,19 @@ msgdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, u32 desc_cnt = 0, i; struct scatterlist *sg; u32 stride; + unsigned long irqflags; for_each_sg(sgl, sg, sg_len, i) desc_cnt += DIV_ROUND_UP(sg_dma_len(sg), MSGDMA_MAX_TRANS_LEN); - spin_lock_bh(&mdev->lock); + spin_lock_irqsave(&mdev->lock, irqflags); if (desc_cnt > mdev->desc_free_cnt) { - spin_unlock_bh(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, irqflags); dev_dbg(mdev->dev, "mdev %p descs are not available\n", mdev); return NULL; } mdev->desc_free_cnt -= desc_cnt; - spin_unlock_bh(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, irqflags); avail = sg_dma_len(sgl); @@ -566,10 +570,11 @@ static void msgdma_start_transfer(struct msgdma_device *mdev) static void msgdma_issue_pending(struct dma_chan *chan) { struct msgdma_device *mdev = to_mdev(chan); + unsigned long flags; - spin_lock_bh(&mdev->lock); + spin_lock_irqsave(&mdev->lock, flags); msgdma_start_transfer(mdev); - spin_unlock_bh(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, flags); } /** @@ -634,10 +639,11 @@ static void msgdma_free_descriptors(struct msgdma_device *mdev) static void msgdma_free_chan_resources(struct dma_chan *dchan) { struct msgdma_device *mdev = to_mdev(dchan); + unsigned long flags; - spin_lock_bh(&mdev->lock); + spin_lock_irqsave(&mdev->lock, flags); msgdma_free_descriptors(mdev); - spin_unlock_bh(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, flags); kfree(mdev->sw_desq); } @@ -682,8 +688,9 @@ static void msgdma_tasklet(unsigned long data) u32 count; u32 __maybe_unused size; u32 __maybe_unused status; + unsigned long flags; - spin_lock(&mdev->lock); + spin_lock_irqsave(&mdev->lock, flags); /* Read number of responses that are available */ count = ioread32(mdev->csr + MSGDMA_CSR_RESP_FILL_LEVEL); @@ -698,13 +705,13 @@ static void msgdma_tasklet(unsigned long data) * bits. So we need to just drop these values. */ size = ioread32(mdev->resp + MSGDMA_RESP_BYTES_TRANSFERRED); - status = ioread32(mdev->resp - MSGDMA_RESP_STATUS); + status = ioread32(mdev->resp + MSGDMA_RESP_STATUS); msgdma_complete_descriptor(mdev); msgdma_chan_desc_cleanup(mdev); } - spin_unlock(&mdev->lock); + spin_unlock_irqrestore(&mdev->lock, flags); } /** diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c index 3879f80a4815..a7ea20e7b8e9 100644 --- a/drivers/dma/edma.c +++ b/drivers/dma/edma.c @@ -1143,11 +1143,24 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( struct edma_desc *edesc; struct device *dev = chan->device->dev; struct edma_chan *echan = to_edma_chan(chan); - unsigned int width, pset_len; + unsigned int width, pset_len, array_size; if (unlikely(!echan || !len)) return NULL; + /* Align the array size (acnt block) with the transfer properties */ + switch (__ffs((src | dest | len))) { + case 0: + array_size = SZ_32K - 1; + break; + case 1: + array_size = SZ_32K - 2; + break; + default: + array_size = SZ_32K - 4; + break; + } + if (len < SZ_64K) { /* * Transfer size less than 64K can be handled with one paRAM @@ -1169,7 +1182,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( * When the full_length is multibple of 32767 one slot can be * used to complete the transfer. */ - width = SZ_32K - 1; + width = array_size; pset_len = rounddown(len, width); /* One slot is enough for lengths multiple of (SZ_32K -1) */ if (unlikely(pset_len == len)) @@ -1217,7 +1230,7 @@ static struct dma_async_tx_descriptor *edma_prep_dma_memcpy( } dest += pset_len; src += pset_len; - pset_len = width = len % (SZ_32K - 1); + pset_len = width = len % array_size; ret = edma_config_pset(chan, &edesc->pset[1], src, dest, 1, width, pset_len, DMA_MEM_TO_MEM); diff --git a/drivers/dma/ti-dma-crossbar.c b/drivers/dma/ti-dma-crossbar.c index 2f65a8fde21d..f1d04b70ee67 100644 --- a/drivers/dma/ti-dma-crossbar.c +++ b/drivers/dma/ti-dma-crossbar.c @@ -262,13 +262,14 @@ static void *ti_dra7_xbar_route_allocate(struct of_phandle_args *dma_spec, mutex_lock(&xbar->mutex); map->xbar_out = find_first_zero_bit(xbar->dma_inuse, xbar->dma_requests); - mutex_unlock(&xbar->mutex); if (map->xbar_out == xbar->dma_requests) { + mutex_unlock(&xbar->mutex); dev_err(&pdev->dev, "Run out of free DMA requests\n"); kfree(map); return ERR_PTR(-ENOMEM); } set_bit(map->xbar_out, xbar->dma_inuse); + mutex_unlock(&xbar->mutex); map->xbar_in = (u16)dma_spec->args[0]; diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 1cb2d1c070c3..a94601d5939e 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -238,7 +238,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table, efi_random_get_seed(sys_table); - if (!nokaslr()) { + /* hibernation expects the runtime regions to stay in the same place */ + if (!IS_ENABLED(CONFIG_HIBERNATION) && !nokaslr()) { /* * Randomize the base of the UEFI runtime services region. * Preserve the 2 MB alignment of the region by taking a diff --git a/drivers/firmware/efi/test/efi_test.c b/drivers/firmware/efi/test/efi_test.c index 08129b7b80ab..41c48a1e8baa 100644 --- a/drivers/firmware/efi/test/efi_test.c +++ b/drivers/firmware/efi/test/efi_test.c @@ -593,6 +593,9 @@ static long efi_runtime_query_capsulecaps(unsigned long arg) if (copy_from_user(&qcaps, qcaps_user, sizeof(qcaps))) return -EFAULT; + if (qcaps.capsule_count == ULONG_MAX) + return -EINVAL; + capsules = kcalloc(qcaps.capsule_count + 1, sizeof(efi_capsule_header_t), GFP_KERNEL); if (!capsules) diff --git a/drivers/fpga/altera-cvp.c b/drivers/fpga/altera-cvp.c index 08629ee69d11..00e73d28077c 100644 --- a/drivers/fpga/altera-cvp.c +++ b/drivers/fpga/altera-cvp.c @@ -361,12 +361,12 @@ static const struct fpga_manager_ops altera_cvp_ops = { .write_complete = altera_cvp_write_complete, }; -static ssize_t show_chkcfg(struct device_driver *dev, char *buf) +static ssize_t chkcfg_show(struct device_driver *dev, char *buf) { return snprintf(buf, 3, "%d\n", altera_cvp_chkcfg); } -static ssize_t store_chkcfg(struct device_driver *drv, const char *buf, +static ssize_t chkcfg_store(struct device_driver *drv, const char *buf, size_t count) { int ret; @@ -378,7 +378,7 @@ static ssize_t store_chkcfg(struct device_driver *drv, const char *buf, return count; } -static DRIVER_ATTR(chkcfg, 0600, show_chkcfg, store_chkcfg); +static DRIVER_ATTR_RW(chkcfg); static int altera_cvp_probe(struct pci_dev *pdev, const struct pci_device_id *dev_id); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 3388d54ba114..3f80f167ed56 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -453,7 +453,8 @@ config GPIO_TS4800 config GPIO_THUNDERX tristate "Cavium ThunderX/OCTEON-TX GPIO" depends on ARCH_THUNDER || (64BIT && COMPILE_TEST) - depends on PCI_MSI && IRQ_DOMAIN_HIERARCHY + depends on PCI_MSI + select IRQ_DOMAIN_HIERARCHY select IRQ_FASTEOI_HIERARCHY_HANDLERS help Say yes here to support the on-chip GPIO lines on the ThunderX diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c index dbf869fb63ce..3233b72b6828 100644 --- a/drivers/gpio/gpio-omap.c +++ b/drivers/gpio/gpio-omap.c @@ -518,7 +518,13 @@ static int omap_gpio_irq_type(struct irq_data *d, unsigned type) if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) irq_set_handler_locked(d, handle_level_irq); else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING)) - irq_set_handler_locked(d, handle_edge_irq); + /* + * Edge IRQs are already cleared/acked in irq_handler and + * not need to be masked, as result handle_edge_irq() + * logic is excessed here and may cause lose of interrupts. + * So just use handle_simple_irq. + */ + irq_set_handler_locked(d, handle_simple_irq); return 0; @@ -678,7 +684,7 @@ static void omap_gpio_free(struct gpio_chip *chip, unsigned offset) static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) { void __iomem *isr_reg = NULL; - u32 isr; + u32 enabled, isr, level_mask; unsigned int bit; struct gpio_bank *bank = gpiobank; unsigned long wa_lock_flags; @@ -691,23 +697,21 @@ static irqreturn_t omap_gpio_irq_handler(int irq, void *gpiobank) pm_runtime_get_sync(bank->chip.parent); while (1) { - u32 isr_saved, level_mask = 0; - u32 enabled; - raw_spin_lock_irqsave(&bank->lock, lock_flags); enabled = omap_get_gpio_irqbank_mask(bank); - isr_saved = isr = readl_relaxed(isr_reg) & enabled; + isr = readl_relaxed(isr_reg) & enabled; if (bank->level_mask) level_mask = bank->level_mask & enabled; + else + level_mask = 0; /* clear edge sensitive interrupts before handler(s) are called so that we don't miss any interrupt occurred while executing them */ - omap_disable_gpio_irqbank(bank, isr_saved & ~level_mask); - omap_clear_gpio_irqbank(bank, isr_saved & ~level_mask); - omap_enable_gpio_irqbank(bank, isr_saved & ~level_mask); + if (isr & ~level_mask) + omap_clear_gpio_irqbank(bank, isr & ~level_mask); raw_spin_unlock_irqrestore(&bank->lock, lock_flags); @@ -1010,7 +1014,7 @@ static void omap_gpio_set(struct gpio_chip *chip, unsigned offset, int value) /*---------------------------------------------------------------------*/ -static void __init omap_gpio_show_rev(struct gpio_bank *bank) +static void omap_gpio_show_rev(struct gpio_bank *bank) { static bool called; u32 rev; diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 4d2113530735..eb4528c87c0b 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c @@ -203,7 +203,7 @@ static acpi_status acpi_gpiochip_request_interrupt(struct acpi_resource *ares, if (pin <= 255) { char ev_name[5]; - sprintf(ev_name, "_%c%02X", + sprintf(ev_name, "_%c%02hhX", agpio->triggering == ACPI_EDGE_SENSITIVE ? 'E' : 'L', pin); if (ACPI_SUCCESS(acpi_get_handle(handle, ev_name, &evt_handle))) diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index a3fdc5a68dff..81ff79336623 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -17,7 +17,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm_encoder.o drm_mode_object.o drm_property.o \ drm_plane.o drm_color_mgmt.o drm_print.o \ drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \ - drm_syncobj.o + drm_syncobj.o drm_lease.o drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o drm-$(CONFIG_DRM_VM) += drm_vm.o diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 25a95c95df14..ef9a3b6d7b62 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -25,7 +25,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_prime.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ amdgpu_gtt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o amdgpu_atomfirmware.o \ - amdgpu_queue_mgr.o amdgpu_vf_error.o + amdgpu_queue_mgr.o amdgpu_vf_error.o amdgpu_sched.o # add asic specific block amdgpu-$(CONFIG_DRM_AMDGPU_CIK)+= cik.o cik_ih.o kv_smc.o kv_dpm.o \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index ebfc267467ee..cbcb6a153aba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -121,6 +121,7 @@ extern int amdgpu_cntl_sb_buf_per_se; extern int amdgpu_param_buf_per_se; extern int amdgpu_job_hang_limit; extern int amdgpu_lbpw; +extern int amdgpu_compute_multipipe; #ifdef CONFIG_DRM_AMDGPU_SI extern int amdgpu_si_support; @@ -731,10 +732,14 @@ struct amdgpu_ctx { struct amdgpu_device *adev; struct amdgpu_queue_mgr queue_mgr; unsigned reset_counter; + uint32_t vram_lost_counter; spinlock_t ring_lock; struct dma_fence **fences; struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS]; - bool preamble_presented; + bool preamble_presented; + enum amd_sched_priority init_priority; + enum amd_sched_priority override_priority; + struct mutex lock; }; struct amdgpu_ctx_mgr { @@ -751,13 +756,18 @@ int amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, struct dma_fence *fence, uint64_t *seq); struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, uint64_t seq); +void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx, + enum amd_sched_priority priority); int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx, unsigned ring_id); + void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr); void amdgpu_ctx_mgr_fini(struct amdgpu_ctx_mgr *mgr); + /* * file private structure */ @@ -769,7 +779,6 @@ struct amdgpu_fpriv { struct mutex bo_list_lock; struct idr bo_list_handles; struct amdgpu_ctx_mgr ctx_mgr; - u32 vram_lost_counter; }; /* @@ -870,7 +879,7 @@ struct amdgpu_mec { struct amdgpu_kiq { u64 eop_gpu_addr; struct amdgpu_bo *eop_obj; - struct mutex ring_mutex; + spinlock_t ring_lock; struct amdgpu_ring ring; struct amdgpu_irq_src irq; }; @@ -1034,6 +1043,10 @@ struct amdgpu_gfx { bool in_suspend; /* NGG */ struct amdgpu_ngg ngg; + + /* pipe reservation */ + struct mutex pipe_reserve_mutex; + DECLARE_BITMAP (pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES); }; int amdgpu_ib_get(struct amdgpu_device *adev, struct amdgpu_vm *vm, @@ -1112,6 +1125,7 @@ struct amdgpu_job { uint32_t gds_base, gds_size; uint32_t gws_base, gws_size; uint32_t oa_base, oa_size; + uint32_t vram_lost_counter; /* user fence handling */ uint64_t uf_addr; @@ -1137,7 +1151,7 @@ static inline void amdgpu_set_ib_value(struct amdgpu_cs_parser *p, /* * Writeback */ -#define AMDGPU_MAX_WB 1024 /* Reserve at most 1024 WB slots for amdgpu-owned rings. */ +#define AMDGPU_MAX_WB 512 /* Reserve at most 512 WB slots for amdgpu-owned rings. */ struct amdgpu_wb { struct amdgpu_bo *wb_obj; @@ -1310,6 +1324,8 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); +int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); @@ -1376,6 +1392,18 @@ struct amdgpu_atcs { }; /* + * Firmware VRAM reservation + */ +struct amdgpu_fw_vram_usage { + u64 start_offset; + u64 size; + struct amdgpu_bo *reserved_bo; + void *va; +}; + +int amdgpu_fw_reserve_vram_init(struct amdgpu_device *adev); + +/* * CGS */ struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev); @@ -1524,7 +1552,6 @@ struct amdgpu_device { /* powerplay */ struct amd_powerplay powerplay; - bool pp_enabled; bool pp_force_state_enabled; /* dpm */ @@ -1580,6 +1607,8 @@ struct amdgpu_device { struct delayed_work late_init_work; struct amdgpu_virt virt; + /* firmware VRAM reservation */ + struct amdgpu_fw_vram_usage fw_vram_usage; /* link all shadow bo */ struct list_head shadow_list; @@ -1831,8 +1860,6 @@ static inline bool amdgpu_has_atpx(void) { return false; } extern const struct drm_ioctl_desc amdgpu_ioctls_kms[]; extern const int amdgpu_max_kms_ioctl; -bool amdgpu_kms_vram_lost(struct amdgpu_device *adev, - struct amdgpu_fpriv *fpriv); int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags); void amdgpu_driver_unload_kms(struct drm_device *dev); void amdgpu_driver_lastclose_kms(struct drm_device *dev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c index a52795d9b458..c04f44a90392 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acp.c @@ -35,41 +35,50 @@ #include "acp_gfx_if.h" -#define ACP_TILE_ON_MASK 0x03 -#define ACP_TILE_OFF_MASK 0x02 -#define ACP_TILE_ON_RETAIN_REG_MASK 0x1f -#define ACP_TILE_OFF_RETAIN_REG_MASK 0x20 - -#define ACP_TILE_P1_MASK 0x3e -#define ACP_TILE_P2_MASK 0x3d -#define ACP_TILE_DSP0_MASK 0x3b -#define ACP_TILE_DSP1_MASK 0x37 - -#define ACP_TILE_DSP2_MASK 0x2f - -#define ACP_DMA_REGS_END 0x146c0 -#define ACP_I2S_PLAY_REGS_START 0x14840 -#define ACP_I2S_PLAY_REGS_END 0x148b4 -#define ACP_I2S_CAP_REGS_START 0x148b8 -#define ACP_I2S_CAP_REGS_END 0x1496c - -#define ACP_I2S_COMP1_CAP_REG_OFFSET 0xac -#define ACP_I2S_COMP2_CAP_REG_OFFSET 0xa8 -#define ACP_I2S_COMP1_PLAY_REG_OFFSET 0x6c -#define ACP_I2S_COMP2_PLAY_REG_OFFSET 0x68 - -#define mmACP_PGFSM_RETAIN_REG 0x51c9 -#define mmACP_PGFSM_CONFIG_REG 0x51ca -#define mmACP_PGFSM_READ_REG_0 0x51cc - -#define mmACP_MEM_SHUT_DOWN_REQ_LO 0x51f8 -#define mmACP_MEM_SHUT_DOWN_REQ_HI 0x51f9 -#define mmACP_MEM_SHUT_DOWN_STS_LO 0x51fa -#define mmACP_MEM_SHUT_DOWN_STS_HI 0x51fb - -#define ACP_TIMEOUT_LOOP 0x000000FF -#define ACP_DEVS 3 -#define ACP_SRC_ID 162 +#define ACP_TILE_ON_MASK 0x03 +#define ACP_TILE_OFF_MASK 0x02 +#define ACP_TILE_ON_RETAIN_REG_MASK 0x1f +#define ACP_TILE_OFF_RETAIN_REG_MASK 0x20 + +#define ACP_TILE_P1_MASK 0x3e +#define ACP_TILE_P2_MASK 0x3d +#define ACP_TILE_DSP0_MASK 0x3b +#define ACP_TILE_DSP1_MASK 0x37 + +#define ACP_TILE_DSP2_MASK 0x2f + +#define ACP_DMA_REGS_END 0x146c0 +#define ACP_I2S_PLAY_REGS_START 0x14840 +#define ACP_I2S_PLAY_REGS_END 0x148b4 +#define ACP_I2S_CAP_REGS_START 0x148b8 +#define ACP_I2S_CAP_REGS_END 0x1496c + +#define ACP_I2S_COMP1_CAP_REG_OFFSET 0xac +#define ACP_I2S_COMP2_CAP_REG_OFFSET 0xa8 +#define ACP_I2S_COMP1_PLAY_REG_OFFSET 0x6c +#define ACP_I2S_COMP2_PLAY_REG_OFFSET 0x68 + +#define mmACP_PGFSM_RETAIN_REG 0x51c9 +#define mmACP_PGFSM_CONFIG_REG 0x51ca +#define mmACP_PGFSM_READ_REG_0 0x51cc + +#define mmACP_MEM_SHUT_DOWN_REQ_LO 0x51f8 +#define mmACP_MEM_SHUT_DOWN_REQ_HI 0x51f9 +#define mmACP_MEM_SHUT_DOWN_STS_LO 0x51fa +#define mmACP_MEM_SHUT_DOWN_STS_HI 0x51fb + +#define mmACP_CONTROL 0x5131 +#define mmACP_STATUS 0x5133 +#define mmACP_SOFT_RESET 0x5134 +#define ACP_CONTROL__ClkEn_MASK 0x1 +#define ACP_SOFT_RESET__SoftResetAud_MASK 0x100 +#define ACP_SOFT_RESET__SoftResetAudDone_MASK 0x1000000 +#define ACP_CLOCK_EN_TIME_OUT_VALUE 0x000000FF +#define ACP_SOFT_RESET_DONE_TIME_OUT_VALUE 0x000000FF + +#define ACP_TIMEOUT_LOOP 0x000000FF +#define ACP_DEVS 3 +#define ACP_SRC_ID 162 enum { ACP_TILE_P1 = 0, @@ -260,6 +269,8 @@ static int acp_hw_init(void *handle) { int r, i; uint64_t acp_base; + u32 val = 0; + u32 count = 0; struct device *dev; struct i2s_platform_data *i2s_pdata; @@ -371,6 +382,8 @@ static int acp_hw_init(void *handle) adev->acp.acp_cell[0].name = "acp_audio_dma"; adev->acp.acp_cell[0].num_resources = 4; adev->acp.acp_cell[0].resources = &adev->acp.acp_res[0]; + adev->acp.acp_cell[0].platform_data = &adev->asic_type; + adev->acp.acp_cell[0].pdata_size = sizeof(adev->asic_type); adev->acp.acp_cell[1].name = "designware-i2s"; adev->acp.acp_cell[1].num_resources = 1; @@ -400,6 +413,46 @@ static int acp_hw_init(void *handle) } } + /* Assert Soft reset of ACP */ + val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); + + val |= ACP_SOFT_RESET__SoftResetAud_MASK; + cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val); + + count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE; + while (true) { + val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); + if (ACP_SOFT_RESET__SoftResetAudDone_MASK == + (val & ACP_SOFT_RESET__SoftResetAudDone_MASK)) + break; + if (--count == 0) { + dev_err(&adev->pdev->dev, "Failed to reset ACP\n"); + return -ETIMEDOUT; + } + udelay(100); + } + /* Enable clock to ACP and wait until the clock is enabled */ + val = cgs_read_register(adev->acp.cgs_device, mmACP_CONTROL); + val = val | ACP_CONTROL__ClkEn_MASK; + cgs_write_register(adev->acp.cgs_device, mmACP_CONTROL, val); + + count = ACP_CLOCK_EN_TIME_OUT_VALUE; + + while (true) { + val = cgs_read_register(adev->acp.cgs_device, mmACP_STATUS); + if (val & (u32) 0x1) + break; + if (--count == 0) { + dev_err(&adev->pdev->dev, "Failed to reset ACP\n"); + return -ETIMEDOUT; + } + udelay(100); + } + /* Deassert the SOFT RESET flags */ + val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); + val &= ~ACP_SOFT_RESET__SoftResetAud_MASK; + cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val); + return 0; } @@ -412,6 +465,8 @@ static int acp_hw_init(void *handle) static int acp_hw_fini(void *handle) { int i, ret; + u32 val = 0; + u32 count = 0; struct device *dev; struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -419,6 +474,42 @@ static int acp_hw_fini(void *handle) if (!adev->acp.acp_cell) return 0; + /* Assert Soft reset of ACP */ + val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); + + val |= ACP_SOFT_RESET__SoftResetAud_MASK; + cgs_write_register(adev->acp.cgs_device, mmACP_SOFT_RESET, val); + + count = ACP_SOFT_RESET_DONE_TIME_OUT_VALUE; + while (true) { + val = cgs_read_register(adev->acp.cgs_device, mmACP_SOFT_RESET); + if (ACP_SOFT_RESET__SoftResetAudDone_MASK == + (val & ACP_SOFT_RESET__SoftResetAudDone_MASK)) + break; + if (--count == 0) { + dev_err(&adev->pdev->dev, "Failed to reset ACP\n"); + return -ETIMEDOUT; + } + udelay(100); + } + /* Disable ACP clock */ + val = cgs_read_register(adev->acp.cgs_device, mmACP_CONTROL); + val &= ~ACP_CONTROL__ClkEn_MASK; + cgs_write_register(adev->acp.cgs_device, mmACP_CONTROL, val); + + count = ACP_CLOCK_EN_TIME_OUT_VALUE; + + while (true) { + val = cgs_read_register(adev->acp.cgs_device, mmACP_STATUS); + if (val & (u32) 0x1) + break; + if (--count == 0) { + dev_err(&adev->pdev->dev, "Failed to reset ACP\n"); + return -ETIMEDOUT; + } + udelay(100); + } + if (adev->acp.acp_genpd) { for (i = 0; i < ACP_DEVS ; i++) { dev = get_mfd_cell_dev(adev->acp.acp_cell[i].name, i); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c index dc7e25cce741..47d1c132ac40 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v7.c @@ -338,6 +338,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, struct cik_mqd *m; uint32_t *mqd_hqd; uint32_t reg, wptr_val, data; + bool valid_wptr = false; m = get_mqd(mqd); @@ -356,7 +357,14 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1); WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, data); - if (read_user_wptr(mm, wptr, wptr_val)) + /* read_user_ptr may take the mm->mmap_sem. + * release srbm_mutex to avoid circular dependency between + * srbm_mutex->mm_sem->reservation_ww_class_mutex->srbm_mutex. + */ + release_queue(kgd); + valid_wptr = read_user_wptr(mm, wptr, wptr_val); + acquire_queue(kgd, pipe_id, queue_id); + if (valid_wptr) WREG32(mmCP_HQD_PQ_WPTR, (wptr_val << wptr_shift) & wptr_mask); data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c index c678c69936a0..056929b8ccd0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gfx_v8.c @@ -292,6 +292,7 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, struct vi_mqd *m; uint32_t *mqd_hqd; uint32_t reg, wptr_val, data; + bool valid_wptr = false; m = get_mqd(mqd); @@ -339,7 +340,14 @@ static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1); WREG32(mmCP_HQD_PQ_DOORBELL_CONTROL, data); - if (read_user_wptr(mm, wptr, wptr_val)) + /* read_user_ptr may take the mm->mmap_sem. + * release srbm_mutex to avoid circular dependency between + * srbm_mutex->mm_sem->reservation_ww_class_mutex->srbm_mutex. + */ + release_queue(kgd); + valid_wptr = read_user_wptr(mm, wptr, wptr_val); + acquire_queue(kgd, pipe_id, queue_id); + if (valid_wptr) WREG32(mmCP_HQD_PQ_WPTR, (wptr_val << wptr_shift) & wptr_mask); data = REG_SET_FIELD(m->cp_hqd_active, CP_HQD_ACTIVE, ACTIVE, 1); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c index ce443586a0c7..f450b69323fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c @@ -1766,34 +1766,32 @@ bool amdgpu_atombios_scratch_need_asic_init(struct amdgpu_device *adev) return true; } -/* Atom needs data in little endian format - * so swap as appropriate when copying data to - * or from atom. Note that atom operates on - * dw units. +/* Atom needs data in little endian format so swap as appropriate when copying + * data to or from atom. Note that atom operates on dw units. + * + * Use to_le=true when sending data to atom and provide at least + * ALIGN(num_bytes,4) bytes in the dst buffer. + * + * Use to_le=false when receiving data from atom and provide ALIGN(num_bytes,4) + * byes in the src buffer. */ void amdgpu_atombios_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) { #ifdef __BIG_ENDIAN - u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */ - u32 *dst32, *src32; + u32 src_tmp[5], dst_tmp[5]; int i; + u8 align_num_bytes = ALIGN(num_bytes, 4); - memcpy(src_tmp, src, num_bytes); - src32 = (u32 *)src_tmp; - dst32 = (u32 *)dst_tmp; if (to_le) { - for (i = 0; i < ((num_bytes + 3) / 4); i++) - dst32[i] = cpu_to_le32(src32[i]); - memcpy(dst, dst_tmp, num_bytes); + memcpy(src_tmp, src, num_bytes); + for (i = 0; i < align_num_bytes / 4; i++) + dst_tmp[i] = cpu_to_le32(src_tmp[i]); + memcpy(dst, dst_tmp, align_num_bytes); } else { - u8 dws = num_bytes & ~3; - for (i = 0; i < ((num_bytes + 3) / 4); i++) - dst32[i] = le32_to_cpu(src32[i]); - memcpy(dst, dst_tmp, dws); - if (num_bytes % 4) { - for (i = 0; i < (num_bytes % 4); i++) - dst[dws+i] = dst_tmp[dws+i]; - } + memcpy(src_tmp, src, align_num_bytes); + for (i = 0; i < align_num_bytes / 4; i++) + dst_tmp[i] = le32_to_cpu(src_tmp[i]); + memcpy(dst, dst_tmp, num_bytes); } #else memcpy(dst, src, num_bytes); @@ -1807,6 +1805,8 @@ int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev) uint16_t data_offset; int usage_bytes = 0; struct _ATOM_VRAM_USAGE_BY_FIRMWARE *firmware_usage; + u64 start_addr; + u64 size; if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { firmware_usage = (struct _ATOM_VRAM_USAGE_BY_FIRMWARE *)(ctx->bios + data_offset); @@ -1815,7 +1815,21 @@ int amdgpu_atombios_allocate_fb_scratch(struct amdgpu_device *adev) le32_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware), le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb)); - usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024; + start_addr = firmware_usage->asFirmwareVramReserveInfo[0].ulStartAddrUsedByFirmware; + size = firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb; + + if ((uint32_t)(start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) == + (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << + ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { + /* Firmware request VRAM reservation for SR-IOV */ + adev->fw_vram_usage.start_offset = (start_addr & + (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; + adev->fw_vram_usage.size = size << 10; + /* Use the default scratch size */ + usage_bytes = 0; + } else { + usage_bytes = le16_to_cpu(firmware_usage->asFirmwareVramReserveInfo[0].usFirmwareUseInKb) * 1024; + } } ctx->scratch_size_bytes = 0; if (usage_bytes == 0) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c index f9ffe8ef0cd6..ff8efd0f8fd5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c @@ -71,19 +71,33 @@ int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev) struct atom_context *ctx = adev->mode_info.atom_context; int index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1, vram_usagebyfirmware); + struct vram_usagebyfirmware_v2_1 * firmware_usage; + uint32_t start_addr, size; uint16_t data_offset; int usage_bytes = 0; if (amdgpu_atom_parse_data_header(ctx, index, NULL, NULL, NULL, &data_offset)) { - struct vram_usagebyfirmware_v2_1 *firmware_usage = - (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset); - + firmware_usage = (struct vram_usagebyfirmware_v2_1 *)(ctx->bios + data_offset); DRM_DEBUG("atom firmware requested %08x %dkb fw %dkb drv\n", le32_to_cpu(firmware_usage->start_address_in_kb), le16_to_cpu(firmware_usage->used_by_firmware_in_kb), le16_to_cpu(firmware_usage->used_by_driver_in_kb)); - usage_bytes = le16_to_cpu(firmware_usage->used_by_driver_in_kb) * 1024; + start_addr = le32_to_cpu(firmware_usage->start_address_in_kb); + size = le16_to_cpu(firmware_usage->used_by_firmware_in_kb); + + if ((uint32_t)(start_addr & ATOM_VRAM_OPERATION_FLAGS_MASK) == + (uint32_t)(ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION << + ATOM_VRAM_OPERATION_FLAGS_SHIFT)) { + /* Firmware request VRAM reservation for SR-IOV */ + adev->fw_vram_usage.start_offset = (start_addr & + (~ATOM_VRAM_OPERATION_FLAGS_MASK)) << 10; + adev->fw_vram_usage.size = size << 10; + /* Use the default scratch size */ + usage_bytes = 0; + } else { + usage_bytes = le16_to_cpu(firmware_usage->used_by_driver_in_kb) << 10; + } } ctx->scratch_size_bytes = 0; if (usage_bytes == 0) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 383204e911a4..a7afe553e0a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -42,6 +42,28 @@ struct amdgpu_cgs_device { struct amdgpu_device *adev = \ ((struct amdgpu_cgs_device *)cgs_device)->adev +static void *amdgpu_cgs_register_pp_handle(struct cgs_device *cgs_device, + int (*call_back_func)(struct amd_pp_init *, void **)) +{ + CGS_FUNC_ADEV; + struct amd_pp_init pp_init; + struct amd_powerplay *amd_pp; + + if (call_back_func == NULL) + return NULL; + + amd_pp = &(adev->powerplay); + pp_init.chip_family = adev->family; + pp_init.chip_id = adev->asic_type; + pp_init.pm_en = (amdgpu_dpm != 0 && !amdgpu_sriov_vf(adev)) ? true : false; + pp_init.feature_mask = amdgpu_pp_feature_mask; + pp_init.device = cgs_device; + if (call_back_func(&pp_init, &(amd_pp->pp_handle))) + return NULL; + + return adev->powerplay.pp_handle; +} + static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type, uint64_t size, uint64_t align, @@ -1179,6 +1201,7 @@ static const struct cgs_ops amdgpu_cgs_ops = { .is_virtualization_enabled = amdgpu_cgs_is_virtualization_enabled, .enter_safe_mode = amdgpu_cgs_enter_safe_mode, .lock_grbm_idx = amdgpu_cgs_lock_grbm_idx, + .register_pp_handle = amdgpu_cgs_register_pp_handle, }; static const struct cgs_os_ops amdgpu_cgs_os_ops = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 126be9e0f05f..8ca3783f2deb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -231,7 +231,7 @@ amdgpu_connector_update_scratch_regs(struct drm_connector *connector, if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -256,7 +256,7 @@ amdgpu_connector_find_encoder(struct drm_connector *connector, for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -371,7 +371,7 @@ amdgpu_connector_best_single_encoder(struct drm_connector *connector) /* pick the encoder ids */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } @@ -1076,7 +1076,7 @@ amdgpu_connector_dvi_detect(struct drm_connector *connector, bool force) if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -1133,7 +1133,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -1152,7 +1152,7 @@ amdgpu_connector_dvi_encoder(struct drm_connector *connector) /* then check use digitial */ /* pick the first one */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } @@ -1293,7 +1293,7 @@ u16 amdgpu_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -1322,7 +1322,7 @@ static bool amdgpu_connector_encoder_is_hbr2(struct drm_connector *connector) for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index c6a214f1e991..f7fceb63413c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -25,6 +25,7 @@ * Jerome Glisse <glisse@freedesktop.org> */ #include <linux/pagemap.h> +#include <linux/sync_file.h> #include <drm/drmP.h> #include <drm/amdgpu_drm.h> #include <drm/drm_syncobj.h> @@ -89,12 +90,14 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) goto free_chunk; } + mutex_lock(&p->ctx->lock); + /* get chunks */ chunk_array_user = u64_to_user_ptr(cs->in.chunks); if (copy_from_user(chunk_array, chunk_array_user, sizeof(uint64_t)*cs->in.num_chunks)) { ret = -EFAULT; - goto put_ctx; + goto free_chunk; } p->nchunks = cs->in.num_chunks; @@ -102,7 +105,7 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) GFP_KERNEL); if (!p->chunks) { ret = -ENOMEM; - goto put_ctx; + goto free_chunk; } for (i = 0; i < p->nchunks; i++) { @@ -169,6 +172,11 @@ static int amdgpu_cs_parser_init(struct amdgpu_cs_parser *p, void *data) if (ret) goto free_all_kdata; + if (p->ctx->vram_lost_counter != p->job->vram_lost_counter) { + ret = -ECANCELED; + goto free_all_kdata; + } + if (p->uf_entry.robj) p->job->uf_addr = uf_offset; kfree(chunk_array); @@ -182,8 +190,6 @@ free_partial_kdata: kfree(p->chunks); p->chunks = NULL; p->nchunks = 0; -put_ctx: - amdgpu_ctx_put(p->ctx); free_chunk: kfree(chunk_array); @@ -704,7 +710,8 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) list_for_each_entry(e, &p->validated, tv.head) { struct reservation_object *resv = e->robj->tbo.resv; - r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp); + r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp, + amdgpu_bo_explicit_sync(e->robj)); if (r) return r; @@ -735,8 +742,10 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, dma_fence_put(parser->fence); - if (parser->ctx) + if (parser->ctx) { + mutex_unlock(&parser->ctx->lock); amdgpu_ctx_put(parser->ctx); + } if (parser->bo_list) amdgpu_bo_list_put(parser->bo_list); @@ -843,14 +852,58 @@ static int amdgpu_cs_ib_vm_chunk(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv = p->filp->driver_priv; struct amdgpu_vm *vm = &fpriv->vm; struct amdgpu_ring *ring = p->job->ring; - int i, r; + int r; /* Only for UVD/VCE VM emulation */ - if (ring->funcs->parse_cs) { - for (i = 0; i < p->job->num_ibs; i++) { - r = amdgpu_ring_parse_cs(ring, p, i); + if (p->job->ring->funcs->parse_cs) { + unsigned i, j; + + for (i = 0, j = 0; i < p->nchunks && j < p->job->num_ibs; i++) { + struct drm_amdgpu_cs_chunk_ib *chunk_ib; + struct amdgpu_bo_va_mapping *m; + struct amdgpu_bo *aobj = NULL; + struct amdgpu_cs_chunk *chunk; + struct amdgpu_ib *ib; + uint64_t offset; + uint8_t *kptr; + + chunk = &p->chunks[i]; + ib = &p->job->ibs[j]; + chunk_ib = chunk->kdata; + + if (chunk->chunk_id != AMDGPU_CHUNK_ID_IB) + continue; + + r = amdgpu_cs_find_mapping(p, chunk_ib->va_start, + &aobj, &m); + if (r) { + DRM_ERROR("IB va_start is invalid\n"); + return r; + } + + if ((chunk_ib->va_start + chunk_ib->ib_bytes) > + (m->last + 1) * AMDGPU_GPU_PAGE_SIZE) { + DRM_ERROR("IB va_start+ib_bytes is invalid\n"); + return -EINVAL; + } + + /* the IB should be reserved at this point */ + r = amdgpu_bo_kmap(aobj, (void **)&kptr); + if (r) { + return r; + } + + offset = m->start * AMDGPU_GPU_PAGE_SIZE; + kptr += chunk_ib->va_start - offset; + + memcpy(ib->ptr, kptr, chunk_ib->ib_bytes); + amdgpu_bo_kunmap(aobj); + + r = amdgpu_ring_parse_cs(ring, p, j); if (r) return r; + + j++; } } @@ -917,54 +970,18 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, parser->job->ring = ring; - if (ring->funcs->parse_cs) { - struct amdgpu_bo_va_mapping *m; - struct amdgpu_bo *aobj = NULL; - uint64_t offset; - uint8_t *kptr; - - r = amdgpu_cs_find_mapping(parser, chunk_ib->va_start, - &aobj, &m); - if (r) { - DRM_ERROR("IB va_start is invalid\n"); - return r; - } - - if ((chunk_ib->va_start + chunk_ib->ib_bytes) > - (m->last + 1) * AMDGPU_GPU_PAGE_SIZE) { - DRM_ERROR("IB va_start+ib_bytes is invalid\n"); - return -EINVAL; - } - - /* the IB should be reserved at this point */ - r = amdgpu_bo_kmap(aobj, (void **)&kptr); - if (r) { - return r; - } - - offset = m->start * AMDGPU_GPU_PAGE_SIZE; - kptr += chunk_ib->va_start - offset; - - r = amdgpu_ib_get(adev, vm, chunk_ib->ib_bytes, ib); - if (r) { - DRM_ERROR("Failed to get ib !\n"); - return r; - } - - memcpy(ib->ptr, kptr, chunk_ib->ib_bytes); - amdgpu_bo_kunmap(aobj); - } else { - r = amdgpu_ib_get(adev, vm, 0, ib); - if (r) { - DRM_ERROR("Failed to get ib !\n"); - return r; - } - + r = amdgpu_ib_get(adev, vm, + ring->funcs->parse_cs ? chunk_ib->ib_bytes : 0, + ib); + if (r) { + DRM_ERROR("Failed to get ib !\n"); + return r; } ib->gpu_addr = chunk_ib->va_start; ib->length_dw = chunk_ib->ib_bytes / 4; ib->flags = chunk_ib->flags; + j++; } @@ -974,7 +991,7 @@ static int amdgpu_cs_ib_fill(struct amdgpu_device *adev, parser->job->ring->funcs->type == AMDGPU_RING_TYPE_VCE)) return -EINVAL; - return 0; + return amdgpu_ctx_wait_prev_fence(parser->ctx, parser->job->ring->idx); } static int amdgpu_cs_process_fence_dep(struct amdgpu_cs_parser *p, @@ -1175,6 +1192,8 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, job->uf_sequence = seq; amdgpu_job_free_resources(job); + amdgpu_ring_priority_get(job->ring, + amd_sched_get_job_priority(&job->base)); trace_amdgpu_cs_ioctl(job); amd_sched_entity_push_job(&job->base); @@ -1188,7 +1207,6 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p, int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_fpriv *fpriv = filp->driver_priv; union drm_amdgpu_cs *cs = data; struct amdgpu_cs_parser parser = {}; bool reserved_buffers = false; @@ -1196,8 +1214,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) if (!adev->accel_working) return -EBUSY; - if (amdgpu_kms_vram_lost(adev, fpriv)) - return -ENODEV; parser.adev = adev; parser.filp = filp; @@ -1208,6 +1224,10 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) goto out; } + r = amdgpu_cs_ib_fill(adev, &parser); + if (r) + goto out; + r = amdgpu_cs_parser_bos(&parser, data); if (r) { if (r == -ENOMEM) @@ -1218,9 +1238,6 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) } reserved_buffers = true; - r = amdgpu_cs_ib_fill(adev, &parser); - if (r) - goto out; r = amdgpu_cs_dependencies(adev, &parser); if (r) { @@ -1256,16 +1273,12 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, { union drm_amdgpu_wait_cs *wait = data; struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_fpriv *fpriv = filp->driver_priv; unsigned long timeout = amdgpu_gem_timeout(wait->in.timeout); struct amdgpu_ring *ring = NULL; struct amdgpu_ctx *ctx; struct dma_fence *fence; long r; - if (amdgpu_kms_vram_lost(adev, fpriv)) - return -ENODEV; - ctx = amdgpu_ctx_get(filp->driver_priv, wait->in.ctx_id); if (ctx == NULL) return -EINVAL; @@ -1283,6 +1296,8 @@ int amdgpu_cs_wait_ioctl(struct drm_device *dev, void *data, r = PTR_ERR(fence); else if (fence) { r = dma_fence_wait_timeout(fence, true, timeout); + if (r > 0 && fence->error) + r = fence->error; dma_fence_put(fence); } else r = 1; @@ -1330,6 +1345,62 @@ static struct dma_fence *amdgpu_cs_get_fence(struct amdgpu_device *adev, return fence; } +int amdgpu_cs_fence_to_handle_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + struct amdgpu_device *adev = dev->dev_private; + union drm_amdgpu_fence_to_handle *info = data; + struct dma_fence *fence; + struct drm_syncobj *syncobj; + struct sync_file *sync_file; + int fd, r; + + fence = amdgpu_cs_get_fence(adev, filp, &info->in.fence); + if (IS_ERR(fence)) + return PTR_ERR(fence); + + switch (info->in.what) { + case AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ: + r = drm_syncobj_create(&syncobj, 0, fence); + dma_fence_put(fence); + if (r) + return r; + r = drm_syncobj_get_handle(filp, syncobj, &info->out.handle); + drm_syncobj_put(syncobj); + return r; + + case AMDGPU_FENCE_TO_HANDLE_GET_SYNCOBJ_FD: + r = drm_syncobj_create(&syncobj, 0, fence); + dma_fence_put(fence); + if (r) + return r; + r = drm_syncobj_get_fd(syncobj, (int*)&info->out.handle); + drm_syncobj_put(syncobj); + return r; + + case AMDGPU_FENCE_TO_HANDLE_GET_SYNC_FILE_FD: + fd = get_unused_fd_flags(O_CLOEXEC); + if (fd < 0) { + dma_fence_put(fence); + return fd; + } + + sync_file = sync_file_create(fence); + dma_fence_put(fence); + if (!sync_file) { + put_unused_fd(fd); + return -ENOMEM; + } + + fd_install(fd, sync_file->file); + info->out.handle = fd; + return 0; + + default: + return -EINVAL; + } +} + /** * amdgpu_cs_wait_all_fence - wait on all fences to signal * @@ -1364,6 +1435,9 @@ static int amdgpu_cs_wait_all_fences(struct amdgpu_device *adev, if (r == 0) break; + + if (fence->error) + return fence->error; } memset(wait, 0, sizeof(*wait)); @@ -1424,7 +1498,7 @@ out: wait->out.status = (r > 0); wait->out.first_signaled = first; /* set return value 0 to indicate success */ - r = 0; + r = array[first]->error; err_free_fence_array: for (i = 0; i < fence_count; i++) @@ -1445,15 +1519,12 @@ int amdgpu_cs_wait_fences_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_fpriv *fpriv = filp->driver_priv; union drm_amdgpu_wait_fences *wait = data; uint32_t fence_count = wait->in.fence_count; struct drm_amdgpu_fence *fences_user; struct drm_amdgpu_fence *fences; int r; - if (amdgpu_kms_vram_lost(adev, fpriv)) - return -ENODEV; /* Get the fences from userspace */ fences = kmalloc_array(fence_count, sizeof(struct drm_amdgpu_fence), GFP_KERNEL); @@ -1511,14 +1582,14 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, if (READ_ONCE((*bo)->tbo.resv->lock.ctx) != &parser->ticket) return -EINVAL; - r = amdgpu_ttm_bind(&(*bo)->tbo, &(*bo)->tbo.mem); - if (unlikely(r)) - return r; - - if ((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS) - return 0; + if (!((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) { + (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; + amdgpu_ttm_placement_from_domain(*bo, (*bo)->allowed_domains); + r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, false, + false); + if (r) + return r; + } - (*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS; - amdgpu_ttm_placement_from_domain(*bo, (*bo)->allowed_domains); - return ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, false, false); + return amdgpu_ttm_bind(&(*bo)->tbo, &(*bo)->tbo.mem); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index 75c933b1a432..c184468e2b2b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -23,13 +23,41 @@ */ #include <drm/drmP.h> +#include <drm/drm_auth.h> #include "amdgpu.h" +#include "amdgpu_sched.h" -static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx) +static int amdgpu_ctx_priority_permit(struct drm_file *filp, + enum amd_sched_priority priority) +{ + /* NORMAL and below are accessible by everyone */ + if (priority <= AMD_SCHED_PRIORITY_NORMAL) + return 0; + + if (capable(CAP_SYS_NICE)) + return 0; + + if (drm_is_current_master(filp)) + return 0; + + return -EACCES; +} + +static int amdgpu_ctx_init(struct amdgpu_device *adev, + enum amd_sched_priority priority, + struct drm_file *filp, + struct amdgpu_ctx *ctx) { unsigned i, j; int r; + if (priority < 0 || priority >= AMD_SCHED_PRIORITY_MAX) + return -EINVAL; + + r = amdgpu_ctx_priority_permit(filp, priority); + if (r) + return r; + memset(ctx, 0, sizeof(*ctx)); ctx->adev = adev; kref_init(&ctx->refcount); @@ -39,19 +67,24 @@ static int amdgpu_ctx_init(struct amdgpu_device *adev, struct amdgpu_ctx *ctx) if (!ctx->fences) return -ENOMEM; + mutex_init(&ctx->lock); + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { ctx->rings[i].sequence = 1; ctx->rings[i].fences = &ctx->fences[amdgpu_sched_jobs * i]; } ctx->reset_counter = atomic_read(&adev->gpu_reset_counter); + ctx->vram_lost_counter = atomic_read(&adev->vram_lost_counter); + ctx->init_priority = priority; + ctx->override_priority = AMD_SCHED_PRIORITY_UNSET; /* create context entity for each ring */ for (i = 0; i < adev->num_rings; i++) { struct amdgpu_ring *ring = adev->rings[i]; struct amd_sched_rq *rq; - rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL]; + rq = &ring->sched.sched_rq[priority]; if (ring == &adev->gfx.kiq.ring) continue; @@ -96,10 +129,14 @@ static void amdgpu_ctx_fini(struct amdgpu_ctx *ctx) &ctx->rings[i].entity); amdgpu_queue_mgr_fini(adev, &ctx->queue_mgr); + + mutex_destroy(&ctx->lock); } static int amdgpu_ctx_alloc(struct amdgpu_device *adev, struct amdgpu_fpriv *fpriv, + struct drm_file *filp, + enum amd_sched_priority priority, uint32_t *id) { struct amdgpu_ctx_mgr *mgr = &fpriv->ctx_mgr; @@ -117,8 +154,9 @@ static int amdgpu_ctx_alloc(struct amdgpu_device *adev, kfree(ctx); return r; } + *id = (uint32_t)r; - r = amdgpu_ctx_init(adev, ctx); + r = amdgpu_ctx_init(adev, priority, filp, ctx); if (r) { idr_remove(&mgr->ctx_handles, *id); *id = 0; @@ -193,6 +231,7 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, { int r; uint32_t id; + enum amd_sched_priority priority; union drm_amdgpu_ctx *args = data; struct amdgpu_device *adev = dev->dev_private; @@ -200,10 +239,16 @@ int amdgpu_ctx_ioctl(struct drm_device *dev, void *data, r = 0; id = args->in.ctx_id; + priority = amdgpu_to_sched_priority(args->in.priority); + + /* For backwards compatibility reasons, we need to accept + * ioctls with garbage in the priority field */ + if (priority == AMD_SCHED_PRIORITY_INVALID) + priority = AMD_SCHED_PRIORITY_NORMAL; switch (args->in.op) { case AMDGPU_CTX_OP_ALLOC_CTX: - r = amdgpu_ctx_alloc(adev, fpriv, &id); + r = amdgpu_ctx_alloc(adev, fpriv, filp, priority, &id); args->out.alloc.ctx_id = id; break; case AMDGPU_CTX_OP_FREE_CTX: @@ -256,12 +301,8 @@ int amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, idx = seq & (amdgpu_sched_jobs - 1); other = cring->fences[idx]; - if (other) { - signed long r; - r = dma_fence_wait_timeout(other, true, MAX_SCHEDULE_TIMEOUT); - if (r < 0) - return r; - } + if (other) + BUG_ON(!dma_fence_is_signaled(other)); dma_fence_get(fence); @@ -305,6 +346,51 @@ struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, return fence; } +void amdgpu_ctx_priority_override(struct amdgpu_ctx *ctx, + enum amd_sched_priority priority) +{ + int i; + struct amdgpu_device *adev = ctx->adev; + struct amd_sched_rq *rq; + struct amd_sched_entity *entity; + struct amdgpu_ring *ring; + enum amd_sched_priority ctx_prio; + + ctx->override_priority = priority; + + ctx_prio = (ctx->override_priority == AMD_SCHED_PRIORITY_UNSET) ? + ctx->init_priority : ctx->override_priority; + + for (i = 0; i < adev->num_rings; i++) { + ring = adev->rings[i]; + entity = &ctx->rings[i].entity; + rq = &ring->sched.sched_rq[ctx_prio]; + + if (ring->funcs->type == AMDGPU_RING_TYPE_KIQ) + continue; + + amd_sched_entity_set_rq(entity, rq); + } +} + +int amdgpu_ctx_wait_prev_fence(struct amdgpu_ctx *ctx, unsigned ring_id) +{ + struct amdgpu_ctx_ring *cring = &ctx->rings[ring_id]; + unsigned idx = cring->sequence & (amdgpu_sched_jobs - 1); + struct dma_fence *other = cring->fences[idx]; + + if (other) { + signed long r; + r = dma_fence_wait_timeout(other, false, MAX_SCHEDULE_TIMEOUT); + if (r < 0) { + DRM_ERROR("Error (%ld) waiting for fence!\n", r); + return r; + } + } + + return 0; +} + void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr) { mutex_init(&mgr->lock); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 3e84ddf9e3b5..efcacb827de7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -56,6 +56,7 @@ #include "amdgpu_vf_error.h" #include "amdgpu_amdkfd.h" +#include "amdgpu_pm.h" MODULE_FIRMWARE("amdgpu/vega10_gpu_info.bin"); MODULE_FIRMWARE("amdgpu/raven_gpu_info.bin"); @@ -108,10 +109,8 @@ uint32_t amdgpu_mm_rreg(struct amdgpu_device *adev, uint32_t reg, { uint32_t ret; - if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) { - BUG_ON(in_interrupt()); + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) return amdgpu_virt_kiq_rreg(adev, reg); - } if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX)) ret = readl(((void __iomem *)adev->rmmio) + (reg * 4)); @@ -136,10 +135,8 @@ void amdgpu_mm_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v, adev->last_mm_index = v; } - if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) { - BUG_ON(in_interrupt()); + if (!(acc_flags & AMDGPU_REGS_NO_KIQ) && amdgpu_sriov_runtime(adev)) return amdgpu_virt_kiq_wreg(adev, reg, v); - } if ((reg * 4) < adev->rmmio_size && !(acc_flags & AMDGPU_REGS_IDX)) writel(v, ((void __iomem *)adev->rmmio) + (reg * 4)); @@ -549,7 +546,7 @@ int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb) if (offset < adev->wb.num_wb) { __set_bit(offset, adev->wb.used); - *wb = offset * 8; /* convert to dw offset */ + *wb = offset << 3; /* convert to dw offset */ return 0; } else { return -EINVAL; @@ -567,7 +564,7 @@ int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb) void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb) { if (wb < adev->wb.num_wb) - __clear_bit(wb, adev->wb.used); + __clear_bit(wb >> 3, adev->wb.used); } /** @@ -657,42 +654,96 @@ void amdgpu_gart_location(struct amdgpu_device *adev, struct amdgpu_mc *mc) } /* - * GPU helpers function. + * Firmware Reservation functions */ /** - * amdgpu_need_post - check if the hw need post or not + * amdgpu_fw_reserve_vram_fini - free fw reserved vram * * @adev: amdgpu_device pointer * - * Check if the asic has been initialized (all asics) at driver startup - * or post is needed if hw reset is performed. - * Returns true if need or false if not. + * free fw reserved vram if it has been reserved. */ -bool amdgpu_need_post(struct amdgpu_device *adev) +void amdgpu_fw_reserve_vram_fini(struct amdgpu_device *adev) { - uint32_t reg; + amdgpu_bo_free_kernel(&adev->fw_vram_usage.reserved_bo, + NULL, &adev->fw_vram_usage.va); +} - if (adev->has_hw_reset) { - adev->has_hw_reset = false; - return true; - } +/** + * amdgpu_fw_reserve_vram_init - create bo vram reservation from fw + * + * @adev: amdgpu_device pointer + * + * create bo vram reservation from fw. + */ +int amdgpu_fw_reserve_vram_init(struct amdgpu_device *adev) +{ + int r = 0; + u64 gpu_addr; + u64 vram_size = adev->mc.visible_vram_size; - /* bios scratch used on CIK+ */ - if (adev->asic_type >= CHIP_BONAIRE) - return amdgpu_atombios_scratch_need_asic_init(adev); + adev->fw_vram_usage.va = NULL; + adev->fw_vram_usage.reserved_bo = NULL; - /* check MEM_SIZE for older asics */ - reg = amdgpu_asic_get_config_memsize(adev); + if (adev->fw_vram_usage.size > 0 && + adev->fw_vram_usage.size <= vram_size) { - if ((reg != 0) && (reg != 0xffffffff)) - return false; + r = amdgpu_bo_create(adev, adev->fw_vram_usage.size, + PAGE_SIZE, true, 0, + AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED | + AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS, NULL, NULL, 0, + &adev->fw_vram_usage.reserved_bo); + if (r) + goto error_create; - return true; + r = amdgpu_bo_reserve(adev->fw_vram_usage.reserved_bo, false); + if (r) + goto error_reserve; + r = amdgpu_bo_pin_restricted(adev->fw_vram_usage.reserved_bo, + AMDGPU_GEM_DOMAIN_VRAM, + adev->fw_vram_usage.start_offset, + (adev->fw_vram_usage.start_offset + + adev->fw_vram_usage.size), &gpu_addr); + if (r) + goto error_pin; + r = amdgpu_bo_kmap(adev->fw_vram_usage.reserved_bo, + &adev->fw_vram_usage.va); + if (r) + goto error_kmap; + amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo); + } + return r; + +error_kmap: + amdgpu_bo_unpin(adev->fw_vram_usage.reserved_bo); +error_pin: + amdgpu_bo_unreserve(adev->fw_vram_usage.reserved_bo); +error_reserve: + amdgpu_bo_unref(&adev->fw_vram_usage.reserved_bo); +error_create: + adev->fw_vram_usage.va = NULL; + adev->fw_vram_usage.reserved_bo = NULL; + return r; } -static bool amdgpu_vpost_needed(struct amdgpu_device *adev) + +/* + * GPU helpers function. + */ +/** + * amdgpu_need_post - check if the hw need post or not + * + * @adev: amdgpu_device pointer + * + * Check if the asic has been initialized (all asics) at driver startup + * or post is needed if hw reset is performed. + * Returns true if need or false if not. + */ +bool amdgpu_need_post(struct amdgpu_device *adev) { + uint32_t reg; + if (amdgpu_sriov_vf(adev)) return false; @@ -715,7 +766,23 @@ static bool amdgpu_vpost_needed(struct amdgpu_device *adev) return true; } } - return amdgpu_need_post(adev); + + if (adev->has_hw_reset) { + adev->has_hw_reset = false; + return true; + } + + /* bios scratch used on CIK+ */ + if (adev->asic_type >= CHIP_BONAIRE) + return amdgpu_atombios_scratch_need_asic_init(adev); + + /* check MEM_SIZE for older asics */ + reg = amdgpu_asic_get_config_memsize(adev); + + if ((reg != 0) && (reg != 0xffffffff)) + return false; + + return true; } /** @@ -1879,6 +1946,7 @@ static int amdgpu_sriov_reinit_late(struct amdgpu_device *adev) static enum amd_ip_block_type ip_order[] = { AMD_IP_BLOCK_TYPE_SMC, + AMD_IP_BLOCK_TYPE_PSP, AMD_IP_BLOCK_TYPE_DCE, AMD_IP_BLOCK_TYPE_GFX, AMD_IP_BLOCK_TYPE_SDMA, @@ -1964,12 +2032,17 @@ static int amdgpu_resume(struct amdgpu_device *adev) static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev) { - if (adev->is_atom_fw) { - if (amdgpu_atomfirmware_gpu_supports_virtualization(adev)) - adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS; - } else { - if (amdgpu_atombios_has_gpu_virtualization_table(adev)) - adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS; + if (amdgpu_sriov_vf(adev)) { + if (adev->is_atom_fw) { + if (amdgpu_atomfirmware_gpu_supports_virtualization(adev)) + adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS; + } else { + if (amdgpu_atombios_has_gpu_virtualization_table(adev)) + adev->virt.caps |= AMDGPU_SRIOV_CAPS_SRIOV_VBIOS; + } + + if (!(adev->virt.caps & AMDGPU_SRIOV_CAPS_SRIOV_VBIOS)) + amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_NO_VBIOS, 0, 0); } } @@ -2010,6 +2083,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, adev->vm_manager.vm_pte_num_rings = 0; adev->gart.gart_funcs = NULL; adev->fence_context = dma_fence_context_alloc(AMDGPU_MAX_RINGS); + bitmap_zero(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES); adev->smc_rreg = &amdgpu_invalid_rreg; adev->smc_wreg = &amdgpu_invalid_wreg; @@ -2038,8 +2112,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, mutex_init(&adev->pm.mutex); mutex_init(&adev->gfx.gpu_clock_mutex); mutex_init(&adev->srbm_mutex); + mutex_init(&adev->gfx.pipe_reserve_mutex); mutex_init(&adev->grbm_idx_mutex); mutex_init(&adev->mn_lock); + mutex_init(&adev->virt.vf_errors.lock); hash_init(adev->mn_hash); amdgpu_check_arguments(adev); @@ -2125,7 +2201,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_atombios_init(adev); if (r) { dev_err(adev->dev, "amdgpu_atombios_init failed\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0); + amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_INIT_FAIL, 0, 0); goto failed; } @@ -2133,10 +2209,9 @@ int amdgpu_device_init(struct amdgpu_device *adev, amdgpu_device_detect_sriov_bios(adev); /* Post card if necessary */ - if (amdgpu_vpost_needed(adev)) { + if (amdgpu_need_post(adev)) { if (!adev->bios) { dev_err(adev->dev, "no vBIOS found\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_NO_VBIOS, 0, 0); r = -EINVAL; goto failed; } @@ -2144,7 +2219,6 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_atom_asic_init(adev->mode_info.atom_context); if (r) { dev_err(adev->dev, "gpu post error!\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_GPU_POST_ERROR, 0, 0); goto failed; } } else { @@ -2156,7 +2230,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_atomfirmware_get_clock_info(adev); if (r) { dev_err(adev->dev, "amdgpu_atomfirmware_get_clock_info failed\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0); + amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0); goto failed; } } else { @@ -2164,7 +2238,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_atombios_get_clock_info(adev); if (r) { dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0); + amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_ATOMBIOS_GET_CLOCK_FAIL, 0, 0); goto failed; } /* init i2c buses */ @@ -2175,7 +2249,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_fence_driver_init(adev); if (r) { dev_err(adev->dev, "amdgpu_fence_driver_init failed\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0); + amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_FENCE_INIT_FAIL, 0, 0); goto failed; } @@ -2185,7 +2259,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_init(adev); if (r) { dev_err(adev->dev, "amdgpu_init failed\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, 0, 0); + amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_INIT_FAIL, 0, 0); amdgpu_fini(adev); goto failed; } @@ -2205,7 +2279,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_ib_pool_init(adev); if (r) { dev_err(adev->dev, "IB initialization failed (%d).\n", r); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_IB_INIT_FAIL, 0, r); + amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_IB_INIT_FAIL, 0, r); goto failed; } @@ -2213,8 +2287,15 @@ int amdgpu_device_init(struct amdgpu_device *adev, if (r) DRM_ERROR("ib ring test failed (%d).\n", r); + if (amdgpu_sriov_vf(adev)) + amdgpu_virt_init_data_exchange(adev); + amdgpu_fbdev_init(adev); + r = amdgpu_pm_sysfs_init(adev); + if (r) + DRM_ERROR("registering pm debugfs failed (%d).\n", r); + r = amdgpu_gem_debugfs_init(adev); if (r) DRM_ERROR("registering gem debugfs failed (%d).\n", r); @@ -2254,7 +2335,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, r = amdgpu_late_init(adev); if (r) { dev_err(adev->dev, "amdgpu_late_init failed\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_AMDGPU_LATE_INIT_FAIL, 0, r); + amdgpu_vf_error_put(adev, AMDGIM_ERROR_VF_AMDGPU_LATE_INIT_FAIL, 0, r); goto failed; } @@ -2286,6 +2367,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) /* evict vram memory */ amdgpu_bo_evict_vram(adev); amdgpu_ib_pool_fini(adev); + amdgpu_fw_reserve_vram_fini(adev); amdgpu_fence_driver_fini(adev); amdgpu_fbdev_fini(adev); r = amdgpu_fini(adev); @@ -2311,6 +2393,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) iounmap(adev->rmmio); adev->rmmio = NULL; amdgpu_doorbell_fini(adev); + amdgpu_pm_sysfs_fini(adev); amdgpu_debugfs_regs_cleanup(adev); } @@ -2537,6 +2620,9 @@ static bool amdgpu_check_soft_reset(struct amdgpu_device *adev) int i; bool asic_hang = false; + if (amdgpu_sriov_vf(adev)) + return true; + for (i = 0; i < adev->num_ip_blocks; i++) { if (!adev->ip_blocks[i].status.valid) continue; @@ -2936,7 +3022,6 @@ out: } } else { dev_err(adev->dev, "asic resume failed (%d).\n", r); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_ASIC_RESUME_FAIL, 0, r); for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { if (adev->rings[i] && adev->rings[i]->sched.thread) { kthread_unpark(adev->rings[i]->sched.thread); @@ -2950,7 +3035,6 @@ out: if (r) { /* bad news, how to tell it to userspace ? */ dev_info(adev->dev, "GPU reset failed\n"); - amdgpu_vf_error_put(AMDGIM_ERROR_VF_GPU_RESET_FAIL, 0, r); } else { dev_info(adev->dev, "GPU reset successed!\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h index f79f9ea58b17..7279fb5c3abc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h @@ -356,6 +356,10 @@ enum amdgpu_pcie_gen { ((adev)->powerplay.pp_funcs->switch_power_profile(\ (adev)->powerplay.pp_handle, type)) +#define amdgpu_dpm_set_clockgating_by_smu(adev, msg_id) \ + ((adev)->powerplay.pp_funcs->set_clockgating_by_smu(\ + (adev)->powerplay.pp_handle, msg_id)) + struct amdgpu_dpm { struct amdgpu_ps *ps; /* number of valid power states */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 4f98960e47f9..dd2f060d62a8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -70,9 +70,12 @@ * - 3.18.0 - Export gpu always on cu bitmap * - 3.19.0 - Add support for UVD MJPEG decode * - 3.20.0 - Add support for local BOs + * - 3.21.0 - Add DRM_AMDGPU_FENCE_TO_HANDLE ioctl + * - 3.22.0 - Add DRM_AMDGPU_SCHED ioctl + * - 3.23.0 - Add query for VRAM lost counter */ #define KMS_DRIVER_MAJOR 3 -#define KMS_DRIVER_MINOR 20 +#define KMS_DRIVER_MINOR 23 #define KMS_DRIVER_PATCHLEVEL 0 int amdgpu_vram_limit = 0; @@ -122,6 +125,7 @@ int amdgpu_cntl_sb_buf_per_se = 0; int amdgpu_param_buf_per_se = 0; int amdgpu_job_hang_limit = 0; int amdgpu_lbpw = -1; +int amdgpu_compute_multipipe = -1; MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); @@ -265,6 +269,9 @@ module_param_named(job_hang_limit, amdgpu_job_hang_limit, int ,0444); MODULE_PARM_DESC(lbpw, "Load Balancing Per Watt (LBPW) support (1 = enable, 0 = disable, -1 = auto)"); module_param_named(lbpw, amdgpu_lbpw, int, 0444); +MODULE_PARM_DESC(compute_multipipe, "Force compute queues to be spread across pipes (1 = enable, 0 = disable, -1 = auto)"); +module_param_named(compute_multipipe, amdgpu_compute_multipipe, int, 0444); + #ifdef CONFIG_DRM_AMDGPU_SI #if defined(CONFIG_DRM_RADEON) || defined(CONFIG_DRM_RADEON_MODULE) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c index 333bad749067..fb9f88ef6059 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c @@ -169,6 +169,32 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f) } /** + * amdgpu_fence_emit_polling - emit a fence on the requeste ring + * + * @ring: ring the fence is associated with + * @s: resulting sequence number + * + * Emits a fence command on the requested ring (all asics). + * Used For polling fence. + * Returns 0 on success, -ENOMEM on failure. + */ +int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s) +{ + uint32_t seq; + + if (!s) + return -EINVAL; + + seq = ++ring->fence_drv.sync_seq; + amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr, + seq, AMDGPU_FENCE_FLAG_INT); + + *s = seq; + + return 0; +} + +/** * amdgpu_fence_schedule_fallback - schedule fallback check * * @ring: pointer to struct amdgpu_ring @@ -282,6 +308,30 @@ int amdgpu_fence_wait_empty(struct amdgpu_ring *ring) } /** + * amdgpu_fence_wait_polling - busy wait for givn sequence number + * + * @ring: ring index the fence is associated with + * @wait_seq: sequence number to wait + * @timeout: the timeout for waiting in usecs + * + * Wait for all fences on the requested ring to signal (all asics). + * Returns left time if no timeout, 0 or minus if timeout. + */ +signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring, + uint32_t wait_seq, + signed long timeout) +{ + uint32_t seq; + + do { + seq = amdgpu_fence_read(ring); + udelay(5); + timeout -= 5; + } while ((int32_t)(wait_seq - seq) > 0 && timeout > 0); + + return timeout > 0 ? timeout : 0; +} +/** * amdgpu_fence_count_emitted - get the count of emitted fences * * @ring: ring the fence is associated with @@ -641,6 +691,19 @@ static int amdgpu_debugfs_fence_info(struct seq_file *m, void *data) atomic_read(&ring->fence_drv.last_seq)); seq_printf(m, "Last emitted 0x%08x\n", ring->fence_drv.sync_seq); + + if (ring->funcs->type != AMDGPU_RING_TYPE_GFX) + continue; + + /* set in CP_VMID_PREEMPT and preemption occurred */ + seq_printf(m, "Last preempted 0x%08x\n", + le32_to_cpu(*(ring->fence_drv.cpu_addr + 2))); + /* set in CP_VMID_RESET and reset occurred */ + seq_printf(m, "Last reset 0x%08x\n", + le32_to_cpu(*(ring->fence_drv.cpu_addr + 4))); + /* Both preemption and reset occurred */ + seq_printf(m, "Last both 0x%08x\n", + le32_to_cpu(*(ring->fence_drv.cpu_addr + 6))); } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index f4370081f6e6..fe818501c520 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -332,12 +332,13 @@ int amdgpu_gart_bind(struct amdgpu_device *adev, uint64_t offset, adev->gart.pages[p] = pagelist[i]; #endif - if (adev->gart.ptr) { - r = amdgpu_gart_map(adev, offset, pages, dma_addr, flags, - adev->gart.ptr); - if (r) - return r; - } + if (!adev->gart.ptr) + return 0; + + r = amdgpu_gart_map(adev, offset, pages, dma_addr, flags, + adev->gart.ptr); + if (r) + return r; mb(); amdgpu_gart_flush_gpu_tlb(adev, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index b0d45c8e6bb3..fb72edc4c026 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -212,7 +212,9 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, AMDGPU_GEM_CREATE_NO_CPU_ACCESS | AMDGPU_GEM_CREATE_CPU_GTT_USWC | AMDGPU_GEM_CREATE_VRAM_CLEARED | - AMDGPU_GEM_CREATE_VM_ALWAYS_VALID)) + AMDGPU_GEM_CREATE_VM_ALWAYS_VALID | + AMDGPU_GEM_CREATE_EXPLICIT_SYNC)) + return -EINVAL; /* reject invalid gem domains */ @@ -577,11 +579,6 @@ int amdgpu_gem_va_ioctl(struct drm_device *dev, void *data, args->operation); return -EINVAL; } - if ((args->operation == AMDGPU_VA_OP_MAP) || - (args->operation == AMDGPU_VA_OP_REPLACE)) { - if (amdgpu_kms_vram_lost(adev, fpriv)) - return -ENODEV; - } INIT_LIST_HEAD(&list); INIT_LIST_HEAD(&duplicates); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 4fcd98e65998..ef043361009f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -109,9 +109,26 @@ void amdgpu_gfx_parse_disable_cu(unsigned *mask, unsigned max_se, unsigned max_s } } +static bool amdgpu_gfx_is_multipipe_capable(struct amdgpu_device *adev) +{ + if (amdgpu_compute_multipipe != -1) { + DRM_INFO("amdgpu: forcing compute pipe policy %d\n", + amdgpu_compute_multipipe); + return amdgpu_compute_multipipe == 1; + } + + /* FIXME: spreading the queues across pipes causes perf regressions + * on POLARIS11 compute workloads */ + if (adev->asic_type == CHIP_POLARIS11) + return false; + + return adev->gfx.mec.num_mec > 1; +} + void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev) { int i, queue, pipe, mec; + bool multipipe_policy = amdgpu_gfx_is_multipipe_capable(adev); /* policy for amdgpu compute queue ownership */ for (i = 0; i < AMDGPU_MAX_COMPUTE_QUEUES; ++i) { @@ -125,8 +142,7 @@ void amdgpu_gfx_compute_queue_acquire(struct amdgpu_device *adev) if (mec >= adev->gfx.mec.num_mec) break; - /* FIXME: spreading the queues across pipes causes perf regressions */ - if (0) { + if (multipipe_policy) { /* policy: amdgpu owns the first two queues of the first MEC */ if (mec == 0 && queue < 2) set_bit(i, adev->gfx.mec.queue_bitmap); @@ -185,7 +201,7 @@ int amdgpu_gfx_kiq_init_ring(struct amdgpu_device *adev, struct amdgpu_kiq *kiq = &adev->gfx.kiq; int r = 0; - mutex_init(&kiq->ring_mutex); + spin_lock_init(&kiq->ring_lock); r = amdgpu_wb_get(adev, &adev->virt.reg_val_offs); if (r) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 0d15eb7d31d7..33535d347734 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -169,7 +169,8 @@ static int amdgpu_gtt_mgr_new(struct ttm_mem_type_manager *man, int r; spin_lock(&mgr->lock); - if (atomic64_read(&mgr->available) < mem->num_pages) { + if ((&tbo->mem == mem || tbo->mem.mem_type != TTM_PL_TT) && + atomic64_read(&mgr->available) < mem->num_pages) { spin_unlock(&mgr->lock); return 0; } @@ -244,8 +245,9 @@ static void amdgpu_gtt_mgr_del(struct ttm_mem_type_manager *man, uint64_t amdgpu_gtt_mgr_usage(struct ttm_mem_type_manager *man) { struct amdgpu_gtt_mgr *mgr = man->priv; + s64 result = man->size - atomic64_read(&mgr->available); - return (u64)(man->size - atomic64_read(&mgr->available)) * PAGE_SIZE; + return (result > 0 ? result : 0) * PAGE_SIZE; } /** @@ -265,7 +267,7 @@ static void amdgpu_gtt_mgr_debug(struct ttm_mem_type_manager *man, drm_mm_print(&mgr->mm, printer); spin_unlock(&mgr->lock); - drm_printf(printer, "man size:%llu pages, gtt available:%llu pages, usage:%lluMB\n", + drm_printf(printer, "man size:%llu pages, gtt available:%lld pages, usage:%lluMB\n", man->size, (u64)atomic64_read(&mgr->available), amdgpu_gtt_mgr_usage(man) >> 20); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c index 4510627ae83e..0cfc68db575b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c @@ -65,6 +65,7 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs, amdgpu_sync_create(&(*job)->sync); amdgpu_sync_create(&(*job)->dep_sync); amdgpu_sync_create(&(*job)->sched_sync); + (*job)->vram_lost_counter = atomic_read(&adev->vram_lost_counter); return 0; } @@ -103,6 +104,7 @@ static void amdgpu_job_free_cb(struct amd_sched_job *s_job) { struct amdgpu_job *job = container_of(s_job, struct amdgpu_job, base); + amdgpu_ring_priority_put(job->ring, amd_sched_get_job_priority(s_job)); dma_fence_put(job->fence); amdgpu_sync_free(&job->sync); amdgpu_sync_free(&job->dep_sync); @@ -139,6 +141,8 @@ int amdgpu_job_submit(struct amdgpu_job *job, struct amdgpu_ring *ring, job->fence_ctx = entity->fence_context; *f = dma_fence_get(&job->base.s_fence->finished); amdgpu_job_free_resources(job); + amdgpu_ring_priority_get(job->ring, + amd_sched_get_job_priority(&job->base)); amd_sched_entity_push_job(&job->base); return 0; @@ -177,8 +181,8 @@ static struct dma_fence *amdgpu_job_dependency(struct amd_sched_job *sched_job) static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job) { struct dma_fence *fence = NULL; + struct amdgpu_device *adev; struct amdgpu_job *job; - struct amdgpu_fpriv *fpriv = NULL; int r; if (!sched_job) { @@ -186,23 +190,25 @@ static struct dma_fence *amdgpu_job_run(struct amd_sched_job *sched_job) return NULL; } job = to_amdgpu_job(sched_job); + adev = job->adev; BUG_ON(amdgpu_sync_peek_fence(&job->sync, NULL)); trace_amdgpu_sched_run_job(job); - if (job->vm) - fpriv = container_of(job->vm, struct amdgpu_fpriv, vm); /* skip ib schedule when vram is lost */ - if (fpriv && amdgpu_kms_vram_lost(job->adev, fpriv)) + if (job->vram_lost_counter != atomic_read(&adev->vram_lost_counter)) { + dma_fence_set_error(&job->base.s_fence->finished, -ECANCELED); DRM_ERROR("Skip scheduling IBs!\n"); - else { - r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs, job, &fence); + } else { + r = amdgpu_ib_schedule(job->ring, job->num_ibs, job->ibs, job, + &fence); if (r) DRM_ERROR("Error scheduling IBs (%d)\n", r); } /* if gpu reset, hw fence will be replaced here */ dma_fence_put(job->fence); job->fence = dma_fence_get(fence); + amdgpu_job_free_resources(job); return fence; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 4fd06f8d9768..6f0b26dae3b0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -28,6 +28,7 @@ #include <drm/drmP.h> #include "amdgpu.h" #include <drm/amdgpu_drm.h> +#include "amdgpu_sched.h" #include "amdgpu_uvd.h" #include "amdgpu_vce.h" @@ -269,7 +270,6 @@ static int amdgpu_firmware_info(struct drm_amdgpu_info_firmware *fw_info, static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) { struct amdgpu_device *adev = dev->dev_private; - struct amdgpu_fpriv *fpriv = filp->driver_priv; struct drm_amdgpu_info *info = data; struct amdgpu_mode_info *minfo = &adev->mode_info; void __user *out = (void __user *)(uintptr_t)info->return_pointer; @@ -282,8 +282,6 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file if (!info->return_size || !info->return_pointer) return -EINVAL; - if (amdgpu_kms_vram_lost(adev, fpriv)) - return -ENODEV; switch (info->query) { case AMDGPU_INFO_ACCEL_WORKING: @@ -765,6 +763,9 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file } return copy_to_user(out, &ui32, min(size, 4u)) ? -EFAULT : 0; } + case AMDGPU_INFO_VRAM_LOST_COUNTER: + ui32 = atomic_read(&adev->vram_lost_counter); + return copy_to_user(out, &ui32, min(size, 4u)) ? -EFAULT : 0; default: DRM_DEBUG_KMS("Invalid request %d\n", info->query); return -EINVAL; @@ -791,12 +792,6 @@ void amdgpu_driver_lastclose_kms(struct drm_device *dev) vga_switcheroo_process_delayed_switch(); } -bool amdgpu_kms_vram_lost(struct amdgpu_device *adev, - struct amdgpu_fpriv *fpriv) -{ - return fpriv->vram_lost_counter != atomic_read(&adev->vram_lost_counter); -} - /** * amdgpu_driver_open_kms - drm callback for open * @@ -853,7 +848,6 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) amdgpu_ctx_mgr_init(&fpriv->ctx_mgr); - fpriv->vram_lost_counter = atomic_read(&adev->vram_lost_counter); file_priv->driver_priv = fpriv; out_suspend: @@ -1023,7 +1017,9 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_VM, amdgpu_vm_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(AMDGPU_SCHED, amdgpu_sched_ioctl, DRM_MASTER), DRM_IOCTL_DEF_DRV(AMDGPU_BO_LIST, amdgpu_bo_list_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(AMDGPU_FENCE_TO_HANDLE, amdgpu_cs_fence_to_handle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), /* KMS */ DRM_IOCTL_DEF_DRV(AMDGPU_GEM_MMAP, amdgpu_gem_mmap_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(AMDGPU_GEM_WAIT_IDLE, amdgpu_gem_wait_idle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 6982baeccd14..ea25164e7f4b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -40,9 +40,7 @@ static void amdgpu_ttm_bo_destroy(struct ttm_buffer_object *tbo) { struct amdgpu_device *adev = amdgpu_ttm_adev(tbo->bdev); - struct amdgpu_bo *bo; - - bo = container_of(tbo, struct amdgpu_bo, tbo); + struct amdgpu_bo *bo = ttm_to_amdgpu_bo(tbo); amdgpu_bo_kunmap(bo); @@ -371,6 +369,9 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, type, &bo->placement, page_align, !kernel, NULL, acc_size, sg, resv, &amdgpu_ttm_bo_destroy); + if (unlikely(r != 0)) + return r; + bytes_moved = atomic64_read(&adev->num_bytes_moved) - initial_bytes_moved; if (adev->mc.visible_vram_size < adev->mc.real_vram_size && @@ -380,9 +381,6 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, else amdgpu_cs_report_moved_bytes(adev, bytes_moved, 0); - if (unlikely(r != 0)) - return r; - if (kernel) bo->tbo.priority = 1; @@ -884,7 +882,7 @@ void amdgpu_bo_move_notify(struct ttm_buffer_object *bo, if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return; - abo = container_of(bo, struct amdgpu_bo, tbo); + abo = ttm_to_amdgpu_bo(bo); amdgpu_vm_bo_invalidate(adev, abo, evict); amdgpu_bo_kunmap(abo); @@ -911,7 +909,7 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) if (!amdgpu_ttm_bo_is_amdgpu_bo(bo)) return 0; - abo = container_of(bo, struct amdgpu_bo, tbo); + abo = ttm_to_amdgpu_bo(bo); /* Remember that this BO was accessed by the CPU */ abo->flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index 39b6bf6fb051..428aae048f4b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -94,6 +94,11 @@ struct amdgpu_bo { }; }; +static inline struct amdgpu_bo *ttm_to_amdgpu_bo(struct ttm_buffer_object *tbo) +{ + return container_of(tbo, struct amdgpu_bo, tbo); +} + /** * amdgpu_mem_type_to_domain - return domain corresponding to mem_type * @mem_type: ttm memory type @@ -188,6 +193,14 @@ static inline bool amdgpu_bo_gpu_accessible(struct amdgpu_bo *bo) } } +/** + * amdgpu_bo_explicit_sync - return whether the bo is explicitly synced + */ +static inline bool amdgpu_bo_explicit_sync(struct amdgpu_bo *bo) +{ + return bo->flags & AMDGPU_GEM_CREATE_EXPLICIT_SYNC; +} + int amdgpu_bo_create(struct amdgpu_device *adev, unsigned long size, int byte_align, bool kernel, u32 domain, u64 flags, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index f6ce52956e6d..a59e04f3eeba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -64,10 +64,6 @@ static const struct cg_flag_name clocks[] = { void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) { - if (adev->pp_enabled) - /* TODO */ - return; - if (adev->pm.dpm_enabled) { mutex_lock(&adev->pm.mutex); if (power_supply_is_system_supplied() > 0) @@ -118,7 +114,7 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev, goto fail; } - if (adev->pp_enabled) { + if (adev->powerplay.pp_funcs->dispatch_tasks) { amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_ENABLE_USER_STATE, &state, NULL); } else { mutex_lock(&adev->pm.mutex); @@ -303,7 +299,8 @@ static ssize_t amdgpu_set_pp_force_state(struct device *dev, if (strlen(buf) == 1) adev->pp_force_state_enabled = false; - else if (adev->pp_enabled) { + else if (adev->powerplay.pp_funcs->dispatch_tasks && + adev->powerplay.pp_funcs->get_pp_num_states) { struct pp_states_info data; ret = kstrtoul(buf, 0, &idx); @@ -531,7 +528,7 @@ static ssize_t amdgpu_set_pp_sclk_od(struct device *dev, if (adev->powerplay.pp_funcs->set_sclk_od) amdgpu_dpm_set_sclk_od(adev, (uint32_t)value); - if (adev->pp_enabled) { + if (adev->powerplay.pp_funcs->dispatch_tasks) { amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL); } else { adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; @@ -575,7 +572,7 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev, if (adev->powerplay.pp_funcs->set_mclk_od) amdgpu_dpm_set_mclk_od(adev, (uint32_t)value); - if (adev->pp_enabled) { + if (adev->powerplay.pp_funcs->dispatch_tasks) { amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_READJUST_POWER_STATE, NULL, NULL); } else { adev->pm.dpm.current_ps = adev->pm.dpm.boot_ps; @@ -959,9 +956,6 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) return 0; - if (adev->pp_enabled) - return effective_mode; - /* Skip fan attributes if fan is not present */ if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || @@ -1317,6 +1311,9 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) if (adev->pm.sysfs_initialized) return 0; + if (adev->pm.dpm_enabled == 0) + return 0; + if (adev->powerplay.pp_funcs->get_temperature == NULL) return 0; @@ -1341,27 +1338,26 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) return ret; } - if (adev->pp_enabled) { - ret = device_create_file(adev->dev, &dev_attr_pp_num_states); - if (ret) { - DRM_ERROR("failed to create device file pp_num_states\n"); - return ret; - } - ret = device_create_file(adev->dev, &dev_attr_pp_cur_state); - if (ret) { - DRM_ERROR("failed to create device file pp_cur_state\n"); - return ret; - } - ret = device_create_file(adev->dev, &dev_attr_pp_force_state); - if (ret) { - DRM_ERROR("failed to create device file pp_force_state\n"); - return ret; - } - ret = device_create_file(adev->dev, &dev_attr_pp_table); - if (ret) { - DRM_ERROR("failed to create device file pp_table\n"); - return ret; - } + + ret = device_create_file(adev->dev, &dev_attr_pp_num_states); + if (ret) { + DRM_ERROR("failed to create device file pp_num_states\n"); + return ret; + } + ret = device_create_file(adev->dev, &dev_attr_pp_cur_state); + if (ret) { + DRM_ERROR("failed to create device file pp_cur_state\n"); + return ret; + } + ret = device_create_file(adev->dev, &dev_attr_pp_force_state); + if (ret) { + DRM_ERROR("failed to create device file pp_force_state\n"); + return ret; + } + ret = device_create_file(adev->dev, &dev_attr_pp_table); + if (ret) { + DRM_ERROR("failed to create device file pp_table\n"); + return ret; } ret = device_create_file(adev->dev, &dev_attr_pp_dpm_sclk); @@ -1417,16 +1413,19 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev) { + if (adev->pm.dpm_enabled == 0) + return; + if (adev->pm.int_hwmon_dev) hwmon_device_unregister(adev->pm.int_hwmon_dev); device_remove_file(adev->dev, &dev_attr_power_dpm_state); device_remove_file(adev->dev, &dev_attr_power_dpm_force_performance_level); - if (adev->pp_enabled) { - device_remove_file(adev->dev, &dev_attr_pp_num_states); - device_remove_file(adev->dev, &dev_attr_pp_cur_state); - device_remove_file(adev->dev, &dev_attr_pp_force_state); - device_remove_file(adev->dev, &dev_attr_pp_table); - } + + device_remove_file(adev->dev, &dev_attr_pp_num_states); + device_remove_file(adev->dev, &dev_attr_pp_cur_state); + device_remove_file(adev->dev, &dev_attr_pp_force_state); + device_remove_file(adev->dev, &dev_attr_pp_table); + device_remove_file(adev->dev, &dev_attr_pp_dpm_sclk); device_remove_file(adev->dev, &dev_attr_pp_dpm_mclk); device_remove_file(adev->dev, &dev_attr_pp_dpm_pcie); @@ -1457,7 +1456,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) amdgpu_fence_wait_empty(ring); } - if (adev->pp_enabled) { + if (adev->powerplay.pp_funcs->dispatch_tasks) { amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_DISPLAY_CONFIG_CHANGE, NULL, NULL); } else { mutex_lock(&adev->pm.mutex); @@ -1592,15 +1591,15 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) if ((adev->flags & AMD_IS_PX) && (ddev->switch_power_state != DRM_SWITCH_POWER_ON)) { seq_printf(m, "PX asic powered off\n"); - } else if (adev->pp_enabled) { - return amdgpu_debugfs_pm_info_pp(m, adev); - } else { + } else if (adev->powerplay.pp_funcs->debugfs_print_current_performance_level) { mutex_lock(&adev->pm.mutex); if (adev->powerplay.pp_funcs->debugfs_print_current_performance_level) adev->powerplay.pp_funcs->debugfs_print_current_performance_level(adev, m); else seq_printf(m, "Debugfs support not implemented for this asic\n"); mutex_unlock(&adev->pm.mutex); + } else { + return amdgpu_debugfs_pm_info_pp(m, adev); } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c index 2d2f0960b025..5f5aa5fddc16 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -34,24 +34,6 @@ #include "cik_dpm.h" #include "vi_dpm.h" -static int amdgpu_create_pp_handle(struct amdgpu_device *adev) -{ - struct amd_pp_init pp_init; - struct amd_powerplay *amd_pp; - int ret; - - amd_pp = &(adev->powerplay); - pp_init.chip_family = adev->family; - pp_init.chip_id = adev->asic_type; - pp_init.pm_en = (amdgpu_dpm != 0 && !amdgpu_sriov_vf(adev)) ? true : false; - pp_init.feature_mask = amdgpu_pp_feature_mask; - pp_init.device = amdgpu_cgs_create_device(adev); - ret = amd_powerplay_create(&pp_init, &(amd_pp->pp_handle)); - if (ret) - return -EINVAL; - return 0; -} - static int amdgpu_pp_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -59,7 +41,6 @@ static int amdgpu_pp_early_init(void *handle) int ret = 0; amd_pp = &(adev->powerplay); - adev->pp_enabled = false; amd_pp->pp_handle = (void *)adev; switch (adev->asic_type) { @@ -73,9 +54,7 @@ static int amdgpu_pp_early_init(void *handle) case CHIP_STONEY: case CHIP_VEGA10: case CHIP_RAVEN: - adev->pp_enabled = true; - if (amdgpu_create_pp_handle(adev)) - return -EINVAL; + amd_pp->cgs_device = amdgpu_cgs_create_device(adev); amd_pp->ip_funcs = &pp_ip_funcs; amd_pp->pp_funcs = &pp_dpm_funcs; break; @@ -97,9 +76,7 @@ static int amdgpu_pp_early_init(void *handle) amd_pp->ip_funcs = &ci_dpm_ip_funcs; amd_pp->pp_funcs = &ci_dpm_funcs; } else { - adev->pp_enabled = true; - if (amdgpu_create_pp_handle(adev)) - return -EINVAL; + amd_pp->cgs_device = amdgpu_cgs_create_device(adev); amd_pp->ip_funcs = &pp_ip_funcs; amd_pp->pp_funcs = &pp_dpm_funcs; } @@ -118,12 +95,9 @@ static int amdgpu_pp_early_init(void *handle) if (adev->powerplay.ip_funcs->early_init) ret = adev->powerplay.ip_funcs->early_init( - adev->powerplay.pp_handle); + amd_pp->cgs_device ? amd_pp->cgs_device : + amd_pp->pp_handle); - if (ret == PP_DPM_DISABLED) { - adev->pm.dpm_enabled = false; - return 0; - } return ret; } @@ -137,11 +111,6 @@ static int amdgpu_pp_late_init(void *handle) ret = adev->powerplay.ip_funcs->late_init( adev->powerplay.pp_handle); - if (adev->pp_enabled && adev->pm.dpm_enabled) { - amdgpu_pm_sysfs_init(adev); - amdgpu_dpm_dispatch_task(adev, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL); - } - return ret; } @@ -176,21 +145,13 @@ static int amdgpu_pp_hw_init(void *handle) int ret = 0; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->pp_enabled && adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) + if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) amdgpu_ucode_init_bo(adev); if (adev->powerplay.ip_funcs->hw_init) ret = adev->powerplay.ip_funcs->hw_init( adev->powerplay.pp_handle); - if (ret == PP_DPM_DISABLED) { - adev->pm.dpm_enabled = false; - return 0; - } - - if ((amdgpu_dpm != 0) && !amdgpu_sriov_vf(adev)) - adev->pm.dpm_enabled = true; - return ret; } @@ -199,14 +160,11 @@ static int amdgpu_pp_hw_fini(void *handle) int ret = 0; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - if (adev->pp_enabled && adev->pm.dpm_enabled) - amdgpu_pm_sysfs_fini(adev); - if (adev->powerplay.ip_funcs->hw_fini) ret = adev->powerplay.ip_funcs->hw_fini( adev->powerplay.pp_handle); - if (adev->pp_enabled && adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) + if (adev->firmware.load_type == AMDGPU_FW_LOAD_SMU) amdgpu_ucode_fini_bo(adev); return ret; @@ -220,9 +178,8 @@ static void amdgpu_pp_late_fini(void *handle) adev->powerplay.ip_funcs->late_fini( adev->powerplay.pp_handle); - - if (adev->pp_enabled) - amd_powerplay_destroy(adev->powerplay.pp_handle); + if (adev->powerplay.cgs_device) + amdgpu_cgs_destroy_device(adev->powerplay.cgs_device); } static int amdgpu_pp_suspend(void *handle) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c index befc09b68543..190e28cb827e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_queue_mgr.c @@ -121,7 +121,7 @@ static enum amdgpu_ring_type amdgpu_hw_ip_to_ring_type(int hw_ip) static int amdgpu_lru_map(struct amdgpu_device *adev, struct amdgpu_queue_mapper *mapper, - int user_ring, + int user_ring, bool lru_pipe_order, struct amdgpu_ring **out_ring) { int r, i, j; @@ -139,7 +139,7 @@ static int amdgpu_lru_map(struct amdgpu_device *adev, } r = amdgpu_ring_lru_get(adev, ring_type, ring_blacklist, - j, out_ring); + j, lru_pipe_order, out_ring); if (r) return r; @@ -284,8 +284,10 @@ int amdgpu_queue_mgr_map(struct amdgpu_device *adev, r = amdgpu_identity_map(adev, mapper, ring, out_ring); break; case AMDGPU_HW_IP_DMA: + r = amdgpu_lru_map(adev, mapper, ring, false, out_ring); + break; case AMDGPU_HW_IP_COMPUTE: - r = amdgpu_lru_map(adev, mapper, ring, out_ring); + r = amdgpu_lru_map(adev, mapper, ring, true, out_ring); break; default: *out_ring = NULL; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c index 5ce65280b396..a98fbbb4739f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c @@ -136,7 +136,8 @@ void amdgpu_ring_commit(struct amdgpu_ring *ring) if (ring->funcs->end_use) ring->funcs->end_use(ring); - amdgpu_ring_lru_touch(ring->adev, ring); + if (ring->funcs->type != AMDGPU_RING_TYPE_KIQ) + amdgpu_ring_lru_touch(ring->adev, ring); } /** @@ -155,6 +156,75 @@ void amdgpu_ring_undo(struct amdgpu_ring *ring) } /** + * amdgpu_ring_priority_put - restore a ring's priority + * + * @ring: amdgpu_ring structure holding the information + * @priority: target priority + * + * Release a request for executing at @priority + */ +void amdgpu_ring_priority_put(struct amdgpu_ring *ring, + enum amd_sched_priority priority) +{ + int i; + + if (!ring->funcs->set_priority) + return; + + if (atomic_dec_return(&ring->num_jobs[priority]) > 0) + return; + + /* no need to restore if the job is already at the lowest priority */ + if (priority == AMD_SCHED_PRIORITY_NORMAL) + return; + + mutex_lock(&ring->priority_mutex); + /* something higher prio is executing, no need to decay */ + if (ring->priority > priority) + goto out_unlock; + + /* decay priority to the next level with a job available */ + for (i = priority; i >= AMD_SCHED_PRIORITY_MIN; i--) { + if (i == AMD_SCHED_PRIORITY_NORMAL + || atomic_read(&ring->num_jobs[i])) { + ring->priority = i; + ring->funcs->set_priority(ring, i); + break; + } + } + +out_unlock: + mutex_unlock(&ring->priority_mutex); +} + +/** + * amdgpu_ring_priority_get - change the ring's priority + * + * @ring: amdgpu_ring structure holding the information + * @priority: target priority + * + * Request a ring's priority to be raised to @priority (refcounted). + */ +void amdgpu_ring_priority_get(struct amdgpu_ring *ring, + enum amd_sched_priority priority) +{ + if (!ring->funcs->set_priority) + return; + + atomic_inc(&ring->num_jobs[priority]); + + mutex_lock(&ring->priority_mutex); + if (priority <= ring->priority) + goto out_unlock; + + ring->priority = priority; + ring->funcs->set_priority(ring, priority); + +out_unlock: + mutex_unlock(&ring->priority_mutex); +} + +/** * amdgpu_ring_init - init driver ring struct. * * @adev: amdgpu_device pointer @@ -169,7 +239,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, unsigned max_dw, struct amdgpu_irq_src *irq_src, unsigned irq_type) { - int r; + int r, i; int sched_hw_submission = amdgpu_sched_hw_submission; /* Set the hw submission limit higher for KIQ because @@ -247,9 +317,14 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, } ring->max_dw = max_dw; + ring->priority = AMD_SCHED_PRIORITY_NORMAL; + mutex_init(&ring->priority_mutex); INIT_LIST_HEAD(&ring->lru_list); amdgpu_ring_lru_touch(adev, ring); + for (i = 0; i < AMD_SCHED_PRIORITY_MAX; ++i) + atomic_set(&ring->num_jobs[i], 0); + if (amdgpu_debugfs_ring_init(adev, ring)) { DRM_ERROR("Failed to register debugfs file for rings !\n"); } @@ -315,14 +390,16 @@ static bool amdgpu_ring_is_blacklisted(struct amdgpu_ring *ring, * @type: amdgpu_ring_type enum * @blacklist: blacklisted ring ids array * @num_blacklist: number of entries in @blacklist + * @lru_pipe_order: find a ring from the least recently used pipe * @ring: output ring * * Retrieve the amdgpu_ring structure for the least recently used ring of * a specific IP block (all asics). * Returns 0 on success, error on failure. */ -int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, - int num_blacklist, struct amdgpu_ring **ring) +int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, + int *blacklist, int num_blacklist, + bool lru_pipe_order, struct amdgpu_ring **ring) { struct amdgpu_ring *entry; @@ -337,10 +414,23 @@ int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, if (amdgpu_ring_is_blacklisted(entry, blacklist, num_blacklist)) continue; - *ring = entry; - amdgpu_ring_lru_touch_locked(adev, *ring); - break; + if (!*ring) { + *ring = entry; + + /* We are done for ring LRU */ + if (!lru_pipe_order) + break; + } + + /* Move all rings on the same pipe to the end of the list */ + if (entry->pipe == (*ring)->pipe) + amdgpu_ring_lru_touch_locked(adev, entry); } + + /* Move the ring we found to the end of the list */ + if (*ring) + amdgpu_ring_lru_touch_locked(adev, *ring); + spin_unlock(&adev->ring_lru_list_lock); if (!*ring) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h index 322d25299a00..b18c2b96691f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h @@ -24,6 +24,7 @@ #ifndef __AMDGPU_RING_H__ #define __AMDGPU_RING_H__ +#include <drm/amdgpu_drm.h> #include "gpu_scheduler.h" /* max number of rings */ @@ -56,6 +57,7 @@ struct amdgpu_device; struct amdgpu_ring; struct amdgpu_ib; struct amdgpu_cs_parser; +struct amdgpu_job; /* * Fences. @@ -88,8 +90,12 @@ int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring, void amdgpu_fence_driver_suspend(struct amdgpu_device *adev); void amdgpu_fence_driver_resume(struct amdgpu_device *adev); int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence); +int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s); void amdgpu_fence_process(struct amdgpu_ring *ring); int amdgpu_fence_wait_empty(struct amdgpu_ring *ring); +signed long amdgpu_fence_wait_polling(struct amdgpu_ring *ring, + uint32_t wait_seq, + signed long timeout); unsigned amdgpu_fence_count_emitted(struct amdgpu_ring *ring); /* @@ -147,6 +153,9 @@ struct amdgpu_ring_funcs { void (*emit_rreg)(struct amdgpu_ring *ring, uint32_t reg); void (*emit_wreg)(struct amdgpu_ring *ring, uint32_t reg, uint32_t val); void (*emit_tmz)(struct amdgpu_ring *ring, bool start); + /* priority functions */ + void (*set_priority) (struct amdgpu_ring *ring, + enum amd_sched_priority priority); }; struct amdgpu_ring { @@ -187,6 +196,12 @@ struct amdgpu_ring { volatile u32 *cond_exe_cpu_addr; unsigned vm_inv_eng; bool has_compute_vm_bug; + + atomic_t num_jobs[AMD_SCHED_PRIORITY_MAX]; + struct mutex priority_mutex; + /* protected by priority_mutex */ + int priority; + #if defined(CONFIG_DEBUG_FS) struct dentry *ent; #endif @@ -197,12 +212,17 @@ void amdgpu_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count); void amdgpu_ring_generic_pad_ib(struct amdgpu_ring *ring, struct amdgpu_ib *ib); void amdgpu_ring_commit(struct amdgpu_ring *ring); void amdgpu_ring_undo(struct amdgpu_ring *ring); +void amdgpu_ring_priority_get(struct amdgpu_ring *ring, + enum amd_sched_priority priority); +void amdgpu_ring_priority_put(struct amdgpu_ring *ring, + enum amd_sched_priority priority); int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring, unsigned ring_size, struct amdgpu_irq_src *irq_src, unsigned irq_type); void amdgpu_ring_fini(struct amdgpu_ring *ring); -int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, int *blacklist, - int num_blacklist, struct amdgpu_ring **ring); +int amdgpu_ring_lru_get(struct amdgpu_device *adev, int type, + int *blacklist, int num_blacklist, + bool lru_pipe_order, struct amdgpu_ring **ring); void amdgpu_ring_lru_touch(struct amdgpu_device *adev, struct amdgpu_ring *ring); static inline void amdgpu_ring_clear_ring(struct amdgpu_ring *ring) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c new file mode 100644 index 000000000000..290cc3f9c433 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.c @@ -0,0 +1,109 @@ +/* + * Copyright 2017 Valve Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Andres Rodriguez <andresx7@gmail.com> + */ + +#include <linux/fdtable.h> +#include <linux/pid.h> +#include <drm/amdgpu_drm.h> +#include "amdgpu.h" + +#include "amdgpu_vm.h" + +enum amd_sched_priority amdgpu_to_sched_priority(int amdgpu_priority) +{ + switch (amdgpu_priority) { + case AMDGPU_CTX_PRIORITY_VERY_HIGH: + return AMD_SCHED_PRIORITY_HIGH_HW; + case AMDGPU_CTX_PRIORITY_HIGH: + return AMD_SCHED_PRIORITY_HIGH_SW; + case AMDGPU_CTX_PRIORITY_NORMAL: + return AMD_SCHED_PRIORITY_NORMAL; + case AMDGPU_CTX_PRIORITY_LOW: + case AMDGPU_CTX_PRIORITY_VERY_LOW: + return AMD_SCHED_PRIORITY_LOW; + case AMDGPU_CTX_PRIORITY_UNSET: + return AMD_SCHED_PRIORITY_UNSET; + default: + WARN(1, "Invalid context priority %d\n", amdgpu_priority); + return AMD_SCHED_PRIORITY_INVALID; + } +} + +static int amdgpu_sched_process_priority_override(struct amdgpu_device *adev, + int fd, + enum amd_sched_priority priority) +{ + struct file *filp = fcheck(fd); + struct drm_file *file; + struct pid *pid; + struct amdgpu_fpriv *fpriv; + struct amdgpu_ctx *ctx; + uint32_t id; + + if (!filp) + return -EINVAL; + + pid = get_pid(((struct drm_file *)filp->private_data)->pid); + + mutex_lock(&adev->ddev->filelist_mutex); + list_for_each_entry(file, &adev->ddev->filelist, lhead) { + if (file->pid != pid) + continue; + + fpriv = file->driver_priv; + idr_for_each_entry(&fpriv->ctx_mgr.ctx_handles, ctx, id) + amdgpu_ctx_priority_override(ctx, priority); + } + mutex_unlock(&adev->ddev->filelist_mutex); + + put_pid(pid); + + return 0; +} + +int amdgpu_sched_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp) +{ + union drm_amdgpu_sched *args = data; + struct amdgpu_device *adev = dev->dev_private; + enum amd_sched_priority priority; + int r; + + priority = amdgpu_to_sched_priority(args->in.priority); + if (args->in.flags || priority == AMD_SCHED_PRIORITY_INVALID) + return -EINVAL; + + switch (args->in.op) { + case AMDGPU_SCHED_OP_PROCESS_PRIORITY_OVERRIDE: + r = amdgpu_sched_process_priority_override(adev, + args->in.fd, + priority); + break; + default: + DRM_ERROR("Invalid sched op specified: %d\n", args->in.op); + r = -EINVAL; + break; + } + + return r; +} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h index 13c8dbbccaf2..b28c067d3822 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sched.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2017 Valve Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,22 +19,16 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * + * Authors: Andres Rodriguez <andresx7@gmail.com> */ -#ifndef _ICELAND_SMC_H -#define _ICELAND_SMC_H -#include "smumgr.h" +#ifndef __AMDGPU_SCHED_H__ +#define __AMDGPU_SCHED_H__ +#include <drm/drmP.h> -int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); -int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr); -int iceland_init_smc_table(struct pp_hwmgr *hwmgr); -int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); -int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr); -uint32_t iceland_get_offsetof(uint32_t type, uint32_t member); -uint32_t iceland_get_mac_definition(uint32_t value); -int iceland_process_firmware_header(struct pp_hwmgr *hwmgr); -int iceland_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); -bool iceland_is_dpm_running(struct pp_hwmgr *hwmgr); -#endif +enum amd_sched_priority amdgpu_to_sched_priority(int amdgpu_priority); +int amdgpu_sched_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); +#endif // __AMDGPU_SCHED_H__ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c index c586f44312f9..a4bf21f8f1c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c @@ -169,14 +169,14 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, * * @sync: sync object to add fences from reservation object to * @resv: reservation object with embedded fence - * @shared: true if we should only sync to the exclusive fence + * @explicit_sync: true if we should only sync to the exclusive fence * * Sync to the fence */ int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, struct reservation_object *resv, - void *owner) + void *owner, bool explicit_sync) { struct reservation_object_list *flist; struct dma_fence *f; @@ -191,6 +191,9 @@ int amdgpu_sync_resv(struct amdgpu_device *adev, f = reservation_object_get_excl(resv); r = amdgpu_sync_fence(adev, sync, f); + if (explicit_sync) + return r; + flist = reservation_object_get_list(resv); if (!flist || r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h index dc7687993317..70d7e3a279a0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h @@ -45,7 +45,8 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, struct reservation_object *resv, - void *owner); + void *owner, + bool explicit_sync); struct dma_fence *amdgpu_sync_peek_fence(struct amdgpu_sync *sync, struct amdgpu_ring *ring); struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 15a28578d458..1f036af85ba6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -44,6 +44,7 @@ #include <linux/debugfs.h> #include <linux/iommu.h> #include "amdgpu.h" +#include "amdgpu_object.h" #include "amdgpu_trace.h" #include "bif/bif_4_1_d.h" @@ -209,7 +210,7 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo, placement->num_busy_placement = 1; return; } - abo = container_of(bo, struct amdgpu_bo, tbo); + abo = ttm_to_amdgpu_bo(bo); switch (bo->mem.mem_type) { case TTM_PL_VRAM: if (adev->mman.buffer_funcs && @@ -257,7 +258,7 @@ gtt: static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) { - struct amdgpu_bo *abo = container_of(bo, struct amdgpu_bo, tbo); + struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); if (amdgpu_ttm_tt_get_usermm(bo->ttm)) return -EPERM; @@ -289,97 +290,177 @@ static uint64_t amdgpu_mm_node_addr(struct ttm_buffer_object *bo, return addr; } -static int amdgpu_move_blit(struct ttm_buffer_object *bo, - bool evict, bool no_wait_gpu, - struct ttm_mem_reg *new_mem, - struct ttm_mem_reg *old_mem) +/** + * amdgpu_find_mm_node - Helper function finds the drm_mm_node + * corresponding to @offset. It also modifies the offset to be + * within the drm_mm_node returned + */ +static struct drm_mm_node *amdgpu_find_mm_node(struct ttm_mem_reg *mem, + unsigned long *offset) { - struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); - struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; + struct drm_mm_node *mm_node = mem->mm_node; - struct drm_mm_node *old_mm, *new_mm; - uint64_t old_start, old_size, new_start, new_size; - unsigned long num_pages; - struct dma_fence *fence = NULL; - int r; + while (*offset >= (mm_node->size << PAGE_SHIFT)) { + *offset -= (mm_node->size << PAGE_SHIFT); + ++mm_node; + } + return mm_node; +} - BUILD_BUG_ON((PAGE_SIZE % AMDGPU_GPU_PAGE_SIZE) != 0); +/** + * amdgpu_copy_ttm_mem_to_mem - Helper function for copy + * + * The function copies @size bytes from {src->mem + src->offset} to + * {dst->mem + dst->offset}. src->bo and dst->bo could be same BO for a + * move and different for a BO to BO copy. + * + * @f: Returns the last fence if multiple jobs are submitted. + */ +int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, + struct amdgpu_copy_mem *src, + struct amdgpu_copy_mem *dst, + uint64_t size, + struct reservation_object *resv, + struct dma_fence **f) +{ + struct amdgpu_ring *ring = adev->mman.buffer_funcs_ring; + struct drm_mm_node *src_mm, *dst_mm; + uint64_t src_node_start, dst_node_start, src_node_size, + dst_node_size, src_page_offset, dst_page_offset; + struct dma_fence *fence = NULL; + int r = 0; + const uint64_t GTT_MAX_BYTES = (AMDGPU_GTT_MAX_TRANSFER_SIZE * + AMDGPU_GPU_PAGE_SIZE); if (!ring->ready) { DRM_ERROR("Trying to move memory with ring turned off.\n"); return -EINVAL; } - old_mm = old_mem->mm_node; - old_size = old_mm->size; - old_start = amdgpu_mm_node_addr(bo, old_mm, old_mem); + src_mm = amdgpu_find_mm_node(src->mem, &src->offset); + src_node_start = amdgpu_mm_node_addr(src->bo, src_mm, src->mem) + + src->offset; + src_node_size = (src_mm->size << PAGE_SHIFT) - src->offset; + src_page_offset = src_node_start & (PAGE_SIZE - 1); - new_mm = new_mem->mm_node; - new_size = new_mm->size; - new_start = amdgpu_mm_node_addr(bo, new_mm, new_mem); + dst_mm = amdgpu_find_mm_node(dst->mem, &dst->offset); + dst_node_start = amdgpu_mm_node_addr(dst->bo, dst_mm, dst->mem) + + dst->offset; + dst_node_size = (dst_mm->size << PAGE_SHIFT) - dst->offset; + dst_page_offset = dst_node_start & (PAGE_SIZE - 1); - num_pages = new_mem->num_pages; mutex_lock(&adev->mman.gtt_window_lock); - while (num_pages) { - unsigned long cur_pages = min(min(old_size, new_size), - (u64)AMDGPU_GTT_MAX_TRANSFER_SIZE); - uint64_t from = old_start, to = new_start; + + while (size) { + unsigned long cur_size; + uint64_t from = src_node_start, to = dst_node_start; struct dma_fence *next; - if (old_mem->mem_type == TTM_PL_TT && - !amdgpu_gtt_mgr_is_allocated(old_mem)) { - r = amdgpu_map_buffer(bo, old_mem, cur_pages, - old_start, 0, ring, &from); + /* Copy size cannot exceed GTT_MAX_BYTES. So if src or dst + * begins at an offset, then adjust the size accordingly + */ + cur_size = min3(min(src_node_size, dst_node_size), size, + GTT_MAX_BYTES); + if (cur_size + src_page_offset > GTT_MAX_BYTES || + cur_size + dst_page_offset > GTT_MAX_BYTES) + cur_size -= max(src_page_offset, dst_page_offset); + + /* Map only what needs to be accessed. Map src to window 0 and + * dst to window 1 + */ + if (src->mem->mem_type == TTM_PL_TT && + !amdgpu_gtt_mgr_is_allocated(src->mem)) { + r = amdgpu_map_buffer(src->bo, src->mem, + PFN_UP(cur_size + src_page_offset), + src_node_start, 0, ring, + &from); if (r) goto error; + /* Adjust the offset because amdgpu_map_buffer returns + * start of mapped page + */ + from += src_page_offset; } - if (new_mem->mem_type == TTM_PL_TT && - !amdgpu_gtt_mgr_is_allocated(new_mem)) { - r = amdgpu_map_buffer(bo, new_mem, cur_pages, - new_start, 1, ring, &to); + if (dst->mem->mem_type == TTM_PL_TT && + !amdgpu_gtt_mgr_is_allocated(dst->mem)) { + r = amdgpu_map_buffer(dst->bo, dst->mem, + PFN_UP(cur_size + dst_page_offset), + dst_node_start, 1, ring, + &to); if (r) goto error; + to += dst_page_offset; } - r = amdgpu_copy_buffer(ring, from, to, - cur_pages * PAGE_SIZE, - bo->resv, &next, false, true); + r = amdgpu_copy_buffer(ring, from, to, cur_size, + resv, &next, false, true); if (r) goto error; dma_fence_put(fence); fence = next; - num_pages -= cur_pages; - if (!num_pages) + size -= cur_size; + if (!size) break; - old_size -= cur_pages; - if (!old_size) { - old_start = amdgpu_mm_node_addr(bo, ++old_mm, old_mem); - old_size = old_mm->size; + src_node_size -= cur_size; + if (!src_node_size) { + src_node_start = amdgpu_mm_node_addr(src->bo, ++src_mm, + src->mem); + src_node_size = (src_mm->size << PAGE_SHIFT); } else { - old_start += cur_pages * PAGE_SIZE; + src_node_start += cur_size; + src_page_offset = src_node_start & (PAGE_SIZE - 1); } - - new_size -= cur_pages; - if (!new_size) { - new_start = amdgpu_mm_node_addr(bo, ++new_mm, new_mem); - new_size = new_mm->size; + dst_node_size -= cur_size; + if (!dst_node_size) { + dst_node_start = amdgpu_mm_node_addr(dst->bo, ++dst_mm, + dst->mem); + dst_node_size = (dst_mm->size << PAGE_SHIFT); } else { - new_start += cur_pages * PAGE_SIZE; + dst_node_start += cur_size; + dst_page_offset = dst_node_start & (PAGE_SIZE - 1); } } +error: mutex_unlock(&adev->mman.gtt_window_lock); + if (f) + *f = dma_fence_get(fence); + dma_fence_put(fence); + return r; +} + + +static int amdgpu_move_blit(struct ttm_buffer_object *bo, + bool evict, bool no_wait_gpu, + struct ttm_mem_reg *new_mem, + struct ttm_mem_reg *old_mem) +{ + struct amdgpu_device *adev = amdgpu_ttm_adev(bo->bdev); + struct amdgpu_copy_mem src, dst; + struct dma_fence *fence = NULL; + int r; + + src.bo = bo; + dst.bo = bo; + src.mem = old_mem; + dst.mem = new_mem; + src.offset = 0; + dst.offset = 0; + + r = amdgpu_ttm_copy_mem_to_mem(adev, &src, &dst, + new_mem->num_pages << PAGE_SHIFT, + bo->resv, &fence); + if (r) + goto error; r = ttm_bo_pipeline_move(bo, fence, evict, new_mem); dma_fence_put(fence); return r; error: - mutex_unlock(&adev->mman.gtt_window_lock); - if (fence) dma_fence_wait(fence, false); dma_fence_put(fence); @@ -484,7 +565,7 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, int r; /* Can't move a pinned BO */ - abo = container_of(bo, struct amdgpu_bo, tbo); + abo = ttm_to_amdgpu_bo(bo); if (WARN_ON_ONCE(abo->pin_count > 0)) return -EINVAL; @@ -582,13 +663,12 @@ static void amdgpu_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_re static unsigned long amdgpu_ttm_io_mem_pfn(struct ttm_buffer_object *bo, unsigned long page_offset) { - struct drm_mm_node *mm = bo->mem.mm_node; - uint64_t size = mm->size; - uint64_t offset = page_offset; + struct drm_mm_node *mm; + unsigned long offset = (page_offset << PAGE_SHIFT); - page_offset = do_div(offset, size); - mm += offset; - return (bo->mem.bus.base >> PAGE_SHIFT) + mm->start + page_offset; + mm = amdgpu_find_mm_node(&bo->mem, &offset); + return (bo->mem.bus.base >> PAGE_SHIFT) + mm->start + + (offset >> PAGE_SHIFT); } /* @@ -829,7 +909,8 @@ int amdgpu_ttm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *bo_mem) placement.busy_placement = &placements; placements.fpfn = 0; placements.lpfn = adev->mc.gart_size >> PAGE_SHIFT; - placements.flags = bo->mem.placement | TTM_PL_FLAG_TT; + placements.flags = (bo->mem.placement & ~TTM_PL_MASK_MEM) | + TTM_PL_FLAG_TT; r = ttm_bo_mem_space(bo, &placement, &tmp, true, false); if (unlikely(r)) @@ -1112,9 +1193,6 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, unsigned long num_pages = bo->mem.num_pages; struct drm_mm_node *node = bo->mem.mm_node; - if (bo->mem.start != AMDGPU_BO_INVALID_OFFSET) - return ttm_bo_eviction_valuable(bo, place); - switch (bo->mem.mem_type) { case TTM_PL_TT: return true; @@ -1129,7 +1207,7 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, num_pages -= node->size; ++node; } - break; + return false; default: break; @@ -1142,9 +1220,9 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, unsigned long offset, void *buf, int len, int write) { - struct amdgpu_bo *abo = container_of(bo, struct amdgpu_bo, tbo); + struct amdgpu_bo *abo = ttm_to_amdgpu_bo(bo); struct amdgpu_device *adev = amdgpu_ttm_adev(abo->tbo.bdev); - struct drm_mm_node *nodes = abo->tbo.mem.mm_node; + struct drm_mm_node *nodes; uint32_t value = 0; int ret = 0; uint64_t pos; @@ -1153,10 +1231,7 @@ static int amdgpu_ttm_access_memory(struct ttm_buffer_object *bo, if (bo->mem.mem_type != TTM_PL_VRAM) return -EIO; - while (offset >= (nodes->size << PAGE_SHIFT)) { - offset -= nodes->size << PAGE_SHIFT; - ++nodes; - } + nodes = amdgpu_find_mm_node(&abo->tbo.mem, &offset); pos = (nodes->start << PAGE_SHIFT) + offset; while (len && pos < adev->mc.mc_vram_size) { @@ -1255,6 +1330,15 @@ int amdgpu_ttm_init(struct amdgpu_device *adev) /* Change the size here instead of the init above so only lpfn is affected */ amdgpu_ttm_set_active_vram_size(adev, adev->mc.visible_vram_size); + /* + *The reserved vram for firmware must be pinned to the specified + *place on the VRAM, so reserve it early. + */ + r = amdgpu_fw_reserve_vram_init(adev); + if (r) { + return r; + } + r = amdgpu_bo_create_kernel(adev, adev->mc.stolen_size, PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM, &adev->stolen_vga_memory, @@ -1479,7 +1563,8 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, job->vm_needs_flush = vm_needs_flush; if (resv) { r = amdgpu_sync_resv(adev, &job->sync, resv, - AMDGPU_FENCE_OWNER_UNDEFINED); + AMDGPU_FENCE_OWNER_UNDEFINED, + false); if (r) { DRM_ERROR("sync failed (%d).\n", r); goto error_free; @@ -1571,7 +1656,7 @@ int amdgpu_fill_buffer(struct amdgpu_bo *bo, if (resv) { r = amdgpu_sync_resv(adev, &job->sync, resv, - AMDGPU_FENCE_OWNER_UNDEFINED); + AMDGPU_FENCE_OWNER_UNDEFINED, false); if (r) { DRM_ERROR("sync failed (%d).\n", r); goto error_free; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 7abae6867339..abd4084982a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -58,6 +58,12 @@ struct amdgpu_mman { struct amd_sched_entity entity; }; +struct amdgpu_copy_mem { + struct ttm_buffer_object *bo; + struct ttm_mem_reg *mem; + unsigned long offset; +}; + extern const struct ttm_mem_type_manager_func amdgpu_gtt_mgr_func; extern const struct ttm_mem_type_manager_func amdgpu_vram_mgr_func; @@ -72,6 +78,12 @@ int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, struct reservation_object *resv, struct dma_fence **fence, bool direct_submit, bool vm_needs_flush); +int amdgpu_ttm_copy_mem_to_mem(struct amdgpu_device *adev, + struct amdgpu_copy_mem *src, + struct amdgpu_copy_mem *dst, + uint64_t size, + struct reservation_object *resv, + struct dma_fence **f); int amdgpu_fill_buffer(struct amdgpu_bo *bo, uint64_t src_data, struct reservation_object *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c index b46280c1279f..2918de2f39ec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c @@ -648,7 +648,7 @@ int amdgpu_vce_ring_parse_cs(struct amdgpu_cs_parser *p, uint32_t ib_idx) uint32_t allocated = 0; uint32_t tmp, handle = 0; uint32_t *size = &tmp; - int i, r, idx = 0; + int i, r = 0, idx = 0; p->job->vm = NULL; ib->gpu_addr = amdgpu_sa_bo_gpu_addr(ib->sa_bo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c index 45ac91861965..7f7097931c6f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.c @@ -25,30 +25,26 @@ #include "amdgpu_vf_error.h" #include "mxgpu_ai.h" -#define AMDGPU_VF_ERROR_ENTRY_SIZE 16 - -/* struct error_entry - amdgpu VF error information. */ -struct amdgpu_vf_error_buffer { - int read_count; - int write_count; - uint16_t code[AMDGPU_VF_ERROR_ENTRY_SIZE]; - uint16_t flags[AMDGPU_VF_ERROR_ENTRY_SIZE]; - uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE]; -}; - -struct amdgpu_vf_error_buffer admgpu_vf_errors; - - -void amdgpu_vf_error_put(uint16_t sub_error_code, uint16_t error_flags, uint64_t error_data) +void amdgpu_vf_error_put(struct amdgpu_device *adev, + uint16_t sub_error_code, + uint16_t error_flags, + uint64_t error_data) { int index; - uint16_t error_code = AMDGIM_ERROR_CODE(AMDGIM_ERROR_CATEGORY_VF, sub_error_code); + uint16_t error_code; - index = admgpu_vf_errors.write_count % AMDGPU_VF_ERROR_ENTRY_SIZE; - admgpu_vf_errors.code [index] = error_code; - admgpu_vf_errors.flags [index] = error_flags; - admgpu_vf_errors.data [index] = error_data; - admgpu_vf_errors.write_count ++; + if (!amdgpu_sriov_vf(adev)) + return; + + error_code = AMDGIM_ERROR_CODE(AMDGIM_ERROR_CATEGORY_VF, sub_error_code); + + mutex_lock(&adev->virt.vf_errors.lock); + index = adev->virt.vf_errors.write_count % AMDGPU_VF_ERROR_ENTRY_SIZE; + adev->virt.vf_errors.code [index] = error_code; + adev->virt.vf_errors.flags [index] = error_flags; + adev->virt.vf_errors.data [index] = error_data; + adev->virt.vf_errors.write_count ++; + mutex_unlock(&adev->virt.vf_errors.lock); } @@ -58,7 +54,8 @@ void amdgpu_vf_error_trans_all(struct amdgpu_device *adev) u32 data1, data2, data3; int index; - if ((NULL == adev) || (!amdgpu_sriov_vf(adev)) || (!adev->virt.ops) || (!adev->virt.ops->trans_msg)) { + if ((NULL == adev) || (!amdgpu_sriov_vf(adev)) || + (!adev->virt.ops) || (!adev->virt.ops->trans_msg)) { return; } /* @@ -68,18 +65,22 @@ void amdgpu_vf_error_trans_all(struct amdgpu_device *adev) return; } */ + + mutex_lock(&adev->virt.vf_errors.lock); /* The errors are overlay of array, correct read_count as full. */ - if (admgpu_vf_errors.write_count - admgpu_vf_errors.read_count > AMDGPU_VF_ERROR_ENTRY_SIZE) { - admgpu_vf_errors.read_count = admgpu_vf_errors.write_count - AMDGPU_VF_ERROR_ENTRY_SIZE; + if (adev->virt.vf_errors.write_count - adev->virt.vf_errors.read_count > AMDGPU_VF_ERROR_ENTRY_SIZE) { + adev->virt.vf_errors.read_count = adev->virt.vf_errors.write_count - AMDGPU_VF_ERROR_ENTRY_SIZE; } - while (admgpu_vf_errors.read_count < admgpu_vf_errors.write_count) { - index =admgpu_vf_errors.read_count % AMDGPU_VF_ERROR_ENTRY_SIZE; - data1 = AMDGIM_ERROR_CODE_FLAGS_TO_MAILBOX (admgpu_vf_errors.code[index], admgpu_vf_errors.flags[index]); - data2 = admgpu_vf_errors.data[index] & 0xFFFFFFFF; - data3 = (admgpu_vf_errors.data[index] >> 32) & 0xFFFFFFFF; + while (adev->virt.vf_errors.read_count < adev->virt.vf_errors.write_count) { + index =adev->virt.vf_errors.read_count % AMDGPU_VF_ERROR_ENTRY_SIZE; + data1 = AMDGIM_ERROR_CODE_FLAGS_TO_MAILBOX(adev->virt.vf_errors.code[index], + adev->virt.vf_errors.flags[index]); + data2 = adev->virt.vf_errors.data[index] & 0xFFFFFFFF; + data3 = (adev->virt.vf_errors.data[index] >> 32) & 0xFFFFFFFF; adev->virt.ops->trans_msg(adev, IDH_LOG_VF_ERROR, data1, data2, data3); - admgpu_vf_errors.read_count ++; + adev->virt.vf_errors.read_count ++; } + mutex_unlock(&adev->virt.vf_errors.lock); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h index 2a3278ec76ba..6436bd053325 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vf_error.h @@ -56,7 +56,10 @@ enum AMDGIM_ERROR_CATEGORY { AMDGIM_ERROR_CATEGORY_MAX }; -void amdgpu_vf_error_put(uint16_t sub_error_code, uint16_t error_flags, uint64_t error_data); +void amdgpu_vf_error_put(struct amdgpu_device *adev, + uint16_t sub_error_code, + uint16_t error_flags, + uint64_t error_data); void amdgpu_vf_error_trans_all (struct amdgpu_device *adev); #endif /* __VF_ERROR_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index ab05121b9272..6738df836a70 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -22,7 +22,7 @@ */ #include "amdgpu.h" -#define MAX_KIQ_REG_WAIT 100000 +#define MAX_KIQ_REG_WAIT 100000000 /* in usecs */ int amdgpu_allocate_static_csa(struct amdgpu_device *adev) { @@ -114,27 +114,25 @@ void amdgpu_virt_init_setting(struct amdgpu_device *adev) uint32_t amdgpu_virt_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) { signed long r; - uint32_t val; - struct dma_fence *f; + unsigned long flags; + uint32_t val, seq; struct amdgpu_kiq *kiq = &adev->gfx.kiq; struct amdgpu_ring *ring = &kiq->ring; BUG_ON(!ring->funcs->emit_rreg); - mutex_lock(&kiq->ring_mutex); + spin_lock_irqsave(&kiq->ring_lock, flags); amdgpu_ring_alloc(ring, 32); amdgpu_ring_emit_rreg(ring, reg); - amdgpu_fence_emit(ring, &f); + amdgpu_fence_emit_polling(ring, &seq); amdgpu_ring_commit(ring); - mutex_unlock(&kiq->ring_mutex); + spin_unlock_irqrestore(&kiq->ring_lock, flags); - r = dma_fence_wait_timeout(f, false, msecs_to_jiffies(MAX_KIQ_REG_WAIT)); - dma_fence_put(f); + r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT); if (r < 1) { - DRM_ERROR("wait for kiq fence error: %ld.\n", r); + DRM_ERROR("wait for kiq fence error: %ld\n", r); return ~0; } - val = adev->wb.wb[adev->virt.reg_val_offs]; return val; @@ -143,23 +141,23 @@ uint32_t amdgpu_virt_kiq_rreg(struct amdgpu_device *adev, uint32_t reg) void amdgpu_virt_kiq_wreg(struct amdgpu_device *adev, uint32_t reg, uint32_t v) { signed long r; - struct dma_fence *f; + unsigned long flags; + uint32_t seq; struct amdgpu_kiq *kiq = &adev->gfx.kiq; struct amdgpu_ring *ring = &kiq->ring; BUG_ON(!ring->funcs->emit_wreg); - mutex_lock(&kiq->ring_mutex); + spin_lock_irqsave(&kiq->ring_lock, flags); amdgpu_ring_alloc(ring, 32); amdgpu_ring_emit_wreg(ring, reg, v); - amdgpu_fence_emit(ring, &f); + amdgpu_fence_emit_polling(ring, &seq); amdgpu_ring_commit(ring); - mutex_unlock(&kiq->ring_mutex); + spin_unlock_irqrestore(&kiq->ring_lock, flags); - r = dma_fence_wait_timeout(f, false, msecs_to_jiffies(MAX_KIQ_REG_WAIT)); + r = amdgpu_fence_wait_polling(ring, seq, MAX_KIQ_REG_WAIT); if (r < 1) - DRM_ERROR("wait for kiq fence error: %ld.\n", r); - dma_fence_put(f); + DRM_ERROR("wait for kiq fence error: %ld\n", r); } /** @@ -274,3 +272,80 @@ void amdgpu_virt_free_mm_table(struct amdgpu_device *adev) (void *)&adev->virt.mm_table.cpu_addr); adev->virt.mm_table.gpu_addr = 0; } + + +int amdgpu_virt_fw_reserve_get_checksum(void *obj, + unsigned long obj_size, + unsigned int key, + unsigned int chksum) +{ + unsigned int ret = key; + unsigned long i = 0; + unsigned char *pos; + + pos = (char *)obj; + /* calculate checksum */ + for (i = 0; i < obj_size; ++i) + ret += *(pos + i); + /* minus the chksum itself */ + pos = (char *)&chksum; + for (i = 0; i < sizeof(chksum); ++i) + ret -= *(pos + i); + return ret; +} + +void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev) +{ + uint32_t pf2vf_ver = 0; + uint32_t pf2vf_size = 0; + uint32_t checksum = 0; + uint32_t checkval; + char *str; + + adev->virt.fw_reserve.p_pf2vf = NULL; + adev->virt.fw_reserve.p_vf2pf = NULL; + + if (adev->fw_vram_usage.va != NULL) { + adev->virt.fw_reserve.p_pf2vf = + (struct amdgim_pf2vf_info_header *)( + adev->fw_vram_usage.va + AMDGIM_DATAEXCHANGE_OFFSET); + pf2vf_ver = adev->virt.fw_reserve.p_pf2vf->version; + AMDGPU_FW_VRAM_PF2VF_READ(adev, header.size, &pf2vf_size); + AMDGPU_FW_VRAM_PF2VF_READ(adev, checksum, &checksum); + + /* pf2vf message must be in 4K */ + if (pf2vf_size > 0 && pf2vf_size < 4096) { + checkval = amdgpu_virt_fw_reserve_get_checksum( + adev->virt.fw_reserve.p_pf2vf, pf2vf_size, + adev->virt.fw_reserve.checksum_key, checksum); + if (checkval == checksum) { + adev->virt.fw_reserve.p_vf2pf = + ((void *)adev->virt.fw_reserve.p_pf2vf + + pf2vf_size); + memset((void *)adev->virt.fw_reserve.p_vf2pf, 0, + sizeof(amdgim_vf2pf_info)); + AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.version, + AMDGPU_FW_VRAM_VF2PF_VER); + AMDGPU_FW_VRAM_VF2PF_WRITE(adev, header.size, + sizeof(amdgim_vf2pf_info)); + AMDGPU_FW_VRAM_VF2PF_READ(adev, driver_version, + &str); +#ifdef MODULE + if (THIS_MODULE->version != NULL) + strcpy(str, THIS_MODULE->version); + else +#endif + strcpy(str, "N/A"); + AMDGPU_FW_VRAM_VF2PF_WRITE(adev, driver_cert, + 0); + AMDGPU_FW_VRAM_VF2PF_WRITE(adev, checksum, + amdgpu_virt_fw_reserve_get_checksum( + adev->virt.fw_reserve.p_vf2pf, + pf2vf_size, + adev->virt.fw_reserve.checksum_key, 0)); + } + } + } +} + + diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h index afcfb8bcfb65..b89d37fc406f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h @@ -36,6 +36,18 @@ struct amdgpu_mm_table { uint64_t gpu_addr; }; +#define AMDGPU_VF_ERROR_ENTRY_SIZE 16 + +/* struct error_entry - amdgpu VF error information. */ +struct amdgpu_vf_error_buffer { + struct mutex lock; + int read_count; + int write_count; + uint16_t code[AMDGPU_VF_ERROR_ENTRY_SIZE]; + uint16_t flags[AMDGPU_VF_ERROR_ENTRY_SIZE]; + uint64_t data[AMDGPU_VF_ERROR_ENTRY_SIZE]; +}; + /** * struct amdgpu_virt_ops - amdgpu device virt operations */ @@ -46,6 +58,179 @@ struct amdgpu_virt_ops { void (*trans_msg)(struct amdgpu_device *adev, u32 req, u32 data1, u32 data2, u32 data3); }; +/* + * Firmware Reserve Frame buffer + */ +struct amdgpu_virt_fw_reserve { + struct amdgim_pf2vf_info_header *p_pf2vf; + struct amdgim_vf2pf_info_header *p_vf2pf; + unsigned int checksum_key; +}; +/* + * Defination between PF and VF + * Structures forcibly aligned to 4 to keep the same style as PF. + */ +#define AMDGIM_DATAEXCHANGE_OFFSET (64 * 1024) + +#define AMDGIM_GET_STRUCTURE_RESERVED_SIZE(total, u8, u16, u32, u64) \ + (total - (((u8)+3) / 4 + ((u16)+1) / 2 + (u32) + (u64)*2)) + +enum AMDGIM_FEATURE_FLAG { + /* GIM supports feature of Error log collecting */ + AMDGIM_FEATURE_ERROR_LOG_COLLECT = 0x1, + /* GIM supports feature of loading uCodes */ + AMDGIM_FEATURE_GIM_LOAD_UCODES = 0x2, +}; + +struct amdgim_pf2vf_info_header { + /* the total structure size in byte. */ + uint32_t size; + /* version of this structure, written by the GIM */ + uint32_t version; +} __aligned(4); +struct amdgim_pf2vf_info_v1 { + /* header contains size and version */ + struct amdgim_pf2vf_info_header header; + /* max_width * max_height */ + unsigned int uvd_enc_max_pixels_count; + /* 16x16 pixels/sec, codec independent */ + unsigned int uvd_enc_max_bandwidth; + /* max_width * max_height */ + unsigned int vce_enc_max_pixels_count; + /* 16x16 pixels/sec, codec independent */ + unsigned int vce_enc_max_bandwidth; + /* MEC FW position in kb from the start of visible frame buffer */ + unsigned int mecfw_kboffset; + /* The features flags of the GIM driver supports. */ + unsigned int feature_flags; + /* use private key from mailbox 2 to create chueksum */ + unsigned int checksum; +} __aligned(4); + +struct amdgim_pf2vf_info_v2 { + /* header contains size and version */ + struct amdgim_pf2vf_info_header header; + /* use private key from mailbox 2 to create chueksum */ + uint32_t checksum; + /* The features flags of the GIM driver supports. */ + uint32_t feature_flags; + /* max_width * max_height */ + uint32_t uvd_enc_max_pixels_count; + /* 16x16 pixels/sec, codec independent */ + uint32_t uvd_enc_max_bandwidth; + /* max_width * max_height */ + uint32_t vce_enc_max_pixels_count; + /* 16x16 pixels/sec, codec independent */ + uint32_t vce_enc_max_bandwidth; + /* MEC FW position in kb from the start of VF visible frame buffer */ + uint64_t mecfw_kboffset; + /* MEC FW size in KB */ + uint32_t mecfw_ksize; + /* UVD FW position in kb from the start of VF visible frame buffer */ + uint64_t uvdfw_kboffset; + /* UVD FW size in KB */ + uint32_t uvdfw_ksize; + /* VCE FW position in kb from the start of VF visible frame buffer */ + uint64_t vcefw_kboffset; + /* VCE FW size in KB */ + uint32_t vcefw_ksize; + uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 0, 0, (9 + sizeof(struct amdgim_pf2vf_info_header)/sizeof(uint32_t)), 3)]; +} __aligned(4); + + +struct amdgim_vf2pf_info_header { + /* the total structure size in byte. */ + uint32_t size; + /*version of this structure, written by the guest */ + uint32_t version; +} __aligned(4); + +struct amdgim_vf2pf_info_v1 { + /* header contains size and version */ + struct amdgim_vf2pf_info_header header; + /* driver version */ + char driver_version[64]; + /* driver certification, 1=WHQL, 0=None */ + unsigned int driver_cert; + /* guest OS type and version: need a define */ + unsigned int os_info; + /* in the unit of 1M */ + unsigned int fb_usage; + /* guest gfx engine usage percentage */ + unsigned int gfx_usage; + /* guest gfx engine health percentage */ + unsigned int gfx_health; + /* guest compute engine usage percentage */ + unsigned int compute_usage; + /* guest compute engine health percentage */ + unsigned int compute_health; + /* guest vce engine usage percentage. 0xffff means N/A. */ + unsigned int vce_enc_usage; + /* guest vce engine health percentage. 0xffff means N/A. */ + unsigned int vce_enc_health; + /* guest uvd engine usage percentage. 0xffff means N/A. */ + unsigned int uvd_enc_usage; + /* guest uvd engine usage percentage. 0xffff means N/A. */ + unsigned int uvd_enc_health; + unsigned int checksum; +} __aligned(4); + +struct amdgim_vf2pf_info_v2 { + /* header contains size and version */ + struct amdgim_vf2pf_info_header header; + uint32_t checksum; + /* driver version */ + uint8_t driver_version[64]; + /* driver certification, 1=WHQL, 0=None */ + uint32_t driver_cert; + /* guest OS type and version: need a define */ + uint32_t os_info; + /* in the unit of 1M */ + uint32_t fb_usage; + /* guest gfx engine usage percentage */ + uint32_t gfx_usage; + /* guest gfx engine health percentage */ + uint32_t gfx_health; + /* guest compute engine usage percentage */ + uint32_t compute_usage; + /* guest compute engine health percentage */ + uint32_t compute_health; + /* guest vce engine usage percentage. 0xffff means N/A. */ + uint32_t vce_enc_usage; + /* guest vce engine health percentage. 0xffff means N/A. */ + uint32_t vce_enc_health; + /* guest uvd engine usage percentage. 0xffff means N/A. */ + uint32_t uvd_enc_usage; + /* guest uvd engine usage percentage. 0xffff means N/A. */ + uint32_t uvd_enc_health; + uint32_t reserved[AMDGIM_GET_STRUCTURE_RESERVED_SIZE(256, 64, 0, (12 + sizeof(struct amdgim_vf2pf_info_header)/sizeof(uint32_t)), 0)]; +} __aligned(4); + +#define AMDGPU_FW_VRAM_VF2PF_VER 2 +typedef struct amdgim_vf2pf_info_v2 amdgim_vf2pf_info ; + +#define AMDGPU_FW_VRAM_VF2PF_WRITE(adev, field, val) \ + do { \ + ((amdgim_vf2pf_info *)adev->virt.fw_reserve.p_vf2pf)->field = (val); \ + } while (0) + +#define AMDGPU_FW_VRAM_VF2PF_READ(adev, field, val) \ + do { \ + (*val) = ((amdgim_vf2pf_info *)adev->virt.fw_reserve.p_vf2pf)->field; \ + } while (0) + +#define AMDGPU_FW_VRAM_PF2VF_READ(adev, field, val) \ + do { \ + if (!adev->virt.fw_reserve.p_pf2vf) \ + *(val) = 0; \ + else { \ + if (adev->virt.fw_reserve.p_pf2vf->version == 1) \ + *(val) = ((struct amdgim_pf2vf_info_v1 *)adev->virt.fw_reserve.p_pf2vf)->field; \ + if (adev->virt.fw_reserve.p_pf2vf->version == 2) \ + *(val) = ((struct amdgim_pf2vf_info_v2 *)adev->virt.fw_reserve.p_pf2vf)->field; \ + } \ + } while (0) + /* GPU virtualization */ struct amdgpu_virt { uint32_t caps; @@ -59,6 +244,8 @@ struct amdgpu_virt { struct work_struct flr_work; struct amdgpu_mm_table mm_table; const struct amdgpu_virt_ops *ops; + struct amdgpu_vf_error_buffer vf_errors; + struct amdgpu_virt_fw_reserve fw_reserve; }; #define AMDGPU_CSA_SIZE (8 * 1024) @@ -101,5 +288,9 @@ int amdgpu_virt_reset_gpu(struct amdgpu_device *adev); int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, struct amdgpu_job *job); int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev); void amdgpu_virt_free_mm_table(struct amdgpu_device *adev); +int amdgpu_virt_fw_reserve_get_checksum(void *obj, unsigned long obj_size, + unsigned int key, + unsigned int chksum); +void amdgpu_virt_init_data_exchange(struct amdgpu_device *adev); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index bbcc67038203..c8c26f21993c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -328,9 +328,10 @@ static int amdgpu_vm_alloc_levels(struct amdgpu_device *adev, AMDGPU_GEM_CREATE_SHADOW); if (vm->pte_support_ats) { - init_value = AMDGPU_PTE_SYSTEM; + init_value = AMDGPU_PTE_DEFAULT_ATC; if (level != adev->vm_manager.num_level - 1) init_value |= AMDGPU_PDE_PTE; + } /* walk over the address space and allocate the page tables */ @@ -1034,7 +1035,7 @@ static int amdgpu_vm_wait_pd(struct amdgpu_device *adev, struct amdgpu_vm *vm, int r; amdgpu_sync_create(&sync); - amdgpu_sync_resv(adev, &sync, vm->root.base.bo->tbo.resv, owner); + amdgpu_sync_resv(adev, &sync, vm->root.base.bo->tbo.resv, owner, false); r = amdgpu_sync_wait(&sync, true); amdgpu_sync_free(&sync); @@ -1175,11 +1176,11 @@ static int amdgpu_vm_update_level(struct amdgpu_device *adev, amdgpu_ring_pad_ib(ring, params.ib); amdgpu_sync_resv(adev, &job->sync, parent->base.bo->tbo.resv, - AMDGPU_FENCE_OWNER_VM); + AMDGPU_FENCE_OWNER_VM, false); if (shadow) amdgpu_sync_resv(adev, &job->sync, shadow->tbo.resv, - AMDGPU_FENCE_OWNER_VM); + AMDGPU_FENCE_OWNER_VM, false); WARN_ON(params.ib->length_dw > ndw); r = amdgpu_job_submit(job, ring, &vm->entity, @@ -1243,7 +1244,7 @@ static void amdgpu_vm_invalidate_level(struct amdgpu_vm *vm, int amdgpu_vm_update_directories(struct amdgpu_device *adev, struct amdgpu_vm *vm) { - int r; + int r = 0; spin_lock(&vm->status_lock); while (!list_empty(&vm->relocated)) { @@ -1643,7 +1644,7 @@ static int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, goto error_free; r = amdgpu_sync_resv(adev, &job->sync, vm->root.base.bo->tbo.resv, - owner); + owner, false); if (r) goto error_free; @@ -1698,6 +1699,7 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, struct drm_mm_node *nodes, struct dma_fence **fence) { + unsigned min_linear_pages = 1 << adev->vm_manager.fragment_size; uint64_t pfn, start = mapping->start; int r; @@ -1732,6 +1734,7 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, } do { + dma_addr_t *dma_addr = NULL; uint64_t max_entries; uint64_t addr, last; @@ -1745,15 +1748,32 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev, } if (pages_addr) { + uint64_t count; + max_entries = min(max_entries, 16ull * 1024ull); - addr = 0; + for (count = 1; count < max_entries; ++count) { + uint64_t idx = pfn + count; + + if (pages_addr[idx] != + (pages_addr[idx - 1] + PAGE_SIZE)) + break; + } + + if (count < min_linear_pages) { + addr = pfn << PAGE_SHIFT; + dma_addr = pages_addr; + } else { + addr = pages_addr[pfn]; + max_entries = count; + } + } else if (flags & AMDGPU_PTE_VALID) { addr += adev->vm_manager.vram_base_offset; + addr += pfn << PAGE_SHIFT; } - addr += pfn << PAGE_SHIFT; last = min((uint64_t)mapping->last, start + max_entries - 1); - r = amdgpu_vm_bo_update_mapping(adev, exclusive, pages_addr, vm, + r = amdgpu_vm_bo_update_mapping(adev, exclusive, dma_addr, vm, start, last, flags, addr, fence); if (r) @@ -2017,7 +2037,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, list_del(&mapping->list); if (vm->pte_support_ats) - init_pte_value = AMDGPU_PTE_SYSTEM; + init_pte_value = AMDGPU_PTE_DEFAULT_ATC; r = amdgpu_vm_bo_update_mapping(adev, NULL, NULL, vm, mapping->start, mapping->last, @@ -2541,7 +2561,8 @@ static uint32_t amdgpu_vm_get_block_size(uint64_t vm_size) * @adev: amdgpu_device pointer * @fragment_size_default: the default fragment size if it's set auto */ -void amdgpu_vm_set_fragment_size(struct amdgpu_device *adev, uint32_t fragment_size_default) +void amdgpu_vm_set_fragment_size(struct amdgpu_device *adev, + uint32_t fragment_size_default) { if (amdgpu_vm_fragment_size == -1) adev->vm_manager.fragment_size = fragment_size_default; @@ -2555,7 +2576,8 @@ void amdgpu_vm_set_fragment_size(struct amdgpu_device *adev, uint32_t fragment_s * @adev: amdgpu_device pointer * @vm_size: the default vm size if it's set auto */ -void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint64_t vm_size, uint32_t fragment_size_default) +void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint64_t vm_size, + uint32_t fragment_size_default) { /* adjust vm size firstly */ if (amdgpu_vm_size == -1) @@ -2627,7 +2649,9 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, if (adev->asic_type == CHIP_RAVEN) { vm->pte_support_ats = true; - init_pde_value = AMDGPU_PTE_SYSTEM | AMDGPU_PDE_PTE; + init_pde_value = AMDGPU_PTE_DEFAULT_ATC + | AMDGPU_PDE_PTE; + } } else vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode & @@ -2682,6 +2706,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, } INIT_KFIFO(vm->faults); + vm->fault_credit = 16; return 0; @@ -2734,8 +2759,9 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) { struct amdgpu_bo_va_mapping *mapping, *tmp; bool prt_fini_needed = !!adev->gart.gart_funcs->set_prt; + struct amdgpu_bo *root; u64 fault; - int i; + int i, r; /* Clear pending page faults from IH when the VM is destroyed */ while (kfifo_get(&vm->faults, &fault)) @@ -2770,13 +2796,51 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) amdgpu_vm_free_mapping(adev, vm, mapping, NULL); } - amdgpu_vm_free_levels(&vm->root); + root = amdgpu_bo_ref(vm->root.base.bo); + r = amdgpu_bo_reserve(root, true); + if (r) { + dev_err(adev->dev, "Leaking page tables because BO reservation failed\n"); + } else { + amdgpu_vm_free_levels(&vm->root); + amdgpu_bo_unreserve(root); + } + amdgpu_bo_unref(&root); dma_fence_put(vm->last_update); for (i = 0; i < AMDGPU_MAX_VMHUBS; i++) amdgpu_vm_free_reserved_vmid(adev, vm, i); } /** + * amdgpu_vm_pasid_fault_credit - Check fault credit for given PASID + * + * @adev: amdgpu_device pointer + * @pasid: PASID do identify the VM + * + * This function is expected to be called in interrupt context. Returns + * true if there was fault credit, false otherwise + */ +bool amdgpu_vm_pasid_fault_credit(struct amdgpu_device *adev, + unsigned int pasid) +{ + struct amdgpu_vm *vm; + + spin_lock(&adev->vm_manager.pasid_lock); + vm = idr_find(&adev->vm_manager.pasid_idr, pasid); + spin_unlock(&adev->vm_manager.pasid_lock); + if (!vm) + /* VM not found, can't track fault credit */ + return true; + + /* No lock needed. only accessed by IRQ handler */ + if (!vm->fault_credit) + /* Too many faults in this VM */ + return false; + + vm->fault_credit--; + return true; +} + +/** * amdgpu_vm_manager_init - init the VM manager * * @adev: amdgpu_device pointer diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 0af090667dfc..aa914256b4bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -73,6 +73,16 @@ struct amdgpu_bo_list_entry; #define AMDGPU_PTE_MTYPE(a) ((uint64_t)a << 57) #define AMDGPU_PTE_MTYPE_MASK AMDGPU_PTE_MTYPE(3ULL) +/* For Raven */ +#define AMDGPU_MTYPE_CC 2 + +#define AMDGPU_PTE_DEFAULT_ATC (AMDGPU_PTE_SYSTEM \ + | AMDGPU_PTE_SNOOPED \ + | AMDGPU_PTE_EXECUTABLE \ + | AMDGPU_PTE_READABLE \ + | AMDGPU_PTE_WRITEABLE \ + | AMDGPU_PTE_MTYPE(AMDGPU_MTYPE_CC)) + /* How to programm VM fault handling */ #define AMDGPU_VM_FAULT_STOP_NEVER 0 #define AMDGPU_VM_FAULT_STOP_FIRST 1 @@ -165,8 +175,11 @@ struct amdgpu_vm { /* Flag to indicate ATS support from PTE for GFX9 */ bool pte_support_ats; - /* Up to 128 pending page faults */ + /* Up to 128 pending retry page faults */ DECLARE_KFIFO(faults, u64, 128); + + /* Limit non-retry fault storms */ + unsigned int fault_credit; }; struct amdgpu_vm_id { @@ -244,6 +257,8 @@ void amdgpu_vm_manager_fini(struct amdgpu_device *adev); int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, int vm_context, unsigned int pasid); void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); +bool amdgpu_vm_pasid_fault_credit(struct amdgpu_device *adev, + unsigned int pasid); void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, struct list_head *validated, struct amdgpu_bo_list_entry *entry); diff --git a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c index 68ce1bdaf2fc..68b505c768ad 100644 --- a/drivers/gpu/drm/amd/amdgpu/ci_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/ci_dpm.c @@ -6365,7 +6365,6 @@ static int ci_dpm_sw_fini(void *handle) flush_work(&adev->pm.dpm.thermal.work); mutex_lock(&adev->pm.mutex); - amdgpu_pm_sysfs_fini(adev); ci_dpm_fini(adev); mutex_unlock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/cik_ih.c b/drivers/gpu/drm/amd/amdgpu/cik_ih.c index 07d3d895da10..a870b354e3f7 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cik_ih.c @@ -237,8 +237,23 @@ static u32 cik_ih_get_wptr(struct amdgpu_device *adev) */ static bool cik_ih_prescreen_iv(struct amdgpu_device *adev) { - /* Process all interrupts */ - return true; + u32 ring_index = adev->irq.ih.rptr >> 2; + u16 pasid; + + switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { + case 146: + case 147: + pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; + if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) + return true; + break; + default: + /* Not a VM fault */ + return true; + } + + adev->irq.ih.rptr += 16; + return false; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ih.c b/drivers/gpu/drm/amd/amdgpu/cz_ih.c index b6cdf4afaf46..fa61d649bb44 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/cz_ih.c @@ -216,8 +216,23 @@ static u32 cz_ih_get_wptr(struct amdgpu_device *adev) */ static bool cz_ih_prescreen_iv(struct amdgpu_device *adev) { - /* Process all interrupts */ - return true; + u32 ring_index = adev->irq.ih.rptr >> 2; + u16 pasid; + + switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { + case 146: + case 147: + pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; + if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) + return true; + break; + default: + /* Not a VM fault */ + return true; + } + + adev->irq.ih.rptr += 16; + return false; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c index b9ee9073cb0d..a8829af120c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/dce_virtual.c +++ b/drivers/gpu/drm/amd/amdgpu/dce_virtual.c @@ -288,7 +288,7 @@ dce_virtual_encoder(struct drm_connector *connector) if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -298,7 +298,7 @@ dce_virtual_encoder(struct drm_connector *connector) /* pick the first one */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index dfc10b1baea0..b8002ac3e536 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -20,6 +20,7 @@ * OTHER DEALINGS IN THE SOFTWARE. * */ +#include <linux/kernel.h> #include <linux/firmware.h> #include <drm/drmP.h> #include "amdgpu.h" @@ -3952,10 +3953,10 @@ static int gfx_v8_0_init_save_restore_list(struct amdgpu_device *adev) adev->gfx.rlc.reg_list_format_size_bytes >> 2, unique_indices, &indices_count, - sizeof(unique_indices) / sizeof(int), + ARRAY_SIZE(unique_indices), indirect_start_offsets, &offset_count, - sizeof(indirect_start_offsets)/sizeof(int)); + ARRAY_SIZE(indirect_start_offsets)); /* save and restore list */ WREG32_FIELD(RLC_SRM_CNTL, AUTO_INCR_ADDR, 1); @@ -3977,14 +3978,14 @@ static int gfx_v8_0_init_save_restore_list(struct amdgpu_device *adev) /* starting offsets starts */ WREG32(mmRLC_GPM_SCRATCH_ADDR, adev->gfx.rlc.starting_offsets_start); - for (i = 0; i < sizeof(indirect_start_offsets)/sizeof(int); i++) + for (i = 0; i < ARRAY_SIZE(indirect_start_offsets); i++) WREG32(mmRLC_GPM_SCRATCH_DATA, indirect_start_offsets[i]); /* unique indices */ temp = mmRLC_SRM_INDEX_CNTL_ADDR_0; data = mmRLC_SRM_INDEX_CNTL_DATA_0; - for (i = 0; i < sizeof(unique_indices) / sizeof(int); i++) { + for (i = 0; i < ARRAY_SIZE(unique_indices); i++) { if (unique_indices[i] != 0) { WREG32(temp + i, unique_indices[i] & 0x3FFFF); WREG32(data + i, unique_indices[i] >> 20); @@ -4132,18 +4133,12 @@ static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev) gfx_v8_0_rlc_reset(adev); gfx_v8_0_init_pg(adev); - if (!adev->pp_enabled) { - if (adev->firmware.load_type != AMDGPU_FW_LOAD_SMU) { - /* legacy rlc firmware loading */ - r = gfx_v8_0_rlc_load_microcode(adev); - if (r) - return r; - } else { - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_RLC_G); - if (r) - return -EINVAL; - } + + if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { + /* legacy rlc firmware loading */ + r = gfx_v8_0_rlc_load_microcode(adev); + if (r) + return r; } gfx_v8_0_rlc_start(adev); @@ -4959,43 +4954,15 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev) if (!(adev->flags & AMD_IS_APU)) gfx_v8_0_enable_gui_idle_interrupt(adev, false); - if (!adev->pp_enabled) { - if (adev->firmware.load_type != AMDGPU_FW_LOAD_SMU) { + if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { /* legacy firmware loading */ - r = gfx_v8_0_cp_gfx_load_microcode(adev); - if (r) - return r; + r = gfx_v8_0_cp_gfx_load_microcode(adev); + if (r) + return r; - r = gfx_v8_0_cp_compute_load_microcode(adev); - if (r) - return r; - } else { - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_CE); - if (r) - return -EINVAL; - - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_PFP); - if (r) - return -EINVAL; - - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_ME); - if (r) - return -EINVAL; - - if (adev->asic_type == CHIP_TOPAZ) { - r = gfx_v8_0_cp_compute_load_microcode(adev); - if (r) - return r; - } else { - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_MEC1); - if (r) - return -EINVAL; - } - } + r = gfx_v8_0_cp_compute_load_microcode(adev); + if (r) + return r; } r = gfx_v8_0_cp_gfx_resume(adev); @@ -6018,7 +5985,6 @@ static int gfx_v8_0_tonga_update_gfx_clock_gating(struct amdgpu_device *adev, { uint32_t msg_id, pp_state = 0; uint32_t pp_support_state = 0; - void *pp_handle = adev->powerplay.pp_handle; if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS)) { if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) { @@ -6036,7 +6002,8 @@ static int gfx_v8_0_tonga_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CG, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)) { @@ -6057,7 +6024,8 @@ static int gfx_v8_0_tonga_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_MG, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; @@ -6069,7 +6037,6 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, uint32_t msg_id, pp_state = 0; uint32_t pp_support_state = 0; - void *pp_handle = adev->powerplay.pp_handle; if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS)) { if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS) { @@ -6087,7 +6054,8 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CG, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_3D_CGCG | AMD_CG_SUPPORT_GFX_3D_CGLS)) { @@ -6106,7 +6074,8 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_3D, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_GFX_MGCG | AMD_CG_SUPPORT_GFX_MGLS)) { @@ -6127,7 +6096,8 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_MG, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_GFX_RLC_LS) { @@ -6142,7 +6112,8 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_RLC, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) { @@ -6156,7 +6127,8 @@ static int gfx_v8_0_polaris_update_gfx_clock_gating(struct amdgpu_device *adev, PP_BLOCK_GFX_CP, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; @@ -6423,6 +6395,104 @@ static void gfx_v8_0_ring_set_wptr_compute(struct amdgpu_ring *ring) WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr)); } +static void gfx_v8_0_ring_set_pipe_percent(struct amdgpu_ring *ring, + bool acquire) +{ + struct amdgpu_device *adev = ring->adev; + int pipe_num, tmp, reg; + int pipe_percent = acquire ? SPI_WCL_PIPE_PERCENT_GFX__VALUE_MASK : 0x1; + + pipe_num = ring->me * adev->gfx.mec.num_pipe_per_mec + ring->pipe; + + /* first me only has 2 entries, GFX and HP3D */ + if (ring->me > 0) + pipe_num -= 2; + + reg = mmSPI_WCL_PIPE_PERCENT_GFX + pipe_num; + tmp = RREG32(reg); + tmp = REG_SET_FIELD(tmp, SPI_WCL_PIPE_PERCENT_GFX, VALUE, pipe_percent); + WREG32(reg, tmp); +} + +static void gfx_v8_0_pipe_reserve_resources(struct amdgpu_device *adev, + struct amdgpu_ring *ring, + bool acquire) +{ + int i, pipe; + bool reserve; + struct amdgpu_ring *iring; + + mutex_lock(&adev->gfx.pipe_reserve_mutex); + pipe = amdgpu_gfx_queue_to_bit(adev, ring->me, ring->pipe, 0); + if (acquire) + set_bit(pipe, adev->gfx.pipe_reserve_bitmap); + else + clear_bit(pipe, adev->gfx.pipe_reserve_bitmap); + + if (!bitmap_weight(adev->gfx.pipe_reserve_bitmap, AMDGPU_MAX_COMPUTE_QUEUES)) { + /* Clear all reservations - everyone reacquires all resources */ + for (i = 0; i < adev->gfx.num_gfx_rings; ++i) + gfx_v8_0_ring_set_pipe_percent(&adev->gfx.gfx_ring[i], + true); + + for (i = 0; i < adev->gfx.num_compute_rings; ++i) + gfx_v8_0_ring_set_pipe_percent(&adev->gfx.compute_ring[i], + true); + } else { + /* Lower all pipes without a current reservation */ + for (i = 0; i < adev->gfx.num_gfx_rings; ++i) { + iring = &adev->gfx.gfx_ring[i]; + pipe = amdgpu_gfx_queue_to_bit(adev, + iring->me, + iring->pipe, + 0); + reserve = test_bit(pipe, adev->gfx.pipe_reserve_bitmap); + gfx_v8_0_ring_set_pipe_percent(iring, reserve); + } + + for (i = 0; i < adev->gfx.num_compute_rings; ++i) { + iring = &adev->gfx.compute_ring[i]; + pipe = amdgpu_gfx_queue_to_bit(adev, + iring->me, + iring->pipe, + 0); + reserve = test_bit(pipe, adev->gfx.pipe_reserve_bitmap); + gfx_v8_0_ring_set_pipe_percent(iring, reserve); + } + } + + mutex_unlock(&adev->gfx.pipe_reserve_mutex); +} + +static void gfx_v8_0_hqd_set_priority(struct amdgpu_device *adev, + struct amdgpu_ring *ring, + bool acquire) +{ + uint32_t pipe_priority = acquire ? 0x2 : 0x0; + uint32_t queue_priority = acquire ? 0xf : 0x0; + + mutex_lock(&adev->srbm_mutex); + vi_srbm_select(adev, ring->me, ring->pipe, ring->queue, 0); + + WREG32(mmCP_HQD_PIPE_PRIORITY, pipe_priority); + WREG32(mmCP_HQD_QUEUE_PRIORITY, queue_priority); + + vi_srbm_select(adev, 0, 0, 0, 0); + mutex_unlock(&adev->srbm_mutex); +} +static void gfx_v8_0_ring_set_priority_compute(struct amdgpu_ring *ring, + enum amd_sched_priority priority) +{ + struct amdgpu_device *adev = ring->adev; + bool acquire = priority == AMD_SCHED_PRIORITY_HIGH_HW; + + if (ring->funcs->type != AMDGPU_RING_TYPE_COMPUTE) + return; + + gfx_v8_0_hqd_set_priority(adev, ring, acquire); + gfx_v8_0_pipe_reserve_resources(adev, ring, acquire); +} + static void gfx_v8_0_ring_emit_fence_compute(struct amdgpu_ring *ring, u64 addr, u64 seq, unsigned flags) @@ -6868,6 +6938,7 @@ static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_compute = { .test_ib = gfx_v8_0_ring_test_ib, .insert_nop = amdgpu_ring_insert_nop, .pad_ib = amdgpu_ring_generic_pad_ib, + .set_priority = gfx_v8_0_ring_set_priority_compute, }; static const struct amdgpu_ring_funcs gfx_v8_0_ring_funcs_kiq = { @@ -7076,7 +7147,7 @@ static void gfx_v8_0_ring_emit_ce_meta(struct amdgpu_ring *ring) { uint64_t ce_payload_addr; int cnt_ce; - static union { + union { struct vi_ce_ib_state regular; struct vi_ce_ib_state_chained_ib chained; } ce_payload = {}; @@ -7105,7 +7176,7 @@ static void gfx_v8_0_ring_emit_de_meta(struct amdgpu_ring *ring) { uint64_t de_payload_addr, gds_addr, csa_addr; int cnt_de; - static union { + union { struct vi_de_ib_state regular; struct vi_de_ib_state_chained_ib chained; } de_payload = {}; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index deeaee1457ef..7f15bb2c5233 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -20,6 +20,7 @@ * OTHER DEALINGS IN THE SOFTWARE. * */ +#include <linux/kernel.h> #include <linux/firmware.h> #include <drm/drmP.h> #include "amdgpu.h" @@ -1730,10 +1731,10 @@ static int gfx_v9_0_init_rlc_save_restore_list(struct amdgpu_device *adev) adev->gfx.rlc.reg_list_format_size_bytes >> 2, unique_indirect_regs, &unique_indirect_reg_count, - sizeof(unique_indirect_regs)/sizeof(int), + ARRAY_SIZE(unique_indirect_regs), indirect_start_offsets, &indirect_start_offsets_count, - sizeof(indirect_start_offsets)/sizeof(int)); + ARRAY_SIZE(indirect_start_offsets)); /* enable auto inc in case it is disabled */ tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_CNTL)); @@ -1770,12 +1771,12 @@ static int gfx_v9_0_init_rlc_save_restore_list(struct amdgpu_device *adev) /* write the starting offsets to RLC scratch ram */ WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_SCRATCH_ADDR), adev->gfx.rlc.starting_offsets_start); - for (i = 0; i < sizeof(indirect_start_offsets)/sizeof(int); i++) + for (i = 0; i < ARRAY_SIZE(indirect_start_offsets); i++) WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_SCRATCH_DATA), indirect_start_offsets[i]); /* load unique indirect regs*/ - for (i = 0; i < sizeof(unique_indirect_regs)/sizeof(int); i++) { + for (i = 0; i < ARRAY_SIZE(unique_indirect_regs); i++) { WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_INDEX_CNTL_ADDR_0) + i, unique_indirect_regs[i] & 0x3FFFF); WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SRM_INDEX_CNTL_DATA_0) + i, @@ -3583,7 +3584,7 @@ static void gfx_v9_0_ring_set_wptr_gfx(struct amdgpu_ring *ring) static void gfx_v9_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 ref_and_mask, reg_mem_engine; - struct nbio_hdp_flush_reg *nbio_hf_reg; + const struct nbio_hdp_flush_reg *nbio_hf_reg; if (ring->adev->flags & AMD_IS_APU) nbio_hf_reg = &nbio_v7_0_hdp_flush_reg; @@ -3806,7 +3807,7 @@ static void gfx_v9_ring_emit_sb(struct amdgpu_ring *ring) static void gfx_v9_0_ring_emit_ce_meta(struct amdgpu_ring *ring) { - static struct v9_ce_ib_state ce_payload = {0}; + struct v9_ce_ib_state ce_payload = {0}; uint64_t csa_addr; int cnt; @@ -3825,7 +3826,7 @@ static void gfx_v9_0_ring_emit_ce_meta(struct amdgpu_ring *ring) static void gfx_v9_0_ring_emit_de_meta(struct amdgpu_ring *ring) { - static struct v9_de_ib_state de_payload = {0}; + struct v9_de_ib_state de_payload = {0}; uint64_t csa_addr, gds_addr; int cnt; diff --git a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c index 65ed6d3a8f05..bd592cb39f37 100644 --- a/drivers/gpu/drm/amd/amdgpu/iceland_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/iceland_ih.c @@ -216,8 +216,23 @@ static u32 iceland_ih_get_wptr(struct amdgpu_device *adev) */ static bool iceland_ih_prescreen_iv(struct amdgpu_device *adev) { - /* Process all interrupts */ - return true; + u32 ring_index = adev->irq.ih.rptr >> 2; + u16 pasid; + + switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { + case 146: + case 147: + pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; + if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) + return true; + break; + default: + /* Not a VM fault */ + return true; + } + + adev->irq.ih.rptr += 16; + return false; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c index b57399a462c2..f33d1ffdb20b 100644 --- a/drivers/gpu/drm/amd/amdgpu/kv_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/kv_dpm.c @@ -2969,16 +2969,10 @@ static int kv_dpm_late_init(void *handle) { /* powerdown unused blocks for now */ struct amdgpu_device *adev = (struct amdgpu_device *)handle; - int ret; if (!amdgpu_dpm) return 0; - /* init the sysfs and debugfs files late */ - ret = amdgpu_pm_sysfs_init(adev); - if (ret) - return ret; - kv_dpm_powergate_acp(adev, true); kv_dpm_powergate_samu(adev, true); @@ -3040,7 +3034,6 @@ static int kv_dpm_sw_fini(void *handle) flush_work(&adev->pm.dpm.thermal.work); mutex_lock(&adev->pm.mutex); - amdgpu_pm_sysfs_fini(adev); kv_dpm_fini(adev); mutex_unlock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c index 2812d88a8bdd..b4906d2f30d3 100644 --- a/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c +++ b/drivers/gpu/drm/amd/amdgpu/mxgpu_ai.c @@ -183,6 +183,12 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev, pr_err("Doesn't get READY_TO_ACCESS_GPU from pf, give up\n"); return r; } + /* Retrieve checksum from mailbox2 */ + if (req == IDH_REQ_GPU_INIT_ACCESS) { + adev->virt.fw_reserve.checksum_key = + RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0, + mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2)); + } } return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c index 045988b18bc3..904a1bab9b9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.c @@ -215,31 +215,27 @@ void nbio_v6_1_get_clockgating_state(struct amdgpu_device *adev, u32 *flags) *flags |= AMD_CG_SUPPORT_BIF_LS; } -struct nbio_hdp_flush_reg nbio_v6_1_hdp_flush_reg; -struct nbio_pcie_index_data nbio_v6_1_pcie_index_data; +const struct nbio_hdp_flush_reg nbio_v6_1_hdp_flush_reg = { + .hdp_flush_req_offset = SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_GPU_HDP_FLUSH_REQ), + .hdp_flush_done_offset = SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_GPU_HDP_FLUSH_DONE), + .ref_and_mask_cp0 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP0_MASK, + .ref_and_mask_cp1 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP1_MASK, + .ref_and_mask_cp2 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP2_MASK, + .ref_and_mask_cp3 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP3_MASK, + .ref_and_mask_cp4 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP4_MASK, + .ref_and_mask_cp5 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP5_MASK, + .ref_and_mask_cp6 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP6_MASK, + .ref_and_mask_cp7 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP7_MASK, + .ref_and_mask_cp8 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP8_MASK, + .ref_and_mask_cp9 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP9_MASK, + .ref_and_mask_sdma0 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__SDMA0_MASK, + .ref_and_mask_sdma1 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__SDMA1_MASK +}; -int nbio_v6_1_init(struct amdgpu_device *adev) -{ - nbio_v6_1_hdp_flush_reg.hdp_flush_req_offset = SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_GPU_HDP_FLUSH_REQ); - nbio_v6_1_hdp_flush_reg.hdp_flush_done_offset = SOC15_REG_OFFSET(NBIO, 0, mmBIF_BX_PF0_GPU_HDP_FLUSH_DONE); - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp0 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP0_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp1 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP1_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp2 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP2_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp3 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP3_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp4 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP4_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp5 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP5_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp6 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP6_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp7 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP7_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp8 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP8_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_cp9 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP9_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_sdma0 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__SDMA0_MASK; - nbio_v6_1_hdp_flush_reg.ref_and_mask_sdma1 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__SDMA1_MASK; - - nbio_v6_1_pcie_index_data.index_offset = SOC15_REG_OFFSET(NBIO, 0, mmPCIE_INDEX); - nbio_v6_1_pcie_index_data.data_offset = SOC15_REG_OFFSET(NBIO, 0, mmPCIE_DATA); - - return 0; -} +const struct nbio_pcie_index_data nbio_v6_1_pcie_index_data = { + .index_offset = SOC15_REG_OFFSET(NBIO, 0, mmPCIE_INDEX), + .data_offset = SOC15_REG_OFFSET(NBIO, 0, mmPCIE_DATA), +}; void nbio_v6_1_detect_hw_virt(struct amdgpu_device *adev) { diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h index 686e4b4d296a..14ca8d45a46c 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v6_1.h @@ -26,8 +26,8 @@ #include "soc15_common.h" -extern struct nbio_hdp_flush_reg nbio_v6_1_hdp_flush_reg; -extern struct nbio_pcie_index_data nbio_v6_1_pcie_index_data; +extern const struct nbio_hdp_flush_reg nbio_v6_1_hdp_flush_reg; +extern const struct nbio_pcie_index_data nbio_v6_1_pcie_index_data; int nbio_v6_1_init(struct amdgpu_device *adev); u32 nbio_v6_1_get_atombios_scratch_regs(struct amdgpu_device *adev, uint32_t idx); diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c index 11b70d601922..f802b973410a 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c @@ -185,28 +185,24 @@ void nbio_v7_0_ih_control(struct amdgpu_device *adev) WREG32_SOC15(NBIO, 0, mmINTERRUPT_CNTL, interrupt_cntl); } -struct nbio_hdp_flush_reg nbio_v7_0_hdp_flush_reg; -struct nbio_pcie_index_data nbio_v7_0_pcie_index_data; +const struct nbio_hdp_flush_reg nbio_v7_0_hdp_flush_reg = { + .hdp_flush_req_offset = SOC15_REG_OFFSET(NBIO, 0, mmGPU_HDP_FLUSH_REQ), + .hdp_flush_done_offset = SOC15_REG_OFFSET(NBIO, 0, mmGPU_HDP_FLUSH_DONE), + .ref_and_mask_cp0 = GPU_HDP_FLUSH_DONE__CP0_MASK, + .ref_and_mask_cp1 = GPU_HDP_FLUSH_DONE__CP1_MASK, + .ref_and_mask_cp2 = GPU_HDP_FLUSH_DONE__CP2_MASK, + .ref_and_mask_cp3 = GPU_HDP_FLUSH_DONE__CP3_MASK, + .ref_and_mask_cp4 = GPU_HDP_FLUSH_DONE__CP4_MASK, + .ref_and_mask_cp5 = GPU_HDP_FLUSH_DONE__CP5_MASK, + .ref_and_mask_cp6 = GPU_HDP_FLUSH_DONE__CP6_MASK, + .ref_and_mask_cp7 = GPU_HDP_FLUSH_DONE__CP7_MASK, + .ref_and_mask_cp8 = GPU_HDP_FLUSH_DONE__CP8_MASK, + .ref_and_mask_cp9 = GPU_HDP_FLUSH_DONE__CP9_MASK, + .ref_and_mask_sdma0 = GPU_HDP_FLUSH_DONE__SDMA0_MASK, + .ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__SDMA1_MASK, +}; -int nbio_v7_0_init(struct amdgpu_device *adev) -{ - nbio_v7_0_hdp_flush_reg.hdp_flush_req_offset = SOC15_REG_OFFSET(NBIO, 0, mmGPU_HDP_FLUSH_REQ); - nbio_v7_0_hdp_flush_reg.hdp_flush_done_offset = SOC15_REG_OFFSET(NBIO, 0, mmGPU_HDP_FLUSH_DONE); - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp0 = GPU_HDP_FLUSH_DONE__CP0_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp1 = GPU_HDP_FLUSH_DONE__CP1_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp2 = GPU_HDP_FLUSH_DONE__CP2_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp3 = GPU_HDP_FLUSH_DONE__CP3_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp4 = GPU_HDP_FLUSH_DONE__CP4_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp5 = GPU_HDP_FLUSH_DONE__CP5_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp6 = GPU_HDP_FLUSH_DONE__CP6_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp7 = GPU_HDP_FLUSH_DONE__CP7_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp8 = GPU_HDP_FLUSH_DONE__CP8_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_cp9 = GPU_HDP_FLUSH_DONE__CP9_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_sdma0 = GPU_HDP_FLUSH_DONE__SDMA0_MASK; - nbio_v7_0_hdp_flush_reg.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__SDMA1_MASK; - - nbio_v7_0_pcie_index_data.index_offset = SOC15_REG_OFFSET(NBIO, 0, mmPCIE_INDEX2); - nbio_v7_0_pcie_index_data.data_offset = SOC15_REG_OFFSET(NBIO, 0, mmPCIE_DATA2); - - return 0; -} +const struct nbio_pcie_index_data nbio_v7_0_pcie_index_data = { + .index_offset = SOC15_REG_OFFSET(NBIO, 0, mmPCIE_INDEX2), + .data_offset = SOC15_REG_OFFSET(NBIO, 0, mmPCIE_DATA2) +}; diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.h b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.h index 054ff49427e6..df8fa90f40d7 100644 --- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.h +++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.h @@ -26,8 +26,8 @@ #include "soc15_common.h" -extern struct nbio_hdp_flush_reg nbio_v7_0_hdp_flush_reg; -extern struct nbio_pcie_index_data nbio_v7_0_pcie_index_data; +extern const struct nbio_hdp_flush_reg nbio_v7_0_hdp_flush_reg; +extern const struct nbio_pcie_index_data nbio_v7_0_pcie_index_data; int nbio_v7_0_init(struct amdgpu_device *adev); u32 nbio_v7_0_get_atombios_scratch_regs(struct amdgpu_device *adev, uint32_t idx); diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c index dea7c909ca5f..4e20d91d5d50 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v10_0.c @@ -257,6 +257,9 @@ int psp_v10_0_cmd_submit(struct psp_context *psp, unsigned int psp_write_ptr_reg = 0; struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem; struct psp_ring *ring = &psp->km_ring; + struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem; + struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start + + ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1; struct amdgpu_device *adev = psp->adev; uint32_t ring_size_dw = ring->ring_size / 4; uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; @@ -266,9 +269,16 @@ int psp_v10_0_cmd_submit(struct psp_context *psp, /* Update KM RB frame pointer to new frame */ if ((psp_write_ptr_reg % ring_size_dw) == 0) - write_frame = ring->ring_mem; + write_frame = ring_buffer_start; else - write_frame = ring->ring_mem + (psp_write_ptr_reg / rb_frame_size_dw); + write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw); + /* Check invalid write_frame ptr address */ + if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) { + DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n", + ring_buffer_start, ring_buffer_end, write_frame); + DRM_ERROR("write_frame is pointing to address out of bounds\n"); + return -EINVAL; + } /* Initialize KM RB frame */ memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); diff --git a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c index cee5c396b277..c7bcfe8e286c 100644 --- a/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c +++ b/drivers/gpu/drm/amd/amdgpu/psp_v3_1.c @@ -367,6 +367,9 @@ int psp_v3_1_cmd_submit(struct psp_context *psp, unsigned int psp_write_ptr_reg = 0; struct psp_gfx_rb_frame * write_frame = psp->km_ring.ring_mem; struct psp_ring *ring = &psp->km_ring; + struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem; + struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start + + ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1; struct amdgpu_device *adev = psp->adev; uint32_t ring_size_dw = ring->ring_size / 4; uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4; @@ -378,9 +381,16 @@ int psp_v3_1_cmd_submit(struct psp_context *psp, /* write_frame ptr increments by size of rb_frame in bytes */ /* psp_write_ptr_reg increments by size of rb_frame in DWORDs */ if ((psp_write_ptr_reg % ring_size_dw) == 0) - write_frame = ring->ring_mem; + write_frame = ring_buffer_start; else - write_frame = ring->ring_mem + (psp_write_ptr_reg / rb_frame_size_dw); + write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw); + /* Check invalid write_frame ptr address */ + if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) { + DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n", + ring_buffer_start, ring_buffer_end, write_frame); + DRM_ERROR("write_frame is pointing to address out of bounds\n"); + return -EINVAL; + } /* Initialize KM RB frame */ memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame)); diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c index acdee3a4602c..67f375bfe452 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v2_4.c @@ -561,21 +561,11 @@ static int sdma_v2_4_start(struct amdgpu_device *adev) { int r; - if (!adev->pp_enabled) { - if (adev->firmware.load_type != AMDGPU_FW_LOAD_SMU) { - r = sdma_v2_4_load_microcode(adev); - if (r) - return r; - } else { - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_SDMA0); - if (r) - return -EINVAL; - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_SDMA1); - if (r) - return -EINVAL; - } + + if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { + r = sdma_v2_4_load_microcode(adev); + if (r) + return r; } /* halt the engine before programing */ diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 72f31cc7df00..6d06f8eb659f 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -819,23 +819,12 @@ static int sdma_v3_0_load_microcode(struct amdgpu_device *adev) */ static int sdma_v3_0_start(struct amdgpu_device *adev) { - int r, i; + int r; - if (!adev->pp_enabled) { - if (adev->firmware.load_type != AMDGPU_FW_LOAD_SMU) { - r = sdma_v3_0_load_microcode(adev); - if (r) - return r; - } else { - for (i = 0; i < adev->sdma.num_instances; i++) { - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - (i == 0) ? - AMDGPU_UCODE_ID_SDMA0 : - AMDGPU_UCODE_ID_SDMA1); - if (r) - return -EINVAL; - } - } + if (adev->firmware.load_type == AMDGPU_FW_LOAD_DIRECT) { + r = sdma_v3_0_load_microcode(adev); + if (r) + return r; } /* disable sdma engine before programing it */ diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c index c26d205ff3bf..46009db3d195 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c @@ -371,7 +371,7 @@ static void sdma_v4_0_ring_emit_ib(struct amdgpu_ring *ring, static void sdma_v4_0_ring_emit_hdp_flush(struct amdgpu_ring *ring) { u32 ref_and_mask = 0; - struct nbio_hdp_flush_reg *nbio_hf_reg; + const struct nbio_hdp_flush_reg *nbio_hf_reg; if (ring->adev->flags & AMD_IS_APU) nbio_hf_reg = &nbio_v7_0_hdp_flush_reg; diff --git a/drivers/gpu/drm/amd/amdgpu/si_dpm.c b/drivers/gpu/drm/amd/amdgpu/si_dpm.c index 9b8db6046271..51fd0c9a20a5 100644 --- a/drivers/gpu/drm/amd/amdgpu/si_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/si_dpm.c @@ -7604,11 +7604,6 @@ static int si_dpm_late_init(void *handle) if (!amdgpu_dpm) return 0; - /* init the sysfs and debugfs files late */ - ret = amdgpu_pm_sysfs_init(adev); - if (ret) - return ret; - ret = si_set_temperature_range(adev); if (ret) return ret; @@ -7764,7 +7759,6 @@ static int si_dpm_sw_fini(void *handle) flush_work(&adev->pm.dpm.thermal.work); mutex_lock(&adev->pm.mutex); - amdgpu_pm_sysfs_fini(adev); si_dpm_fini(adev); mutex_unlock(&adev->pm.mutex); diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index 245a18aeb389..3ca9d114f630 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -101,7 +101,7 @@ static u32 soc15_pcie_rreg(struct amdgpu_device *adev, u32 reg) { unsigned long flags, address, data; u32 r; - struct nbio_pcie_index_data *nbio_pcie_id; + const struct nbio_pcie_index_data *nbio_pcie_id; if (adev->flags & AMD_IS_APU) nbio_pcie_id = &nbio_v7_0_pcie_index_data; @@ -122,7 +122,7 @@ static u32 soc15_pcie_rreg(struct amdgpu_device *adev, u32 reg) static void soc15_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v) { unsigned long flags, address, data; - struct nbio_pcie_index_data *nbio_pcie_id; + const struct nbio_pcie_index_data *nbio_pcie_id; if (adev->flags & AMD_IS_APU) nbio_pcie_id = &nbio_v7_0_pcie_index_data; @@ -279,10 +279,7 @@ static void soc15_init_golden_registers(struct amdgpu_device *adev) } static u32 soc15_get_xclk(struct amdgpu_device *adev) { - if (adev->asic_type == CHIP_VEGA10) - return adev->clock.spll.reference_freq/4; - else - return adev->clock.spll.reference_freq; + return adev->clock.spll.reference_freq; } @@ -604,21 +601,6 @@ static int soc15_common_early_init(void *handle) (amdgpu_ip_block_mask & (1 << AMD_IP_BLOCK_TYPE_PSP))) psp_enabled = true; - /* - * nbio need be used for both sdma and gfx9, but only - * initializes once - */ - switch(adev->asic_type) { - case CHIP_VEGA10: - nbio_v6_1_init(adev); - break; - case CHIP_RAVEN: - nbio_v7_0_init(adev); - break; - default: - return -EINVAL; - } - adev->rev_id = soc15_get_rev_id(adev); adev->external_rev_id = 0xFF; switch (adev->asic_type) { diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c index 5ed00692618e..aa4e320e31f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_ih.c @@ -227,8 +227,23 @@ static u32 tonga_ih_get_wptr(struct amdgpu_device *adev) */ static bool tonga_ih_prescreen_iv(struct amdgpu_device *adev) { - /* Process all interrupts */ - return true; + u32 ring_index = adev->irq.ih.rptr >> 2; + u16 pasid; + + switch (le32_to_cpu(adev->irq.ih.ring[ring_index]) & 0xff) { + case 146: + case 147: + pasid = le32_to_cpu(adev->irq.ih.ring[ring_index + 2]) >> 16; + if (!pasid || amdgpu_vm_pasid_fault_credit(adev, pasid)) + return true; + break; + default: + /* Not a VM fault */ + return true; + } + + adev->irq.ih.rptr += 16; + return false; } /** diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 31db356476f8..2581543b35a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -38,6 +38,8 @@ #include "vi.h" static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev); +static void uvd_v6_0_set_enc_ring_funcs(struct amdgpu_device *adev); + static void uvd_v6_0_set_irq_funcs(struct amdgpu_device *adev); static int uvd_v6_0_start(struct amdgpu_device *adev); static void uvd_v6_0_stop(struct amdgpu_device *adev); @@ -48,6 +50,18 @@ static void uvd_v6_0_enable_mgcg(struct amdgpu_device *adev, bool enable); /** +* uvd_v6_0_enc_support - get encode support status +* +* @adev: amdgpu_device pointer +* +* Returns the current hardware encode support status +*/ +static inline bool uvd_v6_0_enc_support(struct amdgpu_device *adev) +{ + return ((adev->asic_type >= CHIP_POLARIS10) && (adev->asic_type <= CHIP_POLARIS12)); +} + +/** * uvd_v6_0_ring_get_rptr - get read pointer * * @ring: amdgpu_ring pointer @@ -62,6 +76,22 @@ static uint64_t uvd_v6_0_ring_get_rptr(struct amdgpu_ring *ring) } /** + * uvd_v6_0_enc_ring_get_rptr - get enc read pointer + * + * @ring: amdgpu_ring pointer + * + * Returns the current hardware enc read pointer + */ +static uint64_t uvd_v6_0_enc_ring_get_rptr(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + + if (ring == &adev->uvd.ring_enc[0]) + return RREG32(mmUVD_RB_RPTR); + else + return RREG32(mmUVD_RB_RPTR2); +} +/** * uvd_v6_0_ring_get_wptr - get write pointer * * @ring: amdgpu_ring pointer @@ -76,6 +106,23 @@ static uint64_t uvd_v6_0_ring_get_wptr(struct amdgpu_ring *ring) } /** + * uvd_v6_0_enc_ring_get_wptr - get enc write pointer + * + * @ring: amdgpu_ring pointer + * + * Returns the current hardware enc write pointer + */ +static uint64_t uvd_v6_0_enc_ring_get_wptr(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + + if (ring == &adev->uvd.ring_enc[0]) + return RREG32(mmUVD_RB_WPTR); + else + return RREG32(mmUVD_RB_WPTR2); +} + +/** * uvd_v6_0_ring_set_wptr - set write pointer * * @ring: amdgpu_ring pointer @@ -89,11 +136,248 @@ static void uvd_v6_0_ring_set_wptr(struct amdgpu_ring *ring) WREG32(mmUVD_RBC_RB_WPTR, lower_32_bits(ring->wptr)); } +/** + * uvd_v6_0_enc_ring_set_wptr - set enc write pointer + * + * @ring: amdgpu_ring pointer + * + * Commits the enc write pointer to the hardware + */ +static void uvd_v6_0_enc_ring_set_wptr(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + + if (ring == &adev->uvd.ring_enc[0]) + WREG32(mmUVD_RB_WPTR, + lower_32_bits(ring->wptr)); + else + WREG32(mmUVD_RB_WPTR2, + lower_32_bits(ring->wptr)); +} + +/** + * uvd_v6_0_enc_ring_test_ring - test if UVD ENC ring is working + * + * @ring: the engine to test on + * + */ +static int uvd_v6_0_enc_ring_test_ring(struct amdgpu_ring *ring) +{ + struct amdgpu_device *adev = ring->adev; + uint32_t rptr = amdgpu_ring_get_rptr(ring); + unsigned i; + int r; + + r = amdgpu_ring_alloc(ring, 16); + if (r) { + DRM_ERROR("amdgpu: uvd enc failed to lock ring %d (%d).\n", + ring->idx, r); + return r; + } + amdgpu_ring_write(ring, HEVC_ENC_CMD_END); + amdgpu_ring_commit(ring); + + for (i = 0; i < adev->usec_timeout; i++) { + if (amdgpu_ring_get_rptr(ring) != rptr) + break; + DRM_UDELAY(1); + } + + if (i < adev->usec_timeout) { + DRM_INFO("ring test on %d succeeded in %d usecs\n", + ring->idx, i); + } else { + DRM_ERROR("amdgpu: ring %d test failed\n", + ring->idx); + r = -ETIMEDOUT; + } + + return r; +} + +/** + * uvd_v6_0_enc_get_create_msg - generate a UVD ENC create msg + * + * @adev: amdgpu_device pointer + * @ring: ring we should submit the msg to + * @handle: session handle to use + * @fence: optional fence to return + * + * Open up a stream for HW test + */ +static int uvd_v6_0_enc_get_create_msg(struct amdgpu_ring *ring, uint32_t handle, + struct dma_fence **fence) +{ + const unsigned ib_size_dw = 16; + struct amdgpu_job *job; + struct amdgpu_ib *ib; + struct dma_fence *f = NULL; + uint64_t dummy; + int i, r; + + r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); + if (r) + return r; + + ib = &job->ibs[0]; + dummy = ib->gpu_addr + 1024; + + ib->length_dw = 0; + ib->ptr[ib->length_dw++] = 0x00000018; + ib->ptr[ib->length_dw++] = 0x00000001; /* session info */ + ib->ptr[ib->length_dw++] = handle; + ib->ptr[ib->length_dw++] = 0x00010000; + ib->ptr[ib->length_dw++] = upper_32_bits(dummy); + ib->ptr[ib->length_dw++] = dummy; + + ib->ptr[ib->length_dw++] = 0x00000014; + ib->ptr[ib->length_dw++] = 0x00000002; /* task info */ + ib->ptr[ib->length_dw++] = 0x0000001c; + ib->ptr[ib->length_dw++] = 0x00000001; + ib->ptr[ib->length_dw++] = 0x00000000; + + ib->ptr[ib->length_dw++] = 0x00000008; + ib->ptr[ib->length_dw++] = 0x08000001; /* op initialize */ + + for (i = ib->length_dw; i < ib_size_dw; ++i) + ib->ptr[i] = 0x0; + + r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f); + job->fence = dma_fence_get(f); + if (r) + goto err; + + amdgpu_job_free(job); + if (fence) + *fence = dma_fence_get(f); + dma_fence_put(f); + return 0; + +err: + amdgpu_job_free(job); + return r; +} + +/** + * uvd_v6_0_enc_get_destroy_msg - generate a UVD ENC destroy msg + * + * @adev: amdgpu_device pointer + * @ring: ring we should submit the msg to + * @handle: session handle to use + * @fence: optional fence to return + * + * Close up a stream for HW test or if userspace failed to do so + */ +static int uvd_v6_0_enc_get_destroy_msg(struct amdgpu_ring *ring, + uint32_t handle, + bool direct, struct dma_fence **fence) +{ + const unsigned ib_size_dw = 16; + struct amdgpu_job *job; + struct amdgpu_ib *ib; + struct dma_fence *f = NULL; + uint64_t dummy; + int i, r; + + r = amdgpu_job_alloc_with_ib(ring->adev, ib_size_dw * 4, &job); + if (r) + return r; + + ib = &job->ibs[0]; + dummy = ib->gpu_addr + 1024; + + ib->length_dw = 0; + ib->ptr[ib->length_dw++] = 0x00000018; + ib->ptr[ib->length_dw++] = 0x00000001; /* session info */ + ib->ptr[ib->length_dw++] = handle; + ib->ptr[ib->length_dw++] = 0x00010000; + ib->ptr[ib->length_dw++] = upper_32_bits(dummy); + ib->ptr[ib->length_dw++] = dummy; + + ib->ptr[ib->length_dw++] = 0x00000014; + ib->ptr[ib->length_dw++] = 0x00000002; /* task info */ + ib->ptr[ib->length_dw++] = 0x0000001c; + ib->ptr[ib->length_dw++] = 0x00000001; + ib->ptr[ib->length_dw++] = 0x00000000; + + ib->ptr[ib->length_dw++] = 0x00000008; + ib->ptr[ib->length_dw++] = 0x08000002; /* op close session */ + + for (i = ib->length_dw; i < ib_size_dw; ++i) + ib->ptr[i] = 0x0; + + if (direct) { + r = amdgpu_ib_schedule(ring, 1, ib, NULL, &f); + job->fence = dma_fence_get(f); + if (r) + goto err; + + amdgpu_job_free(job); + } else { + r = amdgpu_job_submit(job, ring, &ring->adev->vce.entity, + AMDGPU_FENCE_OWNER_UNDEFINED, &f); + if (r) + goto err; + } + + if (fence) + *fence = dma_fence_get(f); + dma_fence_put(f); + return 0; + +err: + amdgpu_job_free(job); + return r; +} + +/** + * uvd_v6_0_enc_ring_test_ib - test if UVD ENC IBs are working + * + * @ring: the engine to test on + * + */ +static int uvd_v6_0_enc_ring_test_ib(struct amdgpu_ring *ring, long timeout) +{ + struct dma_fence *fence = NULL; + long r; + + r = uvd_v6_0_enc_get_create_msg(ring, 1, NULL); + if (r) { + DRM_ERROR("amdgpu: failed to get create msg (%ld).\n", r); + goto error; + } + + r = uvd_v6_0_enc_get_destroy_msg(ring, 1, true, &fence); + if (r) { + DRM_ERROR("amdgpu: failed to get destroy ib (%ld).\n", r); + goto error; + } + + r = dma_fence_wait_timeout(fence, false, timeout); + if (r == 0) { + DRM_ERROR("amdgpu: IB test timed out.\n"); + r = -ETIMEDOUT; + } else if (r < 0) { + DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r); + } else { + DRM_INFO("ib test on ring %d succeeded\n", ring->idx); + r = 0; + } +error: + dma_fence_put(fence); + return r; +} static int uvd_v6_0_early_init(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; uvd_v6_0_set_ring_funcs(adev); + + if (uvd_v6_0_enc_support(adev)) { + adev->uvd.num_enc_rings = 2; + uvd_v6_0_set_enc_ring_funcs(adev); + } + uvd_v6_0_set_irq_funcs(adev); return 0; @@ -102,7 +386,7 @@ static int uvd_v6_0_early_init(void *handle) static int uvd_v6_0_sw_init(void *handle) { struct amdgpu_ring *ring; - int r; + int i, r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; /* UVD TRAP */ @@ -110,10 +394,31 @@ static int uvd_v6_0_sw_init(void *handle) if (r) return r; + /* UVD ENC TRAP */ + if (uvd_v6_0_enc_support(adev)) { + for (i = 0; i < adev->uvd.num_enc_rings; ++i) { + r = amdgpu_irq_add_id(adev, AMDGPU_IH_CLIENTID_LEGACY, i + 119, &adev->uvd.irq); + if (r) + return r; + } + } + r = amdgpu_uvd_sw_init(adev); if (r) return r; + if (uvd_v6_0_enc_support(adev)) { + struct amd_sched_rq *rq; + ring = &adev->uvd.ring_enc[0]; + rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_NORMAL]; + r = amd_sched_entity_init(&ring->sched, &adev->uvd.entity_enc, + rq, amdgpu_sched_jobs); + if (r) { + DRM_ERROR("Failed setting up UVD ENC run queue.\n"); + return r; + } + } + r = amdgpu_uvd_resume(adev); if (r) return r; @@ -121,19 +426,38 @@ static int uvd_v6_0_sw_init(void *handle) ring = &adev->uvd.ring; sprintf(ring->name, "uvd"); r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0); + if (r) + return r; + + if (uvd_v6_0_enc_support(adev)) { + for (i = 0; i < adev->uvd.num_enc_rings; ++i) { + ring = &adev->uvd.ring_enc[i]; + sprintf(ring->name, "uvd_enc%d", i); + r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0); + if (r) + return r; + } + } return r; } static int uvd_v6_0_sw_fini(void *handle) { - int r; + int i, r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; r = amdgpu_uvd_suspend(adev); if (r) return r; + if (uvd_v6_0_enc_support(adev)) { + amd_sched_entity_fini(&adev->uvd.ring_enc[0].sched, &adev->uvd.entity_enc); + + for (i = 0; i < adev->uvd.num_enc_rings; ++i) + amdgpu_ring_fini(&adev->uvd.ring_enc[i]); + } + return amdgpu_uvd_sw_fini(adev); } @@ -149,7 +473,7 @@ static int uvd_v6_0_hw_init(void *handle) struct amdgpu_device *adev = (struct amdgpu_device *)handle; struct amdgpu_ring *ring = &adev->uvd.ring; uint32_t tmp; - int r; + int i, r; amdgpu_asic_set_uvd_clocks(adev, 10000, 10000); uvd_v6_0_set_clockgating_state(adev, AMD_CG_STATE_UNGATE); @@ -189,9 +513,25 @@ static int uvd_v6_0_hw_init(void *handle) amdgpu_ring_commit(ring); + if (uvd_v6_0_enc_support(adev)) { + for (i = 0; i < adev->uvd.num_enc_rings; ++i) { + ring = &adev->uvd.ring_enc[i]; + ring->ready = true; + r = amdgpu_ring_test_ring(ring); + if (r) { + ring->ready = false; + goto done; + } + } + } + done: - if (!r) - DRM_INFO("UVD initialized successfully.\n"); + if (!r) { + if (uvd_v6_0_enc_support(adev)) + DRM_INFO("UVD and UVD ENC initialized successfully.\n"); + else + DRM_INFO("UVD initialized successfully.\n"); + } return r; } @@ -225,11 +565,7 @@ static int uvd_v6_0_suspend(void *handle) if (r) return r; - /* Skip this for APU for now */ - if (!(adev->flags & AMD_IS_APU)) - r = amdgpu_uvd_suspend(adev); - - return r; + return amdgpu_uvd_suspend(adev); } static int uvd_v6_0_resume(void *handle) @@ -237,12 +573,10 @@ static int uvd_v6_0_resume(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - /* Skip this for APU for now */ - if (!(adev->flags & AMD_IS_APU)) { - r = amdgpu_uvd_resume(adev); - if (r) - return r; - } + r = amdgpu_uvd_resume(adev); + if (r) + return r; + return uvd_v6_0_hw_init(adev); } @@ -514,6 +848,22 @@ static int uvd_v6_0_start(struct amdgpu_device *adev) WREG32_FIELD(UVD_RBC_RB_CNTL, RB_NO_FETCH, 0); + if (uvd_v6_0_enc_support(adev)) { + ring = &adev->uvd.ring_enc[0]; + WREG32(mmUVD_RB_RPTR, lower_32_bits(ring->wptr)); + WREG32(mmUVD_RB_WPTR, lower_32_bits(ring->wptr)); + WREG32(mmUVD_RB_BASE_LO, ring->gpu_addr); + WREG32(mmUVD_RB_BASE_HI, upper_32_bits(ring->gpu_addr)); + WREG32(mmUVD_RB_SIZE, ring->ring_size / 4); + + ring = &adev->uvd.ring_enc[1]; + WREG32(mmUVD_RB_RPTR2, lower_32_bits(ring->wptr)); + WREG32(mmUVD_RB_WPTR2, lower_32_bits(ring->wptr)); + WREG32(mmUVD_RB_BASE_LO2, ring->gpu_addr); + WREG32(mmUVD_RB_BASE_HI2, upper_32_bits(ring->gpu_addr)); + WREG32(mmUVD_RB_SIZE2, ring->ring_size / 4); + } + return 0; } @@ -577,6 +927,26 @@ static void uvd_v6_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 seq } /** + * uvd_v6_0_enc_ring_emit_fence - emit an enc fence & trap command + * + * @ring: amdgpu_ring pointer + * @fence: fence to emit + * + * Write enc a fence and a trap command to the ring. + */ +static void uvd_v6_0_enc_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, + u64 seq, unsigned flags) +{ + WARN_ON(flags & AMDGPU_FENCE_FLAG_64BIT); + + amdgpu_ring_write(ring, HEVC_ENC_CMD_FENCE); + amdgpu_ring_write(ring, addr); + amdgpu_ring_write(ring, upper_32_bits(addr)); + amdgpu_ring_write(ring, seq); + amdgpu_ring_write(ring, HEVC_ENC_CMD_TRAP); +} + +/** * uvd_v6_0_ring_emit_hdp_flush - emit an hdp flush * * @ring: amdgpu_ring pointer @@ -667,6 +1037,24 @@ static void uvd_v6_0_ring_emit_ib(struct amdgpu_ring *ring, amdgpu_ring_write(ring, ib->length_dw); } +/** + * uvd_v6_0_enc_ring_emit_ib - enc execute indirect buffer + * + * @ring: amdgpu_ring pointer + * @ib: indirect buffer to execute + * + * Write enc ring commands to execute the indirect buffer + */ +static void uvd_v6_0_enc_ring_emit_ib(struct amdgpu_ring *ring, + struct amdgpu_ib *ib, unsigned int vm_id, bool ctx_switch) +{ + amdgpu_ring_write(ring, HEVC_ENC_CMD_IB_VM); + amdgpu_ring_write(ring, vm_id); + amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr)); + amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr)); + amdgpu_ring_write(ring, ib->length_dw); +} + static void uvd_v6_0_ring_emit_vm_flush(struct amdgpu_ring *ring, unsigned vm_id, uint64_t pd_addr) { @@ -718,6 +1106,33 @@ static void uvd_v6_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring) amdgpu_ring_write(ring, 0xE); } +static void uvd_v6_0_enc_ring_emit_pipeline_sync(struct amdgpu_ring *ring) +{ + uint32_t seq = ring->fence_drv.sync_seq; + uint64_t addr = ring->fence_drv.gpu_addr; + + amdgpu_ring_write(ring, HEVC_ENC_CMD_WAIT_GE); + amdgpu_ring_write(ring, lower_32_bits(addr)); + amdgpu_ring_write(ring, upper_32_bits(addr)); + amdgpu_ring_write(ring, seq); +} + +static void uvd_v6_0_enc_ring_insert_end(struct amdgpu_ring *ring) +{ + amdgpu_ring_write(ring, HEVC_ENC_CMD_END); +} + +static void uvd_v6_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring, + unsigned int vm_id, uint64_t pd_addr) +{ + amdgpu_ring_write(ring, HEVC_ENC_CMD_UPDATE_PTB); + amdgpu_ring_write(ring, vm_id); + amdgpu_ring_write(ring, pd_addr >> 12); + + amdgpu_ring_write(ring, HEVC_ENC_CMD_FLUSH_TLB); + amdgpu_ring_write(ring, vm_id); +} + static bool uvd_v6_0_is_idle(void *handle) { struct amdgpu_device *adev = (struct amdgpu_device *)handle; @@ -825,8 +1240,31 @@ static int uvd_v6_0_process_interrupt(struct amdgpu_device *adev, struct amdgpu_irq_src *source, struct amdgpu_iv_entry *entry) { + bool int_handled = true; DRM_DEBUG("IH: UVD TRAP\n"); - amdgpu_fence_process(&adev->uvd.ring); + + switch (entry->src_id) { + case 124: + amdgpu_fence_process(&adev->uvd.ring); + break; + case 119: + if (likely(uvd_v6_0_enc_support(adev))) + amdgpu_fence_process(&adev->uvd.ring_enc[0]); + else + int_handled = false; + break; + case 120: + if (likely(uvd_v6_0_enc_support(adev))) + amdgpu_fence_process(&adev->uvd.ring_enc[1]); + else + int_handled = false; + break; + } + + if (false == int_handled) + DRM_ERROR("Unhandled interrupt: %d %d\n", + entry->src_id, entry->src_data[0]); + return 0; } @@ -1153,6 +1591,33 @@ static const struct amdgpu_ring_funcs uvd_v6_0_ring_vm_funcs = { .end_use = amdgpu_uvd_ring_end_use, }; +static const struct amdgpu_ring_funcs uvd_v6_0_enc_ring_vm_funcs = { + .type = AMDGPU_RING_TYPE_UVD_ENC, + .align_mask = 0x3f, + .nop = HEVC_ENC_CMD_NO_OP, + .support_64bit_ptrs = false, + .get_rptr = uvd_v6_0_enc_ring_get_rptr, + .get_wptr = uvd_v6_0_enc_ring_get_wptr, + .set_wptr = uvd_v6_0_enc_ring_set_wptr, + .emit_frame_size = + 4 + /* uvd_v6_0_enc_ring_emit_pipeline_sync */ + 6 + /* uvd_v6_0_enc_ring_emit_vm_flush */ + 5 + 5 + /* uvd_v6_0_enc_ring_emit_fence x2 vm fence */ + 1, /* uvd_v6_0_enc_ring_insert_end */ + .emit_ib_size = 5, /* uvd_v6_0_enc_ring_emit_ib */ + .emit_ib = uvd_v6_0_enc_ring_emit_ib, + .emit_fence = uvd_v6_0_enc_ring_emit_fence, + .emit_vm_flush = uvd_v6_0_enc_ring_emit_vm_flush, + .emit_pipeline_sync = uvd_v6_0_enc_ring_emit_pipeline_sync, + .test_ring = uvd_v6_0_enc_ring_test_ring, + .test_ib = uvd_v6_0_enc_ring_test_ib, + .insert_nop = amdgpu_ring_insert_nop, + .insert_end = uvd_v6_0_enc_ring_insert_end, + .pad_ib = amdgpu_ring_generic_pad_ib, + .begin_use = amdgpu_uvd_ring_begin_use, + .end_use = amdgpu_uvd_ring_end_use, +}; + static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev) { if (adev->asic_type >= CHIP_POLARIS10) { @@ -1164,6 +1629,16 @@ static void uvd_v6_0_set_ring_funcs(struct amdgpu_device *adev) } } +static void uvd_v6_0_set_enc_ring_funcs(struct amdgpu_device *adev) +{ + int i; + + for (i = 0; i < adev->uvd.num_enc_rings; ++i) + adev->uvd.ring_enc[i].funcs = &uvd_v6_0_enc_ring_vm_funcs; + + DRM_INFO("UVD ENC is enabled in VM mode\n"); +} + static const struct amdgpu_irq_src_funcs uvd_v6_0_irq_funcs = { .set = uvd_v6_0_set_interrupt_state, .process = uvd_v6_0_process_interrupt, @@ -1171,7 +1646,11 @@ static const struct amdgpu_irq_src_funcs uvd_v6_0_irq_funcs = { static void uvd_v6_0_set_irq_funcs(struct amdgpu_device *adev) { - adev->uvd.irq.num_types = 1; + if (uvd_v6_0_enc_support(adev)) + adev->uvd.irq.num_types = adev->uvd.num_enc_rings + 1; + else + adev->uvd.irq.num_types = 1; + adev->uvd.irq.funcs = &uvd_v6_0_irq_funcs; } diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c index b8ed8faf2003..6634545060fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c @@ -592,11 +592,7 @@ static int uvd_v7_0_suspend(void *handle) if (r) return r; - /* Skip this for APU for now */ - if (!(adev->flags & AMD_IS_APU)) - r = amdgpu_uvd_suspend(adev); - - return r; + return amdgpu_uvd_suspend(adev); } static int uvd_v7_0_resume(void *handle) @@ -604,12 +600,10 @@ static int uvd_v7_0_resume(void *handle) int r; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - /* Skip this for APU for now */ - if (!(adev->flags & AMD_IS_APU)) { - r = amdgpu_uvd_resume(adev); - if (r) - return r; - } + r = amdgpu_uvd_resume(adev); + if (r) + return r; + return uvd_v7_0_hw_init(adev); } diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c index a3b30d84dbb3..697325737ba8 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c @@ -260,15 +260,18 @@ static bool vega10_ih_prescreen_iv(struct amdgpu_device *adev) return true; } - /* Not a retry fault */ - if (!(dw5 & 0x80)) - return true; - pasid = dw3 & 0xffff; /* No PASID, can't identify faulting process */ if (!pasid) return true; + /* Not a retry fault, check fault credit */ + if (!(dw5 & 0x80)) { + if (!amdgpu_vm_pasid_fault_credit(adev, pasid)) + goto ignore_iv; + return true; + } + addr = ((u64)(dw5 & 0xf) << 44) | ((u64)dw4 << 12); key = AMDGPU_VM_FAULT(pasid, addr); r = amdgpu_ih_add_fault(adev, key); diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 9ff69b90df36..f3cfef48aa99 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1254,7 +1254,6 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, uint32_t msg_id, pp_state = 0; uint32_t pp_support_state = 0; struct amdgpu_device *adev = (struct amdgpu_device *)handle; - void *pp_handle = adev->powerplay.pp_handle; if (adev->cg_flags & (AMD_CG_SUPPORT_MC_LS | AMD_CG_SUPPORT_MC_MGCG)) { if (adev->cg_flags & AMD_CG_SUPPORT_MC_LS) { @@ -1271,7 +1270,8 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_MC, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_SDMA_LS | AMD_CG_SUPPORT_SDMA_MGCG)) { @@ -1289,7 +1289,8 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_SDMA, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_MGCG)) { @@ -1307,7 +1308,8 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_HDP, pp_support_state, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } @@ -1321,7 +1323,8 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_BIF, PP_STATE_SUPPORT_LS, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_BIF_MGCG) { if (state == AMD_CG_STATE_UNGATE) @@ -1333,7 +1336,8 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_BIF, PP_STATE_SUPPORT_CG, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_DRM_LS) { @@ -1347,7 +1351,8 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_DRM, PP_STATE_SUPPORT_LS, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } if (adev->cg_flags & AMD_CG_SUPPORT_ROM_MGCG) { @@ -1361,7 +1366,8 @@ static int vi_common_set_clockgating_state_by_smu(void *handle, PP_BLOCK_SYS_ROM, PP_STATE_SUPPORT_CG, pp_state); - amd_set_clockgating_by_smu(pp_handle, msg_id); + if (adev->powerplay.pp_funcs->set_clockgating_by_smu) + amdgpu_dpm_set_clockgating_by_smu(adev, msg_id); } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/vid.h b/drivers/gpu/drm/amd/amdgpu/vid.h index a6485254a169..dbf3703cbd1b 100644 --- a/drivers/gpu/drm/amd/amdgpu/vid.h +++ b/drivers/gpu/drm/amd/amdgpu/vid.h @@ -465,6 +465,16 @@ #define VCE_CMD_UPDATE_PTB 0x00000107 #define VCE_CMD_FLUSH_TLB 0x00000108 +/* HEVC ENC */ +#define HEVC_ENC_CMD_NO_OP 0x00000000 +#define HEVC_ENC_CMD_END 0x00000001 +#define HEVC_ENC_CMD_FENCE 0x00000003 +#define HEVC_ENC_CMD_TRAP 0x00000004 +#define HEVC_ENC_CMD_IB_VM 0x00000102 +#define HEVC_ENC_CMD_WAIT_GE 0x00000106 +#define HEVC_ENC_CMD_UPDATE_PTB 0x00000107 +#define HEVC_ENC_CMD_FLUSH_TLB 0x00000108 + /* mmPA_SC_RASTER_CONFIG mask */ #define RB_MAP_PKR0(x) ((x) << 0) #define RB_MAP_PKR0_MASK (0x3 << 0) diff --git a/drivers/gpu/drm/amd/amdkfd/Kconfig b/drivers/gpu/drm/amd/amdkfd/Kconfig index e13c67c8d2c0..bc5a2945bd2b 100644 --- a/drivers/gpu/drm/amd/amdkfd/Kconfig +++ b/drivers/gpu/drm/amd/amdkfd/Kconfig @@ -4,6 +4,6 @@ config HSA_AMD tristate "HSA kernel driver for AMD GPU devices" - depends on (DRM_RADEON || DRM_AMDGPU) && AMD_IOMMU_V2 && X86_64 + depends on DRM_AMDGPU && AMD_IOMMU_V2 && X86_64 help Enable this if you want to use HSA features on AMD GPU devices. diff --git a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c index 211fc48697fa..3d5ccb3755d4 100644 --- a/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c +++ b/drivers/gpu/drm/amd/amdkfd/cik_event_interrupt.c @@ -36,6 +36,7 @@ static bool cik_event_interrupt_isr(struct kfd_dev *dev, /* Do not process in ISR, just request it to be forwarded to WQ. */ return (pasid != 0) && (ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE || + ihre->source_id == CIK_INTSRC_SDMA_TRAP || ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG || ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE); } @@ -46,6 +47,7 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev, unsigned int pasid; const struct cik_ih_ring_entry *ihre = (const struct cik_ih_ring_entry *)ih_ring_entry; + uint32_t context_id = ihre->data & 0xfffffff; pasid = (ihre->ring_id & 0xffff0000) >> 16; @@ -53,9 +55,11 @@ static void cik_event_interrupt_wq(struct kfd_dev *dev, return; if (ihre->source_id == CIK_INTSRC_CP_END_OF_PIPE) - kfd_signal_event_interrupt(pasid, 0, 0); + kfd_signal_event_interrupt(pasid, context_id, 28); + else if (ihre->source_id == CIK_INTSRC_SDMA_TRAP) + kfd_signal_event_interrupt(pasid, context_id, 28); else if (ihre->source_id == CIK_INTSRC_SQ_INTERRUPT_MSG) - kfd_signal_event_interrupt(pasid, ihre->data & 0xFF, 8); + kfd_signal_event_interrupt(pasid, context_id & 0xff, 8); else if (ihre->source_id == CIK_INTSRC_CP_BAD_OPCODE) kfd_signal_hw_exception_event(pasid); } diff --git a/drivers/gpu/drm/amd/amdkfd/cik_int.h b/drivers/gpu/drm/amd/amdkfd/cik_int.h index 79a16d24c1b8..109298b9d507 100644 --- a/drivers/gpu/drm/amd/amdkfd/cik_int.h +++ b/drivers/gpu/drm/amd/amdkfd/cik_int.h @@ -32,9 +32,10 @@ struct cik_ih_ring_entry { uint32_t reserved; }; -#define CIK_INTSRC_DEQUEUE_COMPLETE 0xC6 #define CIK_INTSRC_CP_END_OF_PIPE 0xB5 #define CIK_INTSRC_CP_BAD_OPCODE 0xB7 +#define CIK_INTSRC_DEQUEUE_COMPLETE 0xC6 +#define CIK_INTSRC_SDMA_TRAP 0xE0 #define CIK_INTSRC_SQ_INTERRUPT_MSG 0xEF #endif diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 660b3fbade41..505d39156acd 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -282,8 +282,7 @@ static int kfd_ioctl_create_queue(struct file *filep, struct kfd_process *p, p->pasid, dev->id); - err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, - 0, q_properties.type, &queue_id); + err = pqm_create_queue(&p->pqm, dev, filep, &q_properties, &queue_id); if (err != 0) goto err_create_queue; @@ -451,8 +450,8 @@ static int kfd_ioctl_dbg_register(struct file *filep, return -EINVAL; } - mutex_lock(kfd_get_dbgmgr_mutex()); mutex_lock(&p->mutex); + mutex_lock(kfd_get_dbgmgr_mutex()); /* * make sure that we have pdd, if this the first queue created for @@ -480,8 +479,8 @@ static int kfd_ioctl_dbg_register(struct file *filep, } out: - mutex_unlock(&p->mutex); mutex_unlock(kfd_get_dbgmgr_mutex()); + mutex_unlock(&p->mutex); return status; } @@ -836,15 +835,12 @@ static int kfd_ioctl_wait_events(struct file *filp, struct kfd_process *p, void *data) { struct kfd_ioctl_wait_events_args *args = data; - enum kfd_event_wait_result wait_result; int err; err = kfd_wait_on_events(p, args->num_events, (void __user *)args->events_ptr, (args->wait_for_all != 0), - args->timeout, &wait_result); - - args->wait_result = wait_result; + args->timeout, &args->wait_result); return err; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c index 0aa021aa0aa1..c407f6bd9956 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c @@ -184,9 +184,10 @@ static int dbgdev_register_diq(struct kfd_dbgdev *dbgdev) struct kernel_queue *kq = NULL; int status; + properties.type = KFD_QUEUE_TYPE_DIQ; + status = pqm_create_queue(dbgdev->pqm, dbgdev->dev, NULL, - &properties, 0, KFD_QUEUE_TYPE_DIQ, - &qid); + &properties, &qid); if (status) { pr_err("Failed to create DIQ\n"); @@ -769,13 +770,8 @@ int dbgdev_wave_reset_wavefronts(struct kfd_dev *dev, struct kfd_process *p) union GRBM_GFX_INDEX_BITS reg_gfx_index; struct kfd_process_device *pdd; struct dbg_wave_control_info wac_info; - int temp; - int first_vmid_to_scan = 8; - int last_vmid_to_scan = 15; - - first_vmid_to_scan = ffs(dev->shared_resources.compute_vmid_bitmap) - 1; - temp = dev->shared_resources.compute_vmid_bitmap >> first_vmid_to_scan; - last_vmid_to_scan = first_vmid_to_scan + ffz(temp); + int first_vmid_to_scan = dev->vm_info.first_vmid_kfd; + int last_vmid_to_scan = dev->vm_info.last_vmid_kfd; reg_sq_cmd.u32All = 0; status = 0; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 5df12b287201..621a3b53a038 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -92,6 +92,8 @@ static int kfd_gtt_sa_init(struct kfd_dev *kfd, unsigned int buf_size, unsigned int chunk_size); static void kfd_gtt_sa_fini(struct kfd_dev *kfd); +static int kfd_resume(struct kfd_dev *kfd); + static const struct kfd_device_info *lookup_device_info(unsigned short did) { size_t i; @@ -169,15 +171,8 @@ static bool device_iommu_pasid_init(struct kfd_dev *kfd) (unsigned int)(1 << kfd->device_info->max_pasid_bits), iommu_info.max_pasids); - err = amd_iommu_init_device(kfd->pdev, pasid_limit); - if (err < 0) { - dev_err(kfd_device, "error initializing iommu device\n"); - return false; - } - if (!kfd_set_pasid_limit(pasid_limit)) { dev_err(kfd_device, "error setting pasid limit\n"); - amd_iommu_free_device(kfd->pdev); return false; } @@ -189,7 +184,7 @@ static void iommu_pasid_shutdown_callback(struct pci_dev *pdev, int pasid) struct kfd_dev *dev = kfd_device_by_pci_dev(pdev); if (dev) - kfd_unbind_process_from_device(dev, pasid); + kfd_process_iommu_unbind_callback(dev, pasid); } /* @@ -224,6 +219,11 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, kfd->shared_resources = *gpu_resources; + kfd->vm_info.first_vmid_kfd = ffs(gpu_resources->compute_vmid_bitmap)-1; + kfd->vm_info.last_vmid_kfd = fls(gpu_resources->compute_vmid_bitmap)-1; + kfd->vm_info.vmid_num_kfd = kfd->vm_info.last_vmid_kfd + - kfd->vm_info.first_vmid_kfd + 1; + /* calculate max size of mqds needed for queues */ size = max_num_of_queues_per_device * kfd->device_info->mqd_size_aligned; @@ -273,29 +273,22 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto kfd_interrupt_error; } - if (!device_iommu_pasid_init(kfd)) { - dev_err(kfd_device, - "Error initializing iommuv2 for device %x:%x\n", - kfd->pdev->vendor, kfd->pdev->device); - goto device_iommu_pasid_error; - } - amd_iommu_set_invalidate_ctx_cb(kfd->pdev, - iommu_pasid_shutdown_callback); - amd_iommu_set_invalid_ppr_cb(kfd->pdev, iommu_invalid_ppr_cb); - kfd->dqm = device_queue_manager_init(kfd); if (!kfd->dqm) { dev_err(kfd_device, "Error initializing queue manager\n"); goto device_queue_manager_error; } - if (kfd->dqm->ops.start(kfd->dqm)) { + if (!device_iommu_pasid_init(kfd)) { dev_err(kfd_device, - "Error starting queue manager for device %x:%x\n", + "Error initializing iommuv2 for device %x:%x\n", kfd->pdev->vendor, kfd->pdev->device); - goto dqm_start_error; + goto device_iommu_pasid_error; } + if (kfd_resume(kfd)) + goto kfd_resume_error; + kfd->dbgmgr = NULL; kfd->init_complete = true; @@ -307,11 +300,10 @@ bool kgd2kfd_device_init(struct kfd_dev *kfd, goto out; -dqm_start_error: +kfd_resume_error: +device_iommu_pasid_error: device_queue_manager_uninit(kfd->dqm); device_queue_manager_error: - amd_iommu_free_device(kfd->pdev); -device_iommu_pasid_error: kfd_interrupt_exit(kfd); kfd_interrupt_error: kfd_topology_remove_device(kfd); @@ -331,8 +323,8 @@ out: void kgd2kfd_device_exit(struct kfd_dev *kfd) { if (kfd->init_complete) { + kgd2kfd_suspend(kfd); device_queue_manager_uninit(kfd->dqm); - amd_iommu_free_device(kfd->pdev); kfd_interrupt_exit(kfd); kfd_topology_remove_device(kfd); kfd_doorbell_fini(kfd); @@ -345,35 +337,59 @@ void kgd2kfd_device_exit(struct kfd_dev *kfd) void kgd2kfd_suspend(struct kfd_dev *kfd) { - if (kfd->init_complete) { - kfd->dqm->ops.stop(kfd->dqm); - amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL); - amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL); - amd_iommu_free_device(kfd->pdev); - } + if (!kfd->init_complete) + return; + + kfd->dqm->ops.stop(kfd->dqm); + + kfd_unbind_processes_from_device(kfd); + + amd_iommu_set_invalidate_ctx_cb(kfd->pdev, NULL); + amd_iommu_set_invalid_ppr_cb(kfd->pdev, NULL); + amd_iommu_free_device(kfd->pdev); } int kgd2kfd_resume(struct kfd_dev *kfd) { - unsigned int pasid_limit; - int err; + if (!kfd->init_complete) + return 0; - pasid_limit = kfd_get_pasid_limit(); + return kfd_resume(kfd); - if (kfd->init_complete) { - err = amd_iommu_init_device(kfd->pdev, pasid_limit); - if (err < 0) { - dev_err(kfd_device, "failed to initialize iommu\n"); - return -ENXIO; - } +} + +static int kfd_resume(struct kfd_dev *kfd) +{ + int err = 0; + unsigned int pasid_limit = kfd_get_pasid_limit(); - amd_iommu_set_invalidate_ctx_cb(kfd->pdev, - iommu_pasid_shutdown_callback); - amd_iommu_set_invalid_ppr_cb(kfd->pdev, iommu_invalid_ppr_cb); - kfd->dqm->ops.start(kfd->dqm); + err = amd_iommu_init_device(kfd->pdev, pasid_limit); + if (err) + return -ENXIO; + amd_iommu_set_invalidate_ctx_cb(kfd->pdev, + iommu_pasid_shutdown_callback); + amd_iommu_set_invalid_ppr_cb(kfd->pdev, + iommu_invalid_ppr_cb); + + err = kfd_bind_processes_to_device(kfd); + if (err) + goto processes_bind_error; + + err = kfd->dqm->ops.start(kfd->dqm); + if (err) { + dev_err(kfd_device, + "Error starting queue manager for device %x:%x\n", + kfd->pdev->vendor, kfd->pdev->device); + goto dqm_start_error; } - return 0; + return err; + +dqm_start_error: +processes_bind_error: + amd_iommu_free_device(kfd->pdev); + + return err; } /* This is called directly from KGD at ISR. */ @@ -387,7 +403,7 @@ void kgd2kfd_interrupt(struct kfd_dev *kfd, const void *ih_ring_entry) if (kfd->interrupts_active && interrupt_is_wanted(kfd, ih_ring_entry) && enqueue_ih_ring_entry(kfd, ih_ring_entry)) - schedule_work(&kfd->interrupt_work); + queue_work(kfd->ih_wq, &kfd->interrupt_work); spin_unlock(&kfd->interrupt_lock); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index 53a66e821624..e202921c150e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -44,9 +44,14 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd); -static int execute_queues_cpsch(struct device_queue_manager *dqm, bool lock); -static int destroy_queues_cpsch(struct device_queue_manager *dqm, - bool preempt_static_queues, bool lock); +static int execute_queues_cpsch(struct device_queue_manager *dqm, + enum kfd_unmap_queues_filter filter, + uint32_t filter_param); +static int unmap_queues_cpsch(struct device_queue_manager *dqm, + enum kfd_unmap_queues_filter filter, + uint32_t filter_param); + +static int map_queues_cpsch(struct device_queue_manager *dqm); static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm, struct queue *q, @@ -113,11 +118,11 @@ static int allocate_vmid(struct device_queue_manager *dqm, if (dqm->vmid_bitmap == 0) return -ENOMEM; - bit = find_first_bit((unsigned long *)&dqm->vmid_bitmap, CIK_VMID_NUM); + bit = find_first_bit((unsigned long *)&dqm->vmid_bitmap, + dqm->dev->vm_info.vmid_num_kfd); clear_bit(bit, (unsigned long *)&dqm->vmid_bitmap); - /* Kaveri kfd vmid's starts from vmid 8 */ - allocated_vmid = bit + KFD_VMID_START_OFFSET; + allocated_vmid = bit + dqm->dev->vm_info.first_vmid_kfd; pr_debug("vmid allocation %d\n", allocated_vmid); qpd->vmid = allocated_vmid; q->properties.vmid = allocated_vmid; @@ -132,7 +137,7 @@ static void deallocate_vmid(struct device_queue_manager *dqm, struct qcm_process_device *qpd, struct queue *q) { - int bit = qpd->vmid - KFD_VMID_START_OFFSET; + int bit = qpd->vmid - dqm->dev->vm_info.first_vmid_kfd; /* Release the vmid mapping */ set_pasid_vmid_mapping(dqm, 0, qpd->vmid); @@ -184,6 +189,7 @@ static int create_queue_nocpsch(struct device_queue_manager *dqm, } list_add(&q->list, &qpd->queues_list); + qpd->queue_count++; if (q->properties.is_active) dqm->queue_count++; @@ -273,6 +279,9 @@ static int create_compute_queue_nocpsch(struct device_queue_manager *dqm, dqm->dev->kfd2kgd->set_scratch_backing_va( dqm->dev->kgd, qpd->sh_hidden_private_base, qpd->vmid); + if (!q->properties.is_active) + return 0; + retval = mqd->load_mqd(mqd, q->mqd, q->pipe, q->queue, &q->properties, q->process->mm); if (retval) @@ -288,65 +297,74 @@ out_deallocate_hqd: return retval; } -static int destroy_queue_nocpsch(struct device_queue_manager *dqm, +/* Access to DQM has to be locked before calling destroy_queue_nocpsch_locked + * to avoid asynchronized access + */ +static int destroy_queue_nocpsch_locked(struct device_queue_manager *dqm, struct qcm_process_device *qpd, struct queue *q) { int retval; struct mqd_manager *mqd; - retval = 0; - - mutex_lock(&dqm->lock); + mqd = dqm->ops.get_mqd_manager(dqm, + get_mqd_type_from_queue_type(q->properties.type)); + if (!mqd) + return -ENOMEM; if (q->properties.type == KFD_QUEUE_TYPE_COMPUTE) { - mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_COMPUTE); - if (mqd == NULL) { - retval = -ENOMEM; - goto out; - } deallocate_hqd(dqm, q); } else if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { - mqd = dqm->ops.get_mqd_manager(dqm, KFD_MQD_TYPE_SDMA); - if (mqd == NULL) { - retval = -ENOMEM; - goto out; - } dqm->sdma_queue_count--; deallocate_sdma_queue(dqm, q->sdma_id); } else { pr_debug("q->properties.type %d is invalid\n", q->properties.type); - retval = -EINVAL; - goto out; + return -EINVAL; } + dqm->total_queue_count--; retval = mqd->destroy_mqd(mqd, q->mqd, KFD_PREEMPT_TYPE_WAVEFRONT_RESET, - QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS, + KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); - - if (retval) - goto out; + if (retval == -ETIME) + qpd->reset_wavefronts = true; mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); list_del(&q->list); - if (list_empty(&qpd->queues_list)) + if (list_empty(&qpd->queues_list)) { + if (qpd->reset_wavefronts) { + pr_warn("Resetting wave fronts (nocpsch) on dev %p\n", + dqm->dev); + /* dbgdev_wave_reset_wavefronts has to be called before + * deallocate_vmid(), i.e. when vmid is still in use. + */ + dbgdev_wave_reset_wavefronts(dqm->dev, + qpd->pqm->process); + qpd->reset_wavefronts = false; + } + deallocate_vmid(dqm, qpd, q); + } + qpd->queue_count--; if (q->properties.is_active) dqm->queue_count--; - /* - * Unconditionally decrement this counter, regardless of the queue's - * type - */ - dqm->total_queue_count--; - pr_debug("Total of %d queues are accountable so far\n", - dqm->total_queue_count); + return retval; +} -out: +static int destroy_queue_nocpsch(struct device_queue_manager *dqm, + struct qcm_process_device *qpd, + struct queue *q) +{ + int retval; + + mutex_lock(&dqm->lock); + retval = destroy_queue_nocpsch_locked(dqm, qpd, q); mutex_unlock(&dqm->lock); + return retval; } @@ -364,29 +382,56 @@ static int update_queue(struct device_queue_manager *dqm, struct queue *q) goto out_unlock; } - if (q->properties.is_active) - prev_active = true; + /* Save previous activity state for counters */ + prev_active = q->properties.is_active; + + /* Make sure the queue is unmapped before updating the MQD */ + if (sched_policy != KFD_SCHED_POLICY_NO_HWS) { + retval = unmap_queues_cpsch(dqm, + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); + if (retval) { + pr_err("unmap queue failed\n"); + goto out_unlock; + } + } else if (prev_active && + (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || + q->properties.type == KFD_QUEUE_TYPE_SDMA)) { + retval = mqd->destroy_mqd(mqd, q->mqd, + KFD_PREEMPT_TYPE_WAVEFRONT_DRAIN, + KFD_UNMAP_LATENCY_MS, q->pipe, q->queue); + if (retval) { + pr_err("destroy mqd failed\n"); + goto out_unlock; + } + } + + retval = mqd->update_mqd(mqd, q->mqd, &q->properties); /* - * - * check active state vs. the previous state - * and modify counter accordingly + * check active state vs. the previous state and modify + * counter accordingly. map_queues_cpsch uses the + * dqm->queue_count to determine whether a new runlist must be + * uploaded. */ - retval = mqd->update_mqd(mqd, q->mqd, &q->properties); - if ((q->properties.is_active) && (!prev_active)) + if (q->properties.is_active && !prev_active) dqm->queue_count++; else if (!q->properties.is_active && prev_active) dqm->queue_count--; if (sched_policy != KFD_SCHED_POLICY_NO_HWS) - retval = execute_queues_cpsch(dqm, false); + retval = map_queues_cpsch(dqm); + else if (q->properties.is_active && + (q->properties.type == KFD_QUEUE_TYPE_COMPUTE || + q->properties.type == KFD_QUEUE_TYPE_SDMA)) + retval = mqd->load_mqd(mqd, q->mqd, q->pipe, q->queue, + &q->properties, q->process->mm); out_unlock: mutex_unlock(&dqm->lock); return retval; } -static struct mqd_manager *get_mqd_manager_nocpsch( +static struct mqd_manager *get_mqd_manager( struct device_queue_manager *dqm, enum KFD_MQD_TYPE type) { struct mqd_manager *mqd; @@ -407,7 +452,7 @@ static struct mqd_manager *get_mqd_manager_nocpsch( return mqd; } -static int register_process_nocpsch(struct device_queue_manager *dqm, +static int register_process(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { struct device_process_node *n; @@ -422,7 +467,7 @@ static int register_process_nocpsch(struct device_queue_manager *dqm, mutex_lock(&dqm->lock); list_add(&n->list, &dqm->queues); - retval = dqm->ops_asic_specific.register_process(dqm, qpd); + retval = dqm->asic_ops.update_qpd(dqm, qpd); dqm->processes_count++; @@ -431,7 +476,7 @@ static int register_process_nocpsch(struct device_queue_manager *dqm, return retval; } -static int unregister_process_nocpsch(struct device_queue_manager *dqm, +static int unregister_process(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { int retval; @@ -507,13 +552,13 @@ static int initialize_nocpsch(struct device_queue_manager *dqm) dqm->allocated_queues[pipe] |= 1 << queue; } - dqm->vmid_bitmap = (1 << VMID_PER_DEVICE) - 1; + dqm->vmid_bitmap = (1 << dqm->dev->vm_info.vmid_num_kfd) - 1; dqm->sdma_bitmap = (1 << CIK_SDMA_QUEUES) - 1; return 0; } -static void uninitialize_nocpsch(struct device_queue_manager *dqm) +static void uninitialize(struct device_queue_manager *dqm) { int i; @@ -577,14 +622,14 @@ static int create_sdma_queue_nocpsch(struct device_queue_manager *dqm, if (retval) return retval; - q->properties.sdma_queue_id = q->sdma_id % CIK_SDMA_QUEUES_PER_ENGINE; - q->properties.sdma_engine_id = q->sdma_id / CIK_SDMA_ENGINE_NUM; + q->properties.sdma_queue_id = q->sdma_id / CIK_SDMA_QUEUES_PER_ENGINE; + q->properties.sdma_engine_id = q->sdma_id % CIK_SDMA_QUEUES_PER_ENGINE; pr_debug("SDMA id is: %d\n", q->sdma_id); pr_debug("SDMA queue id: %d\n", q->properties.sdma_queue_id); pr_debug("SDMA engine id: %d\n", q->properties.sdma_engine_id); - dqm->ops_asic_specific.init_sdma_vm(dqm, q, qpd); + dqm->asic_ops.init_sdma_vm(dqm, q, qpd); retval = mqd->init_mqd(mqd, &q->mqd, &q->mqd_mem_obj, &q->gart_mqd_addr, &q->properties); if (retval) @@ -613,8 +658,7 @@ static int set_sched_resources(struct device_queue_manager *dqm) int i, mec; struct scheduling_resources res; - res.vmid_mask = (1 << VMID_PER_DEVICE) - 1; - res.vmid_mask <<= KFD_VMID_START_OFFSET; + res.vmid_mask = dqm->dev->shared_resources.compute_vmid_bitmap; res.queue_mask = 0; for (i = 0; i < KGD_MAX_QUEUES; ++i) { @@ -652,8 +696,6 @@ static int set_sched_resources(struct device_queue_manager *dqm) static int initialize_cpsch(struct device_queue_manager *dqm) { - int retval; - pr_debug("num of pipes: %d\n", get_pipes_per_mec(dqm)); mutex_init(&dqm->lock); @@ -661,16 +703,13 @@ static int initialize_cpsch(struct device_queue_manager *dqm) dqm->queue_count = dqm->processes_count = 0; dqm->sdma_queue_count = 0; dqm->active_runlist = false; - retval = dqm->ops_asic_specific.initialize(dqm); - if (retval) - mutex_destroy(&dqm->lock); + dqm->sdma_bitmap = (1 << CIK_SDMA_QUEUES) - 1; - return retval; + return 0; } static int start_cpsch(struct device_queue_manager *dqm) { - struct device_process_node *node; int retval; retval = 0; @@ -697,12 +736,9 @@ static int start_cpsch(struct device_queue_manager *dqm) init_interrupts(dqm); - list_for_each_entry(node, &dqm->queues, list) - if (node->qpd->pqm->process && dqm->dev) - kfd_bind_process_to_device(dqm->dev, - node->qpd->pqm->process); - - execute_queues_cpsch(dqm, true); + mutex_lock(&dqm->lock); + execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); + mutex_unlock(&dqm->lock); return 0; fail_allocate_vidmem: @@ -714,15 +750,10 @@ fail_packet_manager_init: static int stop_cpsch(struct device_queue_manager *dqm) { - struct device_process_node *node; - struct kfd_process_device *pdd; - - destroy_queues_cpsch(dqm, true, true); + mutex_lock(&dqm->lock); + unmap_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); + mutex_unlock(&dqm->lock); - list_for_each_entry(node, &dqm->queues, list) { - pdd = qpd_to_pdd(node->qpd); - pdd->bound = false; - } kfd_gtt_sa_free(dqm->dev, dqm->fence_mem); pm_uninit(&dqm->packets); @@ -752,7 +783,7 @@ static int create_kernel_queue_cpsch(struct device_queue_manager *dqm, list_add(&kq->list, &qpd->priv_queue_list); dqm->queue_count++; qpd->is_debug = true; - execute_queues_cpsch(dqm, false); + execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); mutex_unlock(&dqm->lock); return 0; @@ -763,12 +794,10 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { mutex_lock(&dqm->lock); - /* here we actually preempt the DIQ */ - destroy_queues_cpsch(dqm, true, false); list_del(&kq->list); dqm->queue_count--; qpd->is_debug = false; - execute_queues_cpsch(dqm, false); + execute_queues_cpsch(dqm, KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, 0); /* * Unconditionally decrement this counter, regardless of the queue's * type. @@ -779,14 +808,6 @@ static void destroy_kernel_queue_cpsch(struct device_queue_manager *dqm, mutex_unlock(&dqm->lock); } -static void select_sdma_engine_id(struct queue *q) -{ - static int sdma_id; - - q->sdma_id = sdma_id; - sdma_id = (sdma_id + 1) % 2; -} - static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd, int *allocate_vmid) { @@ -807,9 +828,15 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, goto out; } - if (q->properties.type == KFD_QUEUE_TYPE_SDMA) - select_sdma_engine_id(q); - + if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { + retval = allocate_sdma_queue(dqm, &q->sdma_id); + if (retval) + goto out; + q->properties.sdma_queue_id = + q->sdma_id / CIK_SDMA_QUEUES_PER_ENGINE; + q->properties.sdma_engine_id = + q->sdma_id % CIK_SDMA_QUEUES_PER_ENGINE; + } mqd = dqm->ops.get_mqd_manager(dqm, get_mqd_type_from_queue_type(q->properties.type)); @@ -818,16 +845,18 @@ static int create_queue_cpsch(struct device_queue_manager *dqm, struct queue *q, goto out; } - dqm->ops_asic_specific.init_sdma_vm(dqm, q, qpd); + dqm->asic_ops.init_sdma_vm(dqm, q, qpd); retval = mqd->init_mqd(mqd, &q->mqd, &q->mqd_mem_obj, &q->gart_mqd_addr, &q->properties); if (retval) goto out; list_add(&q->list, &qpd->queues_list); + qpd->queue_count++; if (q->properties.is_active) { dqm->queue_count++; - retval = execute_queues_cpsch(dqm, false); + retval = execute_queues_cpsch(dqm, + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); } if (q->properties.type == KFD_QUEUE_TYPE_SDMA) @@ -848,12 +877,12 @@ out: int amdkfd_fence_wait_timeout(unsigned int *fence_addr, unsigned int fence_value, - unsigned long timeout) + unsigned int timeout_ms) { - timeout += jiffies; + unsigned long end_jiffies = msecs_to_jiffies(timeout_ms) + jiffies; while (*fence_addr != fence_value) { - if (time_after(jiffies, timeout)) { + if (time_after(jiffies, end_jiffies)) { pr_err("qcm fence wait loop timeout expired\n"); return -ETIME; } @@ -863,44 +892,57 @@ int amdkfd_fence_wait_timeout(unsigned int *fence_addr, return 0; } -static int destroy_sdma_queues(struct device_queue_manager *dqm, +static int unmap_sdma_queues(struct device_queue_manager *dqm, unsigned int sdma_engine) { return pm_send_unmap_queue(&dqm->packets, KFD_QUEUE_TYPE_SDMA, - KFD_PREEMPT_TYPE_FILTER_DYNAMIC_QUEUES, 0, false, + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0, false, sdma_engine); } -static int destroy_queues_cpsch(struct device_queue_manager *dqm, - bool preempt_static_queues, bool lock) +/* dqm->lock mutex has to be locked before calling this function */ +static int map_queues_cpsch(struct device_queue_manager *dqm) { int retval; - enum kfd_preempt_type_filter preempt_type; - struct kfd_process_device *pdd; - retval = 0; + if (dqm->queue_count <= 0 || dqm->processes_count <= 0) + return 0; + + if (dqm->active_runlist) + return 0; + + retval = pm_send_runlist(&dqm->packets, &dqm->queues); + if (retval) { + pr_err("failed to execute runlist\n"); + return retval; + } + dqm->active_runlist = true; + + return retval; +} + +/* dqm->lock mutex has to be locked before calling this function */ +static int unmap_queues_cpsch(struct device_queue_manager *dqm, + enum kfd_unmap_queues_filter filter, + uint32_t filter_param) +{ + int retval = 0; - if (lock) - mutex_lock(&dqm->lock); if (!dqm->active_runlist) - goto out; + return retval; pr_debug("Before destroying queues, sdma queue count is : %u\n", dqm->sdma_queue_count); if (dqm->sdma_queue_count > 0) { - destroy_sdma_queues(dqm, 0); - destroy_sdma_queues(dqm, 1); + unmap_sdma_queues(dqm, 0); + unmap_sdma_queues(dqm, 1); } - preempt_type = preempt_static_queues ? - KFD_PREEMPT_TYPE_FILTER_ALL_QUEUES : - KFD_PREEMPT_TYPE_FILTER_DYNAMIC_QUEUES; - retval = pm_send_unmap_queue(&dqm->packets, KFD_QUEUE_TYPE_COMPUTE, - preempt_type, 0, false, 0); + filter, filter_param, false, 0); if (retval) - goto out; + return retval; *dqm->fence_addr = KFD_FENCE_INIT; pm_send_query_status(&dqm->packets, dqm->fence_gpu_addr, @@ -908,55 +950,29 @@ static int destroy_queues_cpsch(struct device_queue_manager *dqm, /* should be timed out */ retval = amdkfd_fence_wait_timeout(dqm->fence_addr, KFD_FENCE_COMPLETED, QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS); - if (retval) { - pdd = kfd_get_process_device_data(dqm->dev, - kfd_get_process(current)); - pdd->reset_wavefronts = true; - goto out; - } + if (retval) + return retval; + pm_release_ib(&dqm->packets); dqm->active_runlist = false; -out: - if (lock) - mutex_unlock(&dqm->lock); return retval; } -static int execute_queues_cpsch(struct device_queue_manager *dqm, bool lock) +/* dqm->lock mutex has to be locked before calling this function */ +static int execute_queues_cpsch(struct device_queue_manager *dqm, + enum kfd_unmap_queues_filter filter, + uint32_t filter_param) { int retval; - if (lock) - mutex_lock(&dqm->lock); - - retval = destroy_queues_cpsch(dqm, false, false); - if (retval) { - pr_err("The cp might be in an unrecoverable state due to an unsuccessful queues preemption"); - goto out; - } - - if (dqm->queue_count <= 0 || dqm->processes_count <= 0) { - retval = 0; - goto out; - } - - if (dqm->active_runlist) { - retval = 0; - goto out; - } - - retval = pm_send_runlist(&dqm->packets, &dqm->queues); + retval = unmap_queues_cpsch(dqm, filter, filter_param); if (retval) { - pr_err("failed to execute runlist"); - goto out; + pr_err("The cp might be in an unrecoverable state due to an unsuccessful queues preemption\n"); + return retval; } - dqm->active_runlist = true; -out: - if (lock) - mutex_unlock(&dqm->lock); - return retval; + return map_queues_cpsch(dqm); } static int destroy_queue_cpsch(struct device_queue_manager *dqm, @@ -991,14 +1007,20 @@ static int destroy_queue_cpsch(struct device_queue_manager *dqm, goto failed; } - if (q->properties.type == KFD_QUEUE_TYPE_SDMA) + if (q->properties.type == KFD_QUEUE_TYPE_SDMA) { dqm->sdma_queue_count--; + deallocate_sdma_queue(dqm, q->sdma_id); + } list_del(&q->list); + qpd->queue_count--; if (q->properties.is_active) dqm->queue_count--; - execute_queues_cpsch(dqm, false); + retval = execute_queues_cpsch(dqm, + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0); + if (retval == -ETIME) + qpd->reset_wavefronts = true; mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); @@ -1068,7 +1090,7 @@ static bool set_cache_memory_policy(struct device_queue_manager *dqm, qpd->sh_mem_ape1_limit = limit >> 16; } - retval = dqm->ops_asic_specific.set_cache_memory_policy( + retval = dqm->asic_ops.set_cache_memory_policy( dqm, qpd, default_policy, @@ -1088,6 +1110,109 @@ out: return retval; } +static int process_termination_nocpsch(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) +{ + struct queue *q, *next; + struct device_process_node *cur, *next_dpn; + int retval = 0; + + mutex_lock(&dqm->lock); + + /* Clear all user mode queues */ + list_for_each_entry_safe(q, next, &qpd->queues_list, list) { + int ret; + + ret = destroy_queue_nocpsch_locked(dqm, qpd, q); + if (ret) + retval = ret; + } + + /* Unregister process */ + list_for_each_entry_safe(cur, next_dpn, &dqm->queues, list) { + if (qpd == cur->qpd) { + list_del(&cur->list); + kfree(cur); + dqm->processes_count--; + break; + } + } + + mutex_unlock(&dqm->lock); + return retval; +} + + +static int process_termination_cpsch(struct device_queue_manager *dqm, + struct qcm_process_device *qpd) +{ + int retval; + struct queue *q, *next; + struct kernel_queue *kq, *kq_next; + struct mqd_manager *mqd; + struct device_process_node *cur, *next_dpn; + enum kfd_unmap_queues_filter filter = + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES; + + retval = 0; + + mutex_lock(&dqm->lock); + + /* Clean all kernel queues */ + list_for_each_entry_safe(kq, kq_next, &qpd->priv_queue_list, list) { + list_del(&kq->list); + dqm->queue_count--; + qpd->is_debug = false; + dqm->total_queue_count--; + filter = KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES; + } + + /* Clear all user mode queues */ + list_for_each_entry(q, &qpd->queues_list, list) { + if (q->properties.type == KFD_QUEUE_TYPE_SDMA) + dqm->sdma_queue_count--; + + if (q->properties.is_active) + dqm->queue_count--; + + dqm->total_queue_count--; + } + + /* Unregister process */ + list_for_each_entry_safe(cur, next_dpn, &dqm->queues, list) { + if (qpd == cur->qpd) { + list_del(&cur->list); + kfree(cur); + dqm->processes_count--; + break; + } + } + + retval = execute_queues_cpsch(dqm, filter, 0); + if (retval || qpd->reset_wavefronts) { + pr_warn("Resetting wave fronts (cpsch) on dev %p\n", dqm->dev); + dbgdev_wave_reset_wavefronts(dqm->dev, qpd->pqm->process); + qpd->reset_wavefronts = false; + } + + /* lastly, free mqd resources */ + list_for_each_entry_safe(q, next, &qpd->queues_list, list) { + mqd = dqm->ops.get_mqd_manager(dqm, + get_mqd_type_from_queue_type(q->properties.type)); + if (!mqd) { + retval = -ENOMEM; + goto out; + } + list_del(&q->list); + qpd->queue_count--; + mqd->uninit_mqd(mqd, q->mqd, q->mqd_mem_obj); + } + +out: + mutex_unlock(&dqm->lock); + return retval; +} + struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) { struct device_queue_manager *dqm; @@ -1109,13 +1234,14 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) dqm->ops.stop = stop_cpsch; dqm->ops.destroy_queue = destroy_queue_cpsch; dqm->ops.update_queue = update_queue; - dqm->ops.get_mqd_manager = get_mqd_manager_nocpsch; - dqm->ops.register_process = register_process_nocpsch; - dqm->ops.unregister_process = unregister_process_nocpsch; - dqm->ops.uninitialize = uninitialize_nocpsch; + dqm->ops.get_mqd_manager = get_mqd_manager; + dqm->ops.register_process = register_process; + dqm->ops.unregister_process = unregister_process; + dqm->ops.uninitialize = uninitialize; dqm->ops.create_kernel_queue = create_kernel_queue_cpsch; dqm->ops.destroy_kernel_queue = destroy_kernel_queue_cpsch; dqm->ops.set_cache_memory_policy = set_cache_memory_policy; + dqm->ops.process_termination = process_termination_cpsch; break; case KFD_SCHED_POLICY_NO_HWS: /* initialize dqm for no cp scheduling */ @@ -1124,12 +1250,13 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) dqm->ops.create_queue = create_queue_nocpsch; dqm->ops.destroy_queue = destroy_queue_nocpsch; dqm->ops.update_queue = update_queue; - dqm->ops.get_mqd_manager = get_mqd_manager_nocpsch; - dqm->ops.register_process = register_process_nocpsch; - dqm->ops.unregister_process = unregister_process_nocpsch; + dqm->ops.get_mqd_manager = get_mqd_manager; + dqm->ops.register_process = register_process; + dqm->ops.unregister_process = unregister_process; dqm->ops.initialize = initialize_nocpsch; - dqm->ops.uninitialize = uninitialize_nocpsch; + dqm->ops.uninitialize = uninitialize; dqm->ops.set_cache_memory_policy = set_cache_memory_policy; + dqm->ops.process_termination = process_termination_nocpsch; break; default: pr_err("Invalid scheduling policy %d\n", sched_policy); @@ -1138,12 +1265,16 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_dev *dev) switch (dev->device_info->asic_family) { case CHIP_CARRIZO: - device_queue_manager_init_vi(&dqm->ops_asic_specific); + device_queue_manager_init_vi(&dqm->asic_ops); break; case CHIP_KAVERI: - device_queue_manager_init_cik(&dqm->ops_asic_specific); + device_queue_manager_init_cik(&dqm->asic_ops); break; + default: + WARN(1, "Unexpected ASIC family %u", + dev->device_info->asic_family); + goto out_free; } if (!dqm->ops.initialize(dqm)) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index faf820a06400..5b77cb69f732 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -29,11 +29,9 @@ #include "kfd_priv.h" #include "kfd_mqd_manager.h" -#define QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS (500) -#define CIK_VMID_NUM (8) -#define KFD_VMID_START_OFFSET (8) -#define VMID_PER_DEVICE CIK_VMID_NUM -#define KFD_DQM_FIRST_PIPE (0) +#define KFD_UNMAP_LATENCY_MS (4000) +#define QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS (2 * KFD_UNMAP_LATENCY_MS + 1000) + #define CIK_SDMA_QUEUES (4) #define CIK_SDMA_QUEUES_PER_ENGINE (2) #define CIK_SDMA_ENGINE_NUM (2) @@ -79,6 +77,8 @@ struct device_process_node { * @set_cache_memory_policy: Sets memory policy (cached/ non cached) for the * memory apertures. * + * @process_termination: Clears all process queues belongs to that device. + * */ struct device_queue_manager_ops { @@ -122,12 +122,14 @@ struct device_queue_manager_ops { enum cache_policy alternate_policy, void __user *alternate_aperture_base, uint64_t alternate_aperture_size); + + int (*process_termination)(struct device_queue_manager *dqm, + struct qcm_process_device *qpd); }; struct device_queue_manager_asic_ops { - int (*register_process)(struct device_queue_manager *dqm, + int (*update_qpd)(struct device_queue_manager *dqm, struct qcm_process_device *qpd); - int (*initialize)(struct device_queue_manager *dqm); bool (*set_cache_memory_policy)(struct device_queue_manager *dqm, struct qcm_process_device *qpd, enum cache_policy default_policy, @@ -153,7 +155,7 @@ struct device_queue_manager_asic_ops { struct device_queue_manager { struct device_queue_manager_ops ops; - struct device_queue_manager_asic_ops ops_asic_specific; + struct device_queue_manager_asic_ops asic_ops; struct mqd_manager *mqds[KFD_MQD_TYPE_MAX]; struct packet_manager packets; @@ -176,8 +178,10 @@ struct device_queue_manager { bool active_runlist; }; -void device_queue_manager_init_cik(struct device_queue_manager_asic_ops *ops); -void device_queue_manager_init_vi(struct device_queue_manager_asic_ops *ops); +void device_queue_manager_init_cik( + struct device_queue_manager_asic_ops *asic_ops); +void device_queue_manager_init_vi( + struct device_queue_manager_asic_ops *asic_ops); void program_sh_mem_settings(struct device_queue_manager *dqm, struct qcm_process_device *qpd); unsigned int get_queues_num(struct device_queue_manager *dqm); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c index 72c3cbabc0a7..28e48c90c596 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_cik.c @@ -32,18 +32,17 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, enum cache_policy alternate_policy, void __user *alternate_aperture_base, uint64_t alternate_aperture_size); -static int register_process_cik(struct device_queue_manager *dqm, +static int update_qpd_cik(struct device_queue_manager *dqm, struct qcm_process_device *qpd); -static int initialize_cpsch_cik(struct device_queue_manager *dqm); static void init_sdma_vm(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd); -void device_queue_manager_init_cik(struct device_queue_manager_asic_ops *ops) +void device_queue_manager_init_cik( + struct device_queue_manager_asic_ops *asic_ops) { - ops->set_cache_memory_policy = set_cache_memory_policy_cik; - ops->register_process = register_process_cik; - ops->initialize = initialize_cpsch_cik; - ops->init_sdma_vm = init_sdma_vm; + asic_ops->set_cache_memory_policy = set_cache_memory_policy_cik; + asic_ops->update_qpd = update_qpd_cik; + asic_ops->init_sdma_vm = init_sdma_vm; } static uint32_t compute_sh_mem_bases_64bit(unsigned int top_address_nybble) @@ -99,7 +98,7 @@ static bool set_cache_memory_policy_cik(struct device_queue_manager *dqm, return true; } -static int register_process_cik(struct device_queue_manager *dqm, +static int update_qpd_cik(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { struct kfd_process_device *pdd; @@ -148,8 +147,3 @@ static void init_sdma_vm(struct device_queue_manager *dqm, struct queue *q, q->properties.sdma_vm_addr = value; } - -static int initialize_cpsch_cik(struct device_queue_manager *dqm) -{ - return 0; -} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c index 40e9ddd096cd..2fbce57a2f21 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager_vi.c @@ -33,18 +33,17 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, enum cache_policy alternate_policy, void __user *alternate_aperture_base, uint64_t alternate_aperture_size); -static int register_process_vi(struct device_queue_manager *dqm, +static int update_qpd_vi(struct device_queue_manager *dqm, struct qcm_process_device *qpd); -static int initialize_cpsch_vi(struct device_queue_manager *dqm); static void init_sdma_vm(struct device_queue_manager *dqm, struct queue *q, struct qcm_process_device *qpd); -void device_queue_manager_init_vi(struct device_queue_manager_asic_ops *ops) +void device_queue_manager_init_vi( + struct device_queue_manager_asic_ops *asic_ops) { - ops->set_cache_memory_policy = set_cache_memory_policy_vi; - ops->register_process = register_process_vi; - ops->initialize = initialize_cpsch_vi; - ops->init_sdma_vm = init_sdma_vm; + asic_ops->set_cache_memory_policy = set_cache_memory_policy_vi; + asic_ops->update_qpd = update_qpd_vi; + asic_ops->init_sdma_vm = init_sdma_vm; } static uint32_t compute_sh_mem_bases_64bit(unsigned int top_address_nybble) @@ -104,7 +103,7 @@ static bool set_cache_memory_policy_vi(struct device_queue_manager *dqm, return true; } -static int register_process_vi(struct device_queue_manager *dqm, +static int update_qpd_vi(struct device_queue_manager *dqm, struct qcm_process_device *qpd) { struct kfd_process_device *pdd; @@ -160,8 +159,3 @@ static void init_sdma_vm(struct device_queue_manager *dqm, struct queue *q, q->properties.sdma_vm_addr = value; } - -static int initialize_cpsch_vi(struct device_queue_manager *dqm) -{ - return 0; -} diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.c b/drivers/gpu/drm/amd/amdkfd/kfd_events.c index 944abfad39c1..cb92d4b72400 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.c @@ -24,8 +24,8 @@ #include <linux/slab.h> #include <linux/types.h> #include <linux/sched/signal.h> +#include <linux/sched/mm.h> #include <linux/uaccess.h> -#include <linux/mm.h> #include <linux/mman.h> #include <linux/memory.h> #include "kfd_priv.h" @@ -33,185 +33,89 @@ #include <linux/device.h> /* - * A task can only be on a single wait_queue at a time, but we need to support - * waiting on multiple events (any/all). - * Instead of each event simply having a wait_queue with sleeping tasks, it - * has a singly-linked list of tasks. - * A thread that wants to sleep creates an array of these, one for each event - * and adds one to each event's waiter chain. + * Wrapper around wait_queue_entry_t */ struct kfd_event_waiter { - struct list_head waiters; - struct task_struct *sleeping_task; - - /* Transitions to true when the event this belongs to is signaled. */ - bool activated; - - /* Event */ - struct kfd_event *event; - uint32_t input_index; + wait_queue_entry_t wait; + struct kfd_event *event; /* Event to wait for */ + bool activated; /* Becomes true when event is signaled */ }; /* - * Over-complicated pooled allocator for event notification slots. - * * Each signal event needs a 64-bit signal slot where the signaler will write - * a 1 before sending an interrupt.l (This is needed because some interrupts + * a 1 before sending an interrupt. (This is needed because some interrupts * do not contain enough spare data bits to identify an event.) - * We get whole pages from vmalloc and map them to the process VA. - * Individual signal events are then allocated a slot in a page. + * We get whole pages and map them to the process VA. + * Individual signal events use their event_id as slot index. */ - -struct signal_page { - struct list_head event_pages; /* kfd_process.signal_event_pages */ +struct kfd_signal_page { uint64_t *kernel_address; uint64_t __user *user_address; - uint32_t page_index; /* Index into the mmap aperture. */ - unsigned int free_slots; - unsigned long used_slot_bitmap[0]; }; -#define SLOTS_PER_PAGE KFD_SIGNAL_EVENT_LIMIT -#define SLOT_BITMAP_SIZE BITS_TO_LONGS(SLOTS_PER_PAGE) -#define BITS_PER_PAGE (ilog2(SLOTS_PER_PAGE)+1) -#define SIGNAL_PAGE_SIZE (sizeof(struct signal_page) + \ - SLOT_BITMAP_SIZE * sizeof(long)) - -/* - * For signal events, the event ID is used as the interrupt user data. - * For SQ s_sendmsg interrupts, this is limited to 8 bits. - */ - -#define INTERRUPT_DATA_BITS 8 -#define SIGNAL_EVENT_ID_SLOT_SHIFT 0 -static uint64_t *page_slots(struct signal_page *page) +static uint64_t *page_slots(struct kfd_signal_page *page) { return page->kernel_address; } -static bool allocate_free_slot(struct kfd_process *process, - struct signal_page **out_page, - unsigned int *out_slot_index) -{ - struct signal_page *page; - - list_for_each_entry(page, &process->signal_event_pages, event_pages) { - if (page->free_slots > 0) { - unsigned int slot = - find_first_zero_bit(page->used_slot_bitmap, - SLOTS_PER_PAGE); - - __set_bit(slot, page->used_slot_bitmap); - page->free_slots--; - - page_slots(page)[slot] = UNSIGNALED_EVENT_SLOT; - - *out_page = page; - *out_slot_index = slot; - - pr_debug("Allocated event signal slot in page %p, slot %d\n", - page, slot); - - return true; - } - } - - pr_debug("No free event signal slots were found for process %p\n", - process); - - return false; -} - -#define list_tail_entry(head, type, member) \ - list_entry((head)->prev, type, member) - -static bool allocate_signal_page(struct file *devkfd, struct kfd_process *p) +static struct kfd_signal_page *allocate_signal_page(struct kfd_process *p) { void *backing_store; - struct signal_page *page; + struct kfd_signal_page *page; - page = kzalloc(SIGNAL_PAGE_SIZE, GFP_KERNEL); + page = kzalloc(sizeof(*page), GFP_KERNEL); if (!page) - goto fail_alloc_signal_page; + return NULL; - page->free_slots = SLOTS_PER_PAGE; - - backing_store = (void *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, + backing_store = (void *) __get_free_pages(GFP_KERNEL, get_order(KFD_SIGNAL_EVENT_LIMIT * 8)); if (!backing_store) goto fail_alloc_signal_store; - /* prevent user-mode info leaks */ + /* Initialize all events to unsignaled */ memset(backing_store, (uint8_t) UNSIGNALED_EVENT_SLOT, - KFD_SIGNAL_EVENT_LIMIT * 8); + KFD_SIGNAL_EVENT_LIMIT * 8); page->kernel_address = backing_store; - - if (list_empty(&p->signal_event_pages)) - page->page_index = 0; - else - page->page_index = list_tail_entry(&p->signal_event_pages, - struct signal_page, - event_pages)->page_index + 1; - pr_debug("Allocated new event signal page at %p, for process %p\n", page, p); - pr_debug("Page index is %d\n", page->page_index); - list_add(&page->event_pages, &p->signal_event_pages); - - return true; + return page; fail_alloc_signal_store: kfree(page); -fail_alloc_signal_page: - return false; + return NULL; } -static bool allocate_event_notification_slot(struct file *devkfd, - struct kfd_process *p, - struct signal_page **page, - unsigned int *signal_slot_index) +static int allocate_event_notification_slot(struct kfd_process *p, + struct kfd_event *ev) { - bool ret; + int id; - ret = allocate_free_slot(p, page, signal_slot_index); - if (!ret) { - ret = allocate_signal_page(devkfd, p); - if (ret) - ret = allocate_free_slot(p, page, signal_slot_index); + if (!p->signal_page) { + p->signal_page = allocate_signal_page(p); + if (!p->signal_page) + return -ENOMEM; + /* Oldest user mode expects 256 event slots */ + p->signal_mapped_size = 256*8; } - return ret; -} - -/* Assumes that the process's event_mutex is locked. */ -static void release_event_notification_slot(struct signal_page *page, - size_t slot_index) -{ - __clear_bit(slot_index, page->used_slot_bitmap); - page->free_slots++; - - /* We don't free signal pages, they are retained by the process - * and reused until it exits. - */ -} - -static struct signal_page *lookup_signal_page_by_index(struct kfd_process *p, - unsigned int page_index) -{ - struct signal_page *page; - /* - * This is safe because we don't delete signal pages until the - * process exits. + * Compatibility with old user mode: Only use signal slots + * user mode has mapped, may be less than + * KFD_SIGNAL_EVENT_LIMIT. This also allows future increase + * of the event limit without breaking user mode. */ - list_for_each_entry(page, &p->signal_event_pages, event_pages) - if (page->page_index == page_index) - return page; + id = idr_alloc(&p->event_idr, ev, 0, p->signal_mapped_size / 8, + GFP_KERNEL); + if (id < 0) + return id; - return NULL; + ev->event_id = id; + page_slots(p->signal_page)[id] = UNSIGNALED_EVENT_SLOT; + + return 0; } /* @@ -220,99 +124,81 @@ static struct signal_page *lookup_signal_page_by_index(struct kfd_process *p, */ static struct kfd_event *lookup_event_by_id(struct kfd_process *p, uint32_t id) { - struct kfd_event *ev; - - hash_for_each_possible(p->events, ev, events, id) - if (ev->event_id == id) - return ev; - - return NULL; + return idr_find(&p->event_idr, id); } -static u32 make_signal_event_id(struct signal_page *page, - unsigned int signal_slot_index) -{ - return page->page_index | - (signal_slot_index << SIGNAL_EVENT_ID_SLOT_SHIFT); -} - -/* - * Produce a kfd event id for a nonsignal event. - * These are arbitrary numbers, so we do a sequential search through - * the hash table for an unused number. +/** + * lookup_signaled_event_by_partial_id - Lookup signaled event from partial ID + * @p: Pointer to struct kfd_process + * @id: ID to look up + * @bits: Number of valid bits in @id + * + * Finds the first signaled event with a matching partial ID. If no + * matching signaled event is found, returns NULL. In that case the + * caller should assume that the partial ID is invalid and do an + * exhaustive search of all siglaned events. + * + * If multiple events with the same partial ID signal at the same + * time, they will be found one interrupt at a time, not necessarily + * in the same order the interrupts occurred. As long as the number of + * interrupts is correct, all signaled events will be seen by the + * driver. */ -static u32 make_nonsignal_event_id(struct kfd_process *p) +static struct kfd_event *lookup_signaled_event_by_partial_id( + struct kfd_process *p, uint32_t id, uint32_t bits) { - u32 id; - - for (id = p->next_nonsignal_event_id; - id < KFD_LAST_NONSIGNAL_EVENT_ID && - lookup_event_by_id(p, id); - id++) - ; + struct kfd_event *ev; - if (id < KFD_LAST_NONSIGNAL_EVENT_ID) { + if (!p->signal_page || id >= KFD_SIGNAL_EVENT_LIMIT) + return NULL; - /* - * What if id == LAST_NONSIGNAL_EVENT_ID - 1? - * Then next_nonsignal_event_id = LAST_NONSIGNAL_EVENT_ID so - * the first loop fails immediately and we proceed with the - * wraparound loop below. - */ - p->next_nonsignal_event_id = id + 1; + /* Fast path for the common case that @id is not a partial ID + * and we only need a single lookup. + */ + if (bits > 31 || (1U << bits) >= KFD_SIGNAL_EVENT_LIMIT) { + if (page_slots(p->signal_page)[id] == UNSIGNALED_EVENT_SLOT) + return NULL; - return id; + return idr_find(&p->event_idr, id); } - for (id = KFD_FIRST_NONSIGNAL_EVENT_ID; - id < KFD_LAST_NONSIGNAL_EVENT_ID && - lookup_event_by_id(p, id); - id++) - ; - + /* General case for partial IDs: Iterate over all matching IDs + * and find the first one that has signaled. + */ + for (ev = NULL; id < KFD_SIGNAL_EVENT_LIMIT && !ev; id += 1U << bits) { + if (page_slots(p->signal_page)[id] == UNSIGNALED_EVENT_SLOT) + continue; - if (id < KFD_LAST_NONSIGNAL_EVENT_ID) { - p->next_nonsignal_event_id = id + 1; - return id; + ev = idr_find(&p->event_idr, id); } - p->next_nonsignal_event_id = KFD_FIRST_NONSIGNAL_EVENT_ID; - return 0; -} - -static struct kfd_event *lookup_event_by_page_slot(struct kfd_process *p, - struct signal_page *page, - unsigned int signal_slot) -{ - return lookup_event_by_id(p, make_signal_event_id(page, signal_slot)); + return ev; } static int create_signal_event(struct file *devkfd, struct kfd_process *p, struct kfd_event *ev) { - if (p->signal_event_count == KFD_SIGNAL_EVENT_LIMIT) { + int ret; + + if (p->signal_mapped_size && + p->signal_event_count == p->signal_mapped_size / 8) { if (!p->signal_event_limit_reached) { pr_warn("Signal event wasn't created because limit was reached\n"); p->signal_event_limit_reached = true; } - return -ENOMEM; + return -ENOSPC; } - if (!allocate_event_notification_slot(devkfd, p, &ev->signal_page, - &ev->signal_slot_index)) { + ret = allocate_event_notification_slot(p, ev); + if (ret) { pr_warn("Signal event wasn't created because out of kernel memory\n"); - return -ENOMEM; + return ret; } p->signal_event_count++; - ev->user_signal_address = - &ev->signal_page->user_address[ev->signal_slot_index]; - - ev->event_id = make_signal_event_id(ev->signal_page, - ev->signal_slot_index); - + ev->user_signal_address = &p->signal_page->user_address[ev->event_id]; pr_debug("Signal event number %zu created with id %d, address %p\n", p->signal_event_count, ev->event_id, ev->user_signal_address); @@ -320,16 +206,20 @@ static int create_signal_event(struct file *devkfd, return 0; } -/* - * No non-signal events are supported yet. - * We create them as events that never signal. - * Set event calls from user-mode are failed. - */ static int create_other_event(struct kfd_process *p, struct kfd_event *ev) { - ev->event_id = make_nonsignal_event_id(p); - if (ev->event_id == 0) - return -ENOMEM; + /* Cast KFD_LAST_NONSIGNAL_EVENT to uint32_t. This allows an + * intentional integer overflow to -1 without a compiler + * warning. idr_alloc treats a negative value as "maximum + * signed integer". + */ + int id = idr_alloc(&p->event_idr, ev, KFD_FIRST_NONSIGNAL_EVENT_ID, + (uint32_t)KFD_LAST_NONSIGNAL_EVENT_ID + 1, + GFP_KERNEL); + + if (id < 0) + return id; + ev->event_id = id; return 0; } @@ -337,50 +227,47 @@ static int create_other_event(struct kfd_process *p, struct kfd_event *ev) void kfd_event_init_process(struct kfd_process *p) { mutex_init(&p->event_mutex); - hash_init(p->events); - INIT_LIST_HEAD(&p->signal_event_pages); - p->next_nonsignal_event_id = KFD_FIRST_NONSIGNAL_EVENT_ID; + idr_init(&p->event_idr); + p->signal_page = NULL; p->signal_event_count = 0; } static void destroy_event(struct kfd_process *p, struct kfd_event *ev) { - if (ev->signal_page) { - release_event_notification_slot(ev->signal_page, - ev->signal_slot_index); - p->signal_event_count--; - } + struct kfd_event_waiter *waiter; - /* - * Abandon the list of waiters. Individual waiting threads will - * clean up their own data. - */ - list_del(&ev->waiters); + /* Wake up pending waiters. They will return failure */ + list_for_each_entry(waiter, &ev->wq.head, wait.entry) + waiter->event = NULL; + wake_up_all(&ev->wq); + + if (ev->type == KFD_EVENT_TYPE_SIGNAL || + ev->type == KFD_EVENT_TYPE_DEBUG) + p->signal_event_count--; - hash_del(&ev->events); + idr_remove(&p->event_idr, ev->event_id); kfree(ev); } static void destroy_events(struct kfd_process *p) { struct kfd_event *ev; - struct hlist_node *tmp; - unsigned int hash_bkt; + uint32_t id; - hash_for_each_safe(p->events, hash_bkt, tmp, ev, events) + idr_for_each_entry(&p->event_idr, ev, id) destroy_event(p, ev); + idr_destroy(&p->event_idr); } /* * We assume that the process is being destroyed and there is no need to * unmap the pages or keep bookkeeping data in order. */ -static void shutdown_signal_pages(struct kfd_process *p) +static void shutdown_signal_page(struct kfd_process *p) { - struct signal_page *page, *tmp; + struct kfd_signal_page *page = p->signal_page; - list_for_each_entry_safe(page, tmp, &p->signal_event_pages, - event_pages) { + if (page) { free_pages((unsigned long)page->kernel_address, get_order(KFD_SIGNAL_EVENT_LIMIT * 8)); kfree(page); @@ -390,7 +277,7 @@ static void shutdown_signal_pages(struct kfd_process *p) void kfd_event_free_process(struct kfd_process *p) { destroy_events(p); - shutdown_signal_pages(p); + shutdown_signal_page(p); } static bool event_can_be_gpu_signaled(const struct kfd_event *ev) @@ -419,7 +306,7 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, ev->auto_reset = auto_reset; ev->signaled = false; - INIT_LIST_HEAD(&ev->waiters); + init_waitqueue_head(&ev->wq); *event_page_offset = 0; @@ -430,10 +317,9 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, case KFD_EVENT_TYPE_DEBUG: ret = create_signal_event(devkfd, p, ev); if (!ret) { - *event_page_offset = (ev->signal_page->page_index | - KFD_MMAP_EVENTS_MASK); + *event_page_offset = KFD_MMAP_EVENTS_MASK; *event_page_offset <<= PAGE_SHIFT; - *event_slot_index = ev->signal_slot_index; + *event_slot_index = ev->event_id; } break; default: @@ -442,8 +328,6 @@ int kfd_event_create(struct file *devkfd, struct kfd_process *p, } if (!ret) { - hash_add(p->events, &ev->events, ev->event_id); - *event_id = ev->event_id; *event_trigger_data = ev->event_id; } else { @@ -477,19 +361,18 @@ int kfd_event_destroy(struct kfd_process *p, uint32_t event_id) static void set_event(struct kfd_event *ev) { struct kfd_event_waiter *waiter; - struct kfd_event_waiter *next; - /* Auto reset if the list is non-empty and we're waking someone. */ - ev->signaled = !ev->auto_reset || list_empty(&ev->waiters); + /* Auto reset if the list is non-empty and we're waking + * someone. waitqueue_active is safe here because we're + * protected by the p->event_mutex, which is also held when + * updating the wait queues in kfd_wait_on_events. + */ + ev->signaled = !ev->auto_reset || !waitqueue_active(&ev->wq); - list_for_each_entry_safe(waiter, next, &ev->waiters, waiters) { + list_for_each_entry(waiter, &ev->wq.head, wait.entry) waiter->activated = true; - /* _init because free_waiters will call list_del */ - list_del_init(&waiter->waiters); - - wake_up_process(waiter->sleeping_task); - } + wake_up_all(&ev->wq); } /* Assumes that p is current. */ @@ -538,13 +421,7 @@ int kfd_reset_event(struct kfd_process *p, uint32_t event_id) static void acknowledge_signal(struct kfd_process *p, struct kfd_event *ev) { - page_slots(ev->signal_page)[ev->signal_slot_index] = - UNSIGNALED_EVENT_SLOT; -} - -static bool is_slot_signaled(struct signal_page *page, unsigned int index) -{ - return page_slots(page)[index] != UNSIGNALED_EVENT_SLOT; + page_slots(p->signal_page)[ev->event_id] = UNSIGNALED_EVENT_SLOT; } static void set_event_from_interrupt(struct kfd_process *p, @@ -559,7 +436,7 @@ static void set_event_from_interrupt(struct kfd_process *p, void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id, uint32_t valid_id_bits) { - struct kfd_event *ev; + struct kfd_event *ev = NULL; /* * Because we are called from arbitrary context (workqueue) as opposed @@ -573,26 +450,46 @@ void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id, mutex_lock(&p->event_mutex); - if (valid_id_bits >= INTERRUPT_DATA_BITS) { - /* Partial ID is a full ID. */ - ev = lookup_event_by_id(p, partial_id); + if (valid_id_bits) + ev = lookup_signaled_event_by_partial_id(p, partial_id, + valid_id_bits); + if (ev) { set_event_from_interrupt(p, ev); - } else { + } else if (p->signal_page) { /* - * Partial ID is in fact partial. For now we completely - * ignore it, but we could use any bits we did receive to - * search faster. + * Partial ID lookup failed. Assume that the event ID + * in the interrupt payload was invalid and do an + * exhaustive search of signaled events. */ - struct signal_page *page; - unsigned int i; - - list_for_each_entry(page, &p->signal_event_pages, event_pages) - for (i = 0; i < SLOTS_PER_PAGE; i++) - if (is_slot_signaled(page, i)) { - ev = lookup_event_by_page_slot(p, - page, i); + uint64_t *slots = page_slots(p->signal_page); + uint32_t id; + + if (valid_id_bits) + pr_debug_ratelimited("Partial ID invalid: %u (%u valid bits)\n", + partial_id, valid_id_bits); + + if (p->signal_event_count < KFD_SIGNAL_EVENT_LIMIT/2) { + /* With relatively few events, it's faster to + * iterate over the event IDR + */ + idr_for_each_entry(&p->event_idr, ev, id) { + if (id >= KFD_SIGNAL_EVENT_LIMIT) + break; + + if (slots[id] != UNSIGNALED_EVENT_SLOT) + set_event_from_interrupt(p, ev); + } + } else { + /* With relatively many events, it's faster to + * iterate over the signal slots and lookup + * only signaled events from the IDR. + */ + for (id = 0; id < KFD_SIGNAL_EVENT_LIMIT; id++) + if (slots[id] != UNSIGNALED_EVENT_SLOT) { + ev = lookup_event_by_id(p, id); set_event_from_interrupt(p, ev); } + } } mutex_unlock(&p->event_mutex); @@ -609,18 +506,16 @@ static struct kfd_event_waiter *alloc_event_waiters(uint32_t num_events) GFP_KERNEL); for (i = 0; (event_waiters) && (i < num_events) ; i++) { - INIT_LIST_HEAD(&event_waiters[i].waiters); - event_waiters[i].sleeping_task = current; + init_wait(&event_waiters[i].wait); event_waiters[i].activated = false; } return event_waiters; } -static int init_event_waiter(struct kfd_process *p, +static int init_event_waiter_get_status(struct kfd_process *p, struct kfd_event_waiter *waiter, - uint32_t event_id, - uint32_t input_index) + uint32_t event_id) { struct kfd_event *ev = lookup_event_by_id(p, event_id); @@ -628,38 +523,60 @@ static int init_event_waiter(struct kfd_process *p, return -EINVAL; waiter->event = ev; - waiter->input_index = input_index; waiter->activated = ev->signaled; ev->signaled = ev->signaled && !ev->auto_reset; - list_add(&waiter->waiters, &ev->waiters); - return 0; } -static bool test_event_condition(bool all, uint32_t num_events, +static void init_event_waiter_add_to_waitlist(struct kfd_event_waiter *waiter) +{ + struct kfd_event *ev = waiter->event; + + /* Only add to the wait list if we actually need to + * wait on this event. + */ + if (!waiter->activated) + add_wait_queue(&ev->wq, &waiter->wait); +} + +/* test_event_condition - Test condition of events being waited for + * @all: Return completion only if all events have signaled + * @num_events: Number of events to wait for + * @event_waiters: Array of event waiters, one per event + * + * Returns KFD_IOC_WAIT_RESULT_COMPLETE if all (or one) event(s) have + * signaled. Returns KFD_IOC_WAIT_RESULT_TIMEOUT if no (or not all) + * events have signaled. Returns KFD_IOC_WAIT_RESULT_FAIL if any of + * the events have been destroyed. + */ +static uint32_t test_event_condition(bool all, uint32_t num_events, struct kfd_event_waiter *event_waiters) { uint32_t i; uint32_t activated_count = 0; for (i = 0; i < num_events; i++) { + if (!event_waiters[i].event) + return KFD_IOC_WAIT_RESULT_FAIL; + if (event_waiters[i].activated) { if (!all) - return true; + return KFD_IOC_WAIT_RESULT_COMPLETE; activated_count++; } } - return activated_count == num_events; + return activated_count == num_events ? + KFD_IOC_WAIT_RESULT_COMPLETE : KFD_IOC_WAIT_RESULT_TIMEOUT; } /* * Copy event specific data, if defined. * Currently only memory exception events have additional data to copy to user */ -static bool copy_signaled_event_data(uint32_t num_events, +static int copy_signaled_event_data(uint32_t num_events, struct kfd_event_waiter *event_waiters, struct kfd_event_data __user *data) { @@ -673,15 +590,15 @@ static bool copy_signaled_event_data(uint32_t num_events, waiter = &event_waiters[i]; event = waiter->event; if (waiter->activated && event->type == KFD_EVENT_TYPE_MEMORY) { - dst = &data[waiter->input_index].memory_exception_data; + dst = &data[i].memory_exception_data; src = &event->memory_exception_data; if (copy_to_user(dst, src, sizeof(struct kfd_hsa_memory_exception_data))) - return false; + return -EFAULT; } } - return true; + return 0; } @@ -710,7 +627,9 @@ static void free_waiters(uint32_t num_events, struct kfd_event_waiter *waiters) uint32_t i; for (i = 0; i < num_events; i++) - list_del(&waiters[i].waiters); + if (waiters[i].event) + remove_wait_queue(&waiters[i].event->wq, + &waiters[i].wait); kfree(waiters); } @@ -718,38 +637,56 @@ static void free_waiters(uint32_t num_events, struct kfd_event_waiter *waiters) int kfd_wait_on_events(struct kfd_process *p, uint32_t num_events, void __user *data, bool all, uint32_t user_timeout_ms, - enum kfd_event_wait_result *wait_result) + uint32_t *wait_result) { struct kfd_event_data __user *events = (struct kfd_event_data __user *) data; uint32_t i; int ret = 0; + struct kfd_event_waiter *event_waiters = NULL; long timeout = user_timeout_to_jiffies(user_timeout_ms); - mutex_lock(&p->event_mutex); - event_waiters = alloc_event_waiters(num_events); if (!event_waiters) { ret = -ENOMEM; - goto fail; + goto out; } + mutex_lock(&p->event_mutex); + for (i = 0; i < num_events; i++) { struct kfd_event_data event_data; if (copy_from_user(&event_data, &events[i], sizeof(struct kfd_event_data))) { ret = -EFAULT; - goto fail; + goto out_unlock; } - ret = init_event_waiter(p, &event_waiters[i], - event_data.event_id, i); + ret = init_event_waiter_get_status(p, &event_waiters[i], + event_data.event_id); if (ret) - goto fail; + goto out_unlock; } + /* Check condition once. */ + *wait_result = test_event_condition(all, num_events, event_waiters); + if (*wait_result == KFD_IOC_WAIT_RESULT_COMPLETE) { + ret = copy_signaled_event_data(num_events, + event_waiters, events); + goto out_unlock; + } else if (WARN_ON(*wait_result == KFD_IOC_WAIT_RESULT_FAIL)) { + /* This should not happen. Events shouldn't be + * destroyed while we're holding the event_mutex + */ + goto out_unlock; + } + + /* Add to wait lists if we need to wait. */ + for (i = 0; i < num_events; i++) + init_event_waiter_add_to_waitlist(&event_waiters[i]); + mutex_unlock(&p->event_mutex); while (true) { @@ -771,62 +708,66 @@ int kfd_wait_on_events(struct kfd_process *p, break; } - if (test_event_condition(all, num_events, event_waiters)) { - if (copy_signaled_event_data(num_events, - event_waiters, events)) - *wait_result = KFD_WAIT_COMPLETE; - else - *wait_result = KFD_WAIT_ERROR; + /* Set task state to interruptible sleep before + * checking wake-up conditions. A concurrent wake-up + * will put the task back into runnable state. In that + * case schedule_timeout will not put the task to + * sleep and we'll get a chance to re-check the + * updated conditions almost immediately. Otherwise, + * this race condition would lead to a soft hang or a + * very long sleep. + */ + set_current_state(TASK_INTERRUPTIBLE); + + *wait_result = test_event_condition(all, num_events, + event_waiters); + if (*wait_result != KFD_IOC_WAIT_RESULT_TIMEOUT) break; - } - if (timeout <= 0) { - *wait_result = KFD_WAIT_TIMEOUT; + if (timeout <= 0) break; - } - timeout = schedule_timeout_interruptible(timeout); + timeout = schedule_timeout(timeout); } __set_current_state(TASK_RUNNING); + /* copy_signaled_event_data may sleep. So this has to happen + * after the task state is set back to RUNNING. + */ + if (!ret && *wait_result == KFD_IOC_WAIT_RESULT_COMPLETE) + ret = copy_signaled_event_data(num_events, + event_waiters, events); + mutex_lock(&p->event_mutex); +out_unlock: free_waiters(num_events, event_waiters); mutex_unlock(&p->event_mutex); - - return ret; - -fail: - if (event_waiters) - free_waiters(num_events, event_waiters); - - mutex_unlock(&p->event_mutex); - - *wait_result = KFD_WAIT_ERROR; +out: + if (ret) + *wait_result = KFD_IOC_WAIT_RESULT_FAIL; + else if (*wait_result == KFD_IOC_WAIT_RESULT_FAIL) + ret = -EIO; return ret; } int kfd_event_mmap(struct kfd_process *p, struct vm_area_struct *vma) { - - unsigned int page_index; unsigned long pfn; - struct signal_page *page; + struct kfd_signal_page *page; + int ret; - /* check required size is logical */ - if (get_order(KFD_SIGNAL_EVENT_LIMIT * 8) != + /* check required size doesn't exceed the allocated size */ + if (get_order(KFD_SIGNAL_EVENT_LIMIT * 8) < get_order(vma->vm_end - vma->vm_start)) { pr_err("Event page mmap requested illegal size\n"); return -EINVAL; } - page_index = vma->vm_pgoff; - - page = lookup_signal_page_by_index(p, page_index); + page = p->signal_page; if (!page) { /* Probably KFD bug, but mmap is user-accessible. */ - pr_debug("Signal page could not be found for page_index %u\n", - page_index); + pr_debug("Signal page could not be found\n"); return -EINVAL; } @@ -847,8 +788,12 @@ int kfd_event_mmap(struct kfd_process *p, struct vm_area_struct *vma) page->user_address = (uint64_t __user *)vma->vm_start; /* mapping the page to user process */ - return remap_pfn_range(vma, vma->vm_start, pfn, + ret = remap_pfn_range(vma, vma->vm_start, pfn, vma->vm_end - vma->vm_start, vma->vm_page_prot); + if (!ret) + p->signal_mapped_size = vma->vm_end - vma->vm_start; + + return ret; } /* @@ -860,12 +805,13 @@ static void lookup_events_by_type_and_signal(struct kfd_process *p, { struct kfd_hsa_memory_exception_data *ev_data; struct kfd_event *ev; - int bkt; + uint32_t id; bool send_signal = true; ev_data = (struct kfd_hsa_memory_exception_data *) event_data; - hash_for_each(p->events, bkt, ev, events) + id = KFD_FIRST_NONSIGNAL_EVENT_ID; + idr_for_each_entry_continue(&p->event_idr, ev, id) if (ev->type == type) { send_signal = false; dev_dbg(kfd_device, @@ -904,14 +850,24 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid, * running so the lookup function returns a locked process. */ struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); + struct mm_struct *mm; if (!p) return; /* Presumably process exited. */ + /* Take a safe reference to the mm_struct, which may otherwise + * disappear even while the kfd_process is still referenced. + */ + mm = get_task_mm(p->lead_thread); + if (!mm) { + mutex_unlock(&p->mutex); + return; /* Process is exiting */ + } + memset(&memory_exception_data, 0, sizeof(memory_exception_data)); - down_read(&p->mm->mmap_sem); - vma = find_vma(p->mm, address); + down_read(&mm->mmap_sem); + vma = find_vma(mm, address); memory_exception_data.gpu_id = dev->id; memory_exception_data.va = address; @@ -937,7 +893,8 @@ void kfd_signal_iommu_event(struct kfd_dev *dev, unsigned int pasid, } } - up_read(&p->mm->mmap_sem); + up_read(&mm->mmap_sem); + mmput(mm); mutex_lock(&p->event_mutex); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_events.h b/drivers/gpu/drm/amd/amdkfd/kfd_events.h index 28f6838b1f4c..abca5bfebbff 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_events.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_events.h @@ -27,12 +27,17 @@ #include <linux/hashtable.h> #include <linux/types.h> #include <linux/list.h> +#include <linux/wait.h> #include "kfd_priv.h" #include <uapi/linux/kfd_ioctl.h> -#define KFD_EVENT_ID_NONSIGNAL_MASK 0x80000000U -#define KFD_FIRST_NONSIGNAL_EVENT_ID KFD_EVENT_ID_NONSIGNAL_MASK -#define KFD_LAST_NONSIGNAL_EVENT_ID UINT_MAX +/* + * IDR supports non-negative integer IDs. Small IDs are used for + * signal events to match their signal slot. Use the upper half of the + * ID space for non-signal events. + */ +#define KFD_FIRST_NONSIGNAL_EVENT_ID ((INT_MAX >> 1) + 1) +#define KFD_LAST_NONSIGNAL_EVENT_ID INT_MAX /* * Written into kfd_signal_slot_t to indicate that the event is not signaled. @@ -46,9 +51,6 @@ struct kfd_event_waiter; struct signal_page; struct kfd_event { - /* All events in process, rooted at kfd_process.events. */ - struct hlist_node events; - u32 event_id; bool signaled; @@ -56,11 +58,9 @@ struct kfd_event { int type; - struct list_head waiters; /* List of kfd_event_waiter by waiters. */ + wait_queue_head_t wq; /* List of event waiters. */ /* Only for signal events. */ - struct signal_page *signal_page; - unsigned int signal_slot_index; uint64_t __user *user_signal_address; /* type specific data */ diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c index 70b3a99cffc2..035c351f47c5 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_interrupt.c @@ -42,26 +42,26 @@ #include <linux/slab.h> #include <linux/device.h> +#include <linux/kfifo.h> #include "kfd_priv.h" -#define KFD_INTERRUPT_RING_SIZE 1024 +#define KFD_IH_NUM_ENTRIES 8192 static void interrupt_wq(struct work_struct *); int kfd_interrupt_init(struct kfd_dev *kfd) { - void *interrupt_ring = kmalloc_array(KFD_INTERRUPT_RING_SIZE, - kfd->device_info->ih_ring_entry_size, - GFP_KERNEL); - if (!interrupt_ring) - return -ENOMEM; - - kfd->interrupt_ring = interrupt_ring; - kfd->interrupt_ring_size = - KFD_INTERRUPT_RING_SIZE * kfd->device_info->ih_ring_entry_size; - atomic_set(&kfd->interrupt_ring_wptr, 0); - atomic_set(&kfd->interrupt_ring_rptr, 0); + int r; + + r = kfifo_alloc(&kfd->ih_fifo, + KFD_IH_NUM_ENTRIES * kfd->device_info->ih_ring_entry_size, + GFP_KERNEL); + if (r) { + dev_err(kfd_chardev(), "Failed to allocate IH fifo\n"); + return r; + } + kfd->ih_wq = alloc_workqueue("KFD IH", WQ_HIGHPRI, 1); spin_lock_init(&kfd->interrupt_lock); INIT_WORK(&kfd->interrupt_work, interrupt_wq); @@ -92,74 +92,47 @@ void kfd_interrupt_exit(struct kfd_dev *kfd) spin_unlock_irqrestore(&kfd->interrupt_lock, flags); /* - * Flush_scheduled_work ensures that there are no outstanding + * flush_work ensures that there are no outstanding * work-queue items that will access interrupt_ring. New work items * can't be created because we stopped interrupt handling above. */ - flush_scheduled_work(); + flush_workqueue(kfd->ih_wq); - kfree(kfd->interrupt_ring); + kfifo_free(&kfd->ih_fifo); } /* - * This assumes that it can't be called concurrently with itself - * but only with dequeue_ih_ring_entry. + * Assumption: single reader/writer. This function is not re-entrant */ bool enqueue_ih_ring_entry(struct kfd_dev *kfd, const void *ih_ring_entry) { - unsigned int rptr = atomic_read(&kfd->interrupt_ring_rptr); - unsigned int wptr = atomic_read(&kfd->interrupt_ring_wptr); + int count; - if ((rptr - wptr) % kfd->interrupt_ring_size == - kfd->device_info->ih_ring_entry_size) { - /* This is very bad, the system is likely to hang. */ + count = kfifo_in(&kfd->ih_fifo, ih_ring_entry, + kfd->device_info->ih_ring_entry_size); + if (count != kfd->device_info->ih_ring_entry_size) { dev_err_ratelimited(kfd_chardev(), - "Interrupt ring overflow, dropping interrupt.\n"); + "Interrupt ring overflow, dropping interrupt %d\n", + count); return false; } - memcpy(kfd->interrupt_ring + wptr, ih_ring_entry, - kfd->device_info->ih_ring_entry_size); - - wptr = (wptr + kfd->device_info->ih_ring_entry_size) % - kfd->interrupt_ring_size; - smp_wmb(); /* Ensure memcpy'd data is visible before wptr update. */ - atomic_set(&kfd->interrupt_ring_wptr, wptr); - return true; } /* - * This assumes that it can't be called concurrently with itself - * but only with enqueue_ih_ring_entry. + * Assumption: single reader/writer. This function is not re-entrant */ static bool dequeue_ih_ring_entry(struct kfd_dev *kfd, void *ih_ring_entry) { - /* - * Assume that wait queues have an implicit barrier, i.e. anything that - * happened in the ISR before it queued work is visible. - */ - - unsigned int wptr = atomic_read(&kfd->interrupt_ring_wptr); - unsigned int rptr = atomic_read(&kfd->interrupt_ring_rptr); + int count; - if (rptr == wptr) - return false; - - memcpy(ih_ring_entry, kfd->interrupt_ring + rptr, - kfd->device_info->ih_ring_entry_size); - - rptr = (rptr + kfd->device_info->ih_ring_entry_size) % - kfd->interrupt_ring_size; + count = kfifo_out(&kfd->ih_fifo, ih_ring_entry, + kfd->device_info->ih_ring_entry_size); - /* - * Ensure the rptr write update is not visible until - * memcpy has finished reading. - */ - smp_mb(); - atomic_set(&kfd->interrupt_ring_rptr, rptr); + WARN_ON(count && count != kfd->device_info->ih_ring_entry_size); - return true; + return count == kfd->device_info->ih_ring_entry_size; } static void interrupt_wq(struct work_struct *work) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c index ed71ad40e8f7..8b0c0645d7c0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c @@ -185,7 +185,7 @@ static void uninitialize(struct kernel_queue *kq) kq->mqd->destroy_mqd(kq->mqd, kq->queue->mqd, KFD_PREEMPT_TYPE_WAVEFRONT_RESET, - QUEUE_PREEMPT_DEFAULT_TIMEOUT_MS, + KFD_UNMAP_LATENCY_MS, kq->queue->pipe, kq->queue->queue); else if (kq->queue->properties.type == KFD_QUEUE_TYPE_DIQ) @@ -303,14 +303,20 @@ struct kernel_queue *kernel_queue_init(struct kfd_dev *dev, case CHIP_KAVERI: kernel_queue_init_cik(&kq->ops_asic_specific); break; + default: + WARN(1, "Unexpected ASIC family %u", + dev->device_info->asic_family); + goto out_free; } - if (!kq->ops.initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE)) { - pr_err("Failed to init kernel queue\n"); - kfree(kq); - return NULL; - } - return kq; + if (kq->ops.initialize(kq, dev, type, KFD_KERNEL_QUEUE_SIZE)) + return kq; + + pr_err("Failed to init kernel queue\n"); + +out_free: + kfree(kq); + return NULL; } void kernel_queue_uninit(struct kernel_queue *kq) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c index b1ef1368c3bb..dfd260ef81ff 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager.c @@ -31,6 +31,9 @@ struct mqd_manager *mqd_manager_init(enum KFD_MQD_TYPE type, return mqd_manager_init_cik(type, dev); case CHIP_CARRIZO: return mqd_manager_init_vi(type, dev); + default: + WARN(1, "Unexpected ASIC family %u", + dev->device_info->asic_family); } return NULL; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c index 44ffd23348fc..4859d263fa2a 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_cik.c @@ -189,12 +189,9 @@ static int update_mqd(struct mqd_manager *mm, void *mqd, if (q->format == KFD_QUEUE_FORMAT_AQL) m->cp_hqd_pq_control |= NO_UPDATE_RPTR; - q->is_active = false; - if (q->queue_size > 0 && + q->is_active = (q->queue_size > 0 && q->queue_address != 0 && - q->queue_percent > 0) { - q->is_active = true; - } + q->queue_percent > 0); return 0; } @@ -215,24 +212,17 @@ static int update_mqd_sdma(struct mqd_manager *mm, void *mqd, m->sdma_rlc_rb_base_hi = upper_32_bits(q->queue_address >> 8); m->sdma_rlc_rb_rptr_addr_lo = lower_32_bits((uint64_t)q->read_ptr); m->sdma_rlc_rb_rptr_addr_hi = upper_32_bits((uint64_t)q->read_ptr); - m->sdma_rlc_doorbell = q->doorbell_off << - SDMA0_RLC0_DOORBELL__OFFSET__SHIFT | - 1 << SDMA0_RLC0_DOORBELL__ENABLE__SHIFT; + m->sdma_rlc_doorbell = + q->doorbell_off << SDMA0_RLC0_DOORBELL__OFFSET__SHIFT; m->sdma_rlc_virtual_addr = q->sdma_vm_addr; m->sdma_engine_id = q->sdma_engine_id; m->sdma_queue_id = q->sdma_queue_id; - q->is_active = false; - if (q->queue_size > 0 && + q->is_active = (q->queue_size > 0 && q->queue_address != 0 && - q->queue_percent > 0) { - m->sdma_rlc_rb_cntl |= - 1 << SDMA0_RLC0_RB_CNTL__RB_ENABLE__SHIFT; - - q->is_active = true; - } + q->queue_percent > 0); return 0; } @@ -359,19 +349,13 @@ static int update_mqd_hiq(struct mqd_manager *mm, void *mqd, m->cp_hqd_pq_base_hi = upper_32_bits((uint64_t)q->queue_address >> 8); m->cp_hqd_pq_rptr_report_addr_lo = lower_32_bits((uint64_t)q->read_ptr); m->cp_hqd_pq_rptr_report_addr_hi = upper_32_bits((uint64_t)q->read_ptr); - m->cp_hqd_pq_doorbell_control = DOORBELL_EN | - DOORBELL_OFFSET(q->doorbell_off); + m->cp_hqd_pq_doorbell_control = DOORBELL_OFFSET(q->doorbell_off); m->cp_hqd_vmid = q->vmid; - m->cp_hqd_active = 0; - q->is_active = false; - if (q->queue_size > 0 && + q->is_active = (q->queue_size > 0 && q->queue_address != 0 && - q->queue_percent > 0) { - m->cp_hqd_active = 1; - q->is_active = true; - } + q->queue_percent > 0); return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c index 73cbfe186dd2..4ea854f9007b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_vi.c @@ -163,12 +163,9 @@ static int __update_mqd(struct mqd_manager *mm, void *mqd, 2 << CP_HQD_PQ_CONTROL__SLOT_BASED_WPTR__SHIFT; } - q->is_active = false; - if (q->queue_size > 0 && + q->is_active = (q->queue_size > 0 && q->queue_address != 0 && - q->queue_percent > 0) { - q->is_active = true; - } + q->queue_percent > 0); return 0; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c index 1d312603de9f..16da8ad02d8b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c @@ -140,8 +140,6 @@ static int pm_create_map_process(struct packet_manager *pm, uint32_t *buffer, struct qcm_process_device *qpd) { struct pm4_mes_map_process *packet; - struct queue *cur; - uint32_t num_queues; packet = (struct pm4_mes_map_process *)buffer; @@ -156,10 +154,7 @@ static int pm_create_map_process(struct packet_manager *pm, uint32_t *buffer, packet->bitfields10.gds_size = qpd->gds_size; packet->bitfields10.num_gws = qpd->num_gws; packet->bitfields10.num_oac = qpd->num_oac; - num_queues = 0; - list_for_each_entry(cur, &qpd->queues_list, list) - num_queues++; - packet->bitfields10.num_queues = (qpd->is_debug) ? 0 : num_queues; + packet->bitfields10.num_queues = (qpd->is_debug) ? 0 : qpd->queue_count; packet->sh_mem_config = qpd->sh_mem_config; packet->sh_mem_bases = qpd->sh_mem_bases; @@ -208,7 +203,7 @@ static int pm_create_map_queue(struct packet_manager *pm, uint32_t *buffer, queue_type__mes_map_queues__debug_interface_queue_vi; break; case KFD_QUEUE_TYPE_SDMA: - packet->bitfields2.engine_sel = + packet->bitfields2.engine_sel = q->properties.sdma_engine_id + engine_sel__mes_map_queues__sdma0_vi; use_static = false; /* no static queues under SDMA */ break; @@ -376,7 +371,7 @@ int pm_send_set_resources(struct packet_manager *pm, packet->bitfields2.queue_type = queue_type__mes_set_resources__hsa_interface_queue_hiq; packet->bitfields2.vmid_mask = res->vmid_mask; - packet->bitfields2.unmap_latency = KFD_UNMAP_LATENCY; + packet->bitfields2.unmap_latency = KFD_UNMAP_LATENCY_MS / 100; packet->bitfields7.oac_mask = res->oac_mask; packet->bitfields8.gds_heap_base = res->gds_heap_base; packet->bitfields8.gds_heap_size = res->gds_heap_size; @@ -476,7 +471,7 @@ fail_acquire_packet_buffer: } int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, - enum kfd_preempt_type_filter mode, + enum kfd_unmap_queues_filter filter, uint32_t filter_param, bool reset, unsigned int sdma_engine) { @@ -494,8 +489,8 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, packet = (struct pm4_mes_unmap_queues *)buffer; memset(buffer, 0, sizeof(struct pm4_mes_unmap_queues)); - pr_debug("static_queue: unmapping queues: mode is %d , reset is %d , type is %d\n", - mode, reset, type); + pr_debug("static_queue: unmapping queues: filter is %d , reset is %d , type is %d\n", + filter, reset, type); packet->header.u32All = build_pm4_header(IT_UNMAP_QUEUES, sizeof(struct pm4_mes_unmap_queues)); switch (type) { @@ -521,29 +516,29 @@ int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, packet->bitfields2.action = action__mes_unmap_queues__preempt_queues; - switch (mode) { - case KFD_PREEMPT_TYPE_FILTER_SINGLE_QUEUE: + switch (filter) { + case KFD_UNMAP_QUEUES_FILTER_SINGLE_QUEUE: packet->bitfields2.queue_sel = queue_sel__mes_unmap_queues__perform_request_on_specified_queues; packet->bitfields2.num_queues = 1; packet->bitfields3b.doorbell_offset0 = filter_param; break; - case KFD_PREEMPT_TYPE_FILTER_BY_PASID: + case KFD_UNMAP_QUEUES_FILTER_BY_PASID: packet->bitfields2.queue_sel = queue_sel__mes_unmap_queues__perform_request_on_pasid_queues; packet->bitfields3a.pasid = filter_param; break; - case KFD_PREEMPT_TYPE_FILTER_ALL_QUEUES: + case KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES: packet->bitfields2.queue_sel = queue_sel__mes_unmap_queues__unmap_all_queues; break; - case KFD_PREEMPT_TYPE_FILTER_DYNAMIC_QUEUES: + case KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES: /* in this case, we do not preempt static queues */ packet->bitfields2.queue_sel = queue_sel__mes_unmap_queues__unmap_all_non_static_queues; break; default: - WARN(1, "filter %d", mode); + WARN(1, "filter %d", filter); retval = -EINVAL; goto err_invalid; } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 634083e340d1..9e4134c5b481 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -31,8 +31,12 @@ #include <linux/workqueue.h> #include <linux/spinlock.h> #include <linux/kfd_ioctl.h> +#include <linux/idr.h> +#include <linux/kfifo.h> #include <kgd_kfd_interface.h> +#include "amd_shared.h" + #define KFD_SYSFS_FILE_MODE 0444 #define KFD_MMAP_DOORBELL_MASK 0x8000000000000 @@ -112,11 +116,6 @@ enum cache_policy { cache_policy_noncoherent }; -enum asic_family_type { - CHIP_KAVERI = 0, - CHIP_CARRIZO -}; - struct kfd_event_interrupt_class { bool (*interrupt_isr)(struct kfd_dev *dev, const uint32_t *ih_ring_entry); @@ -125,7 +124,7 @@ struct kfd_event_interrupt_class { }; struct kfd_device_info { - unsigned int asic_family; + enum amd_asic_type asic_family; const struct kfd_event_interrupt_class *event_interrupt_class; unsigned int max_pasid_bits; unsigned int max_no_of_hqd; @@ -141,6 +140,12 @@ struct kfd_mem_obj { uint32_t *cpu_ptr; }; +struct kfd_vmid_info { + uint32_t first_vmid_kfd; + uint32_t last_vmid_kfd; + uint32_t vmid_num_kfd; +}; + struct kfd_dev { struct kgd_dev *kgd; @@ -162,6 +167,7 @@ struct kfd_dev { */ struct kgd2kfd_shared_resources shared_resources; + struct kfd_vmid_info vm_info; const struct kfd2kgd_calls *kfd2kgd; struct mutex doorbell_mutex; @@ -177,10 +183,8 @@ struct kfd_dev { unsigned int gtt_sa_num_of_chunks; /* Interrupts */ - void *interrupt_ring; - size_t interrupt_ring_size; - atomic_t interrupt_ring_rptr; - atomic_t interrupt_ring_wptr; + struct kfifo ih_fifo; + struct workqueue_struct *ih_wq; struct work_struct interrupt_work; spinlock_t interrupt_lock; @@ -218,22 +222,22 @@ void kfd_chardev_exit(void); struct device *kfd_chardev(void); /** - * enum kfd_preempt_type_filter + * enum kfd_unmap_queues_filter * - * @KFD_PREEMPT_TYPE_FILTER_SINGLE_QUEUE: Preempts single queue. + * @KFD_UNMAP_QUEUES_FILTER_SINGLE_QUEUE: Preempts single queue. * - * @KFD_PRERMPT_TYPE_FILTER_ALL_QUEUES: Preempts all queues in the + * @KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES: Preempts all queues in the * running queues list. * - * @KFD_PRERMPT_TYPE_FILTER_BY_PASID: Preempts queues that belongs to + * @KFD_UNMAP_QUEUES_FILTER_BY_PASID: Preempts queues that belongs to * specific process. * */ -enum kfd_preempt_type_filter { - KFD_PREEMPT_TYPE_FILTER_SINGLE_QUEUE, - KFD_PREEMPT_TYPE_FILTER_ALL_QUEUES, - KFD_PREEMPT_TYPE_FILTER_DYNAMIC_QUEUES, - KFD_PREEMPT_TYPE_FILTER_BY_PASID +enum kfd_unmap_queues_filter { + KFD_UNMAP_QUEUES_FILTER_SINGLE_QUEUE, + KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES, + KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, + KFD_UNMAP_QUEUES_FILTER_BY_PASID }; /** @@ -401,7 +405,6 @@ struct scheduling_resources { struct process_queue_manager { /* data */ struct kfd_process *process; - unsigned int num_concurrent_processes; struct list_head queues; unsigned long *queue_slot_bitmap; }; @@ -417,6 +420,12 @@ struct qcm_process_device { unsigned int queue_count; unsigned int vmid; bool is_debug; + + /* This flag tells if we should reset all wavefronts on + * process termination + */ + bool reset_wavefronts; + /* * All the memory management data should be here too */ @@ -432,6 +441,13 @@ struct qcm_process_device { uint32_t sh_hidden_private_base; }; + +enum kfd_pdd_bound { + PDD_UNBOUND = 0, + PDD_BOUND, + PDD_BOUND_SUSPENDED, +}; + /* Data that is per-process-per device. */ struct kfd_process_device { /* @@ -443,6 +459,8 @@ struct kfd_process_device { /* The device that owns this data. */ struct kfd_dev *dev; + /* The process that owns this kfd_process_device. */ + struct kfd_process *process; /* per-process-per device QCM data structure */ struct qcm_process_device qpd; @@ -456,12 +474,14 @@ struct kfd_process_device { uint64_t scratch_limit; /* Is this process/pasid bound to this device? (amd_iommu_bind_pasid) */ - bool bound; + enum kfd_pdd_bound bound; - /* This flag tells if we should reset all - * wavefronts on process termination + /* Flag used to tell the pdd has dequeued from the dqm. + * This is used to prevent dev->dqm->ops.process_termination() from + * being called twice when it is already called in IOMMU callback + * function. */ - bool reset_wavefronts; + bool already_dequeued; }; #define qpd_to_pdd(x) container_of(x, struct kfd_process_device, qpd) @@ -474,7 +494,12 @@ struct kfd_process { */ struct hlist_node kfd_processes; - struct mm_struct *mm; + /* + * Opaque pointer to mm_struct. We don't hold a reference to + * it so it should never be dereferenced from here. This is + * only used for looking up processes by their mm. + */ + void *mm; struct mutex mutex; @@ -482,6 +507,8 @@ struct kfd_process { * In any process, the thread that started main() is the lead * thread and outlives the rest. * It is here because amd_iommu_bind_pasid wants a task_struct. + * It can also be used for safely getting a reference to the + * mm_struct of the process. */ struct task_struct *lead_thread; @@ -502,22 +529,16 @@ struct kfd_process { struct process_queue_manager pqm; - /* The process's queues. */ - size_t queue_array_size; - - /* Size is queue_array_size, up to MAX_PROCESS_QUEUES. */ - struct kfd_queue **queues; - /*Is the user space process 32 bit?*/ bool is_32bit_user_mode; /* Event-related data */ struct mutex event_mutex; - /* All events in process hashed by ID, linked on kfd_event.events. */ - DECLARE_HASHTABLE(events, 4); - /* struct slot_page_header.event_pages */ - struct list_head signal_event_pages; - u32 next_nonsignal_event_id; + /* Event ID allocator and lookup */ + struct idr event_idr; + /* Event page */ + struct kfd_signal_page *signal_page; + size_t signal_mapped_size; size_t signal_event_count; bool signal_event_limit_reached; }; @@ -547,8 +568,10 @@ struct kfd_process *kfd_get_process(const struct task_struct *); struct kfd_process *kfd_lookup_process_by_pasid(unsigned int pasid); struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev, - struct kfd_process *p); -void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid); + struct kfd_process *p); +int kfd_bind_processes_to_device(struct kfd_dev *dev); +void kfd_unbind_processes_from_device(struct kfd_dev *dev); +void kfd_process_iommu_unbind_callback(struct kfd_dev *dev, unsigned int pasid); struct kfd_process_device *kfd_get_process_device_data(struct kfd_dev *dev, struct kfd_process *p); struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, @@ -646,14 +669,14 @@ struct process_queue_node { struct list_head process_queue_list; }; +void kfd_process_dequeue_from_device(struct kfd_process_device *pdd); +void kfd_process_dequeue_from_all_devices(struct kfd_process *p); int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p); void pqm_uninit(struct process_queue_manager *pqm); int pqm_create_queue(struct process_queue_manager *pqm, struct kfd_dev *dev, struct file *f, struct queue_properties *properties, - unsigned int flags, - enum kfd_queue_type type, unsigned int *qid); int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid); int pqm_update_queue(struct process_queue_manager *pqm, unsigned int qid, @@ -663,15 +686,12 @@ struct kernel_queue *pqm_get_kernel_queue(struct process_queue_manager *pqm, int amdkfd_fence_wait_timeout(unsigned int *fence_addr, unsigned int fence_value, - unsigned long timeout); + unsigned int timeout_ms); /* Packet Manager */ -#define KFD_HIQ_TIMEOUT (500) - #define KFD_FENCE_COMPLETED (100) #define KFD_FENCE_INIT (10) -#define KFD_UNMAP_LATENCY (150) struct packet_manager { struct device_queue_manager *dqm; @@ -690,7 +710,7 @@ int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, uint32_t fence_value); int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, - enum kfd_preempt_type_filter mode, + enum kfd_unmap_queues_filter mode, uint32_t filter_param, bool reset, unsigned int sdma_engine); @@ -702,19 +722,13 @@ uint64_t kfd_get_number_elems(struct kfd_dev *kfd); extern const struct kfd_event_interrupt_class event_interrupt_class_cik; extern const struct kfd_device_global_init_class device_global_init_class_cik; -enum kfd_event_wait_result { - KFD_WAIT_COMPLETE, - KFD_WAIT_TIMEOUT, - KFD_WAIT_ERROR -}; - void kfd_event_init_process(struct kfd_process *p); void kfd_event_free_process(struct kfd_process *p); int kfd_event_mmap(struct kfd_process *process, struct vm_area_struct *vma); int kfd_wait_on_events(struct kfd_process *p, uint32_t num_events, void __user *data, bool all, uint32_t user_timeout_ms, - enum kfd_event_wait_result *wait_result); + uint32_t *wait_result); void kfd_signal_event_interrupt(unsigned int pasid, uint32_t partial_id, uint32_t valid_id_bits); void kfd_signal_iommu_event(struct kfd_dev *dev, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 9e65ce3c1967..1f5ccd28bd41 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -35,13 +35,6 @@ struct mm_struct; #include "kfd_dbgmgr.h" /* - * Initial size for the array of queues. - * The allocated size is doubled each time - * it is exceeded up to MAX_PROCESS_QUEUES. - */ -#define INITIAL_QUEUE_ARRAY_SIZE 16 - -/* * List of struct kfd_process (field kfd_process). * Unique/indexed by mm_struct* */ @@ -171,12 +164,10 @@ static void kfd_process_wq_release(struct work_struct *work) pr_debug("Releasing pdd (topology id %d) for process (pasid %d) in workqueue\n", pdd->dev->id, p->pasid); - if (pdd->reset_wavefronts) - dbgdev_wave_reset_wavefronts(pdd->dev, p); + if (pdd->bound == PDD_BOUND) + amd_iommu_unbind_pasid(pdd->dev->pdev, p->pasid); - amd_iommu_unbind_pasid(pdd->dev->pdev, p->pasid); list_del(&pdd->per_device_list); - kfree(pdd); } @@ -189,8 +180,6 @@ static void kfd_process_wq_release(struct work_struct *work) mutex_destroy(&p->mutex); - kfree(p->queues); - kfree(p); kfree(work); @@ -202,7 +191,6 @@ static void kfd_process_destroy_delayed(struct rcu_head *rcu) struct kfd_process *p; p = container_of(rcu, struct kfd_process, rcu); - WARN_ON(atomic_read(&p->mm->mm_count) <= 0); mmdrop(p->mm); @@ -236,24 +224,26 @@ static void kfd_process_notifier_release(struct mmu_notifier *mn, mutex_lock(&p->mutex); - /* In case our notifier is called before IOMMU notifier */ - pqm_uninit(&p->pqm); - - /* Iterate over all process device data structure and check - * if we should delete debug managers and reset all wavefronts + /* Iterate over all process device data structures and if the + * pdd is in debug mode, we should first force unregistration, + * then we will be able to destroy the queues */ list_for_each_entry(pdd, &p->per_device_data, per_device_list) { - if ((pdd->dev->dbgmgr) && - (pdd->dev->dbgmgr->pasid == p->pasid)) - kfd_dbgmgr_destroy(pdd->dev->dbgmgr); - - if (pdd->reset_wavefronts) { - pr_warn("Resetting all wave fronts\n"); - dbgdev_wave_reset_wavefronts(pdd->dev, p); - pdd->reset_wavefronts = false; + struct kfd_dev *dev = pdd->dev; + + mutex_lock(kfd_get_dbgmgr_mutex()); + if (dev && dev->dbgmgr && dev->dbgmgr->pasid == p->pasid) { + if (!kfd_dbgmgr_unregister(dev->dbgmgr, p)) { + kfd_dbgmgr_destroy(dev->dbgmgr); + dev->dbgmgr = NULL; + } } + mutex_unlock(kfd_get_dbgmgr_mutex()); } + kfd_process_dequeue_from_all_devices(p); + pqm_uninit(&p->pqm); + mutex_unlock(&p->mutex); /* @@ -280,11 +270,6 @@ static struct kfd_process *create_process(const struct task_struct *thread) if (!process) goto err_alloc_process; - process->queues = kmalloc_array(INITIAL_QUEUE_ARRAY_SIZE, - sizeof(process->queues[0]), GFP_KERNEL); - if (!process->queues) - goto err_alloc_queues; - process->pasid = kfd_pasid_alloc(); if (process->pasid == 0) goto err_alloc_pasid; @@ -307,8 +292,6 @@ static struct kfd_process *create_process(const struct task_struct *thread) process->lead_thread = thread->group_leader; - process->queue_array_size = INITIAL_QUEUE_ARRAY_SIZE; - INIT_LIST_HEAD(&process->per_device_data); kfd_event_init_process(process); @@ -337,8 +320,6 @@ err_mmu_notifier: err_alloc_doorbells: kfd_pasid_free(process->pasid); err_alloc_pasid: - kfree(process->queues); -err_alloc_queues: kfree(process); err_alloc_process: return ERR_PTR(err); @@ -351,9 +332,9 @@ struct kfd_process_device *kfd_get_process_device_data(struct kfd_dev *dev, list_for_each_entry(pdd, &p->per_device_data, per_device_list) if (pdd->dev == dev) - break; + return pdd; - return pdd; + return NULL; } struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, @@ -367,7 +348,9 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, INIT_LIST_HEAD(&pdd->qpd.queues_list); INIT_LIST_HEAD(&pdd->qpd.priv_queue_list); pdd->qpd.dqm = dev->dqm; - pdd->reset_wavefronts = false; + pdd->process = p; + pdd->bound = PDD_UNBOUND; + pdd->already_dequeued = false; list_add(&pdd->per_device_list, &p->per_device_data); } @@ -393,19 +376,87 @@ struct kfd_process_device *kfd_bind_process_to_device(struct kfd_dev *dev, return ERR_PTR(-ENOMEM); } - if (pdd->bound) + if (pdd->bound == PDD_BOUND) { return pdd; + } else if (unlikely(pdd->bound == PDD_BOUND_SUSPENDED)) { + pr_err("Binding PDD_BOUND_SUSPENDED pdd is unexpected!\n"); + return ERR_PTR(-EINVAL); + } err = amd_iommu_bind_pasid(dev->pdev, p->pasid, p->lead_thread); if (err < 0) return ERR_PTR(err); - pdd->bound = true; + pdd->bound = PDD_BOUND; return pdd; } -void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid) +/* + * Bind processes do the device that have been temporarily unbound + * (PDD_BOUND_SUSPENDED) in kfd_unbind_processes_from_device. + */ +int kfd_bind_processes_to_device(struct kfd_dev *dev) +{ + struct kfd_process_device *pdd; + struct kfd_process *p; + unsigned int temp; + int err = 0; + + int idx = srcu_read_lock(&kfd_processes_srcu); + + hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { + mutex_lock(&p->mutex); + pdd = kfd_get_process_device_data(dev, p); + if (pdd->bound != PDD_BOUND_SUSPENDED) { + mutex_unlock(&p->mutex); + continue; + } + + err = amd_iommu_bind_pasid(dev->pdev, p->pasid, + p->lead_thread); + if (err < 0) { + pr_err("Unexpected pasid %d binding failure\n", + p->pasid); + mutex_unlock(&p->mutex); + break; + } + + pdd->bound = PDD_BOUND; + mutex_unlock(&p->mutex); + } + + srcu_read_unlock(&kfd_processes_srcu, idx); + + return err; +} + +/* + * Mark currently bound processes as PDD_BOUND_SUSPENDED. These + * processes will be restored to PDD_BOUND state in + * kfd_bind_processes_to_device. + */ +void kfd_unbind_processes_from_device(struct kfd_dev *dev) +{ + struct kfd_process_device *pdd; + struct kfd_process *p; + unsigned int temp; + + int idx = srcu_read_lock(&kfd_processes_srcu); + + hash_for_each_rcu(kfd_processes_table, temp, p, kfd_processes) { + mutex_lock(&p->mutex); + pdd = kfd_get_process_device_data(dev, p); + + if (pdd->bound == PDD_BOUND) + pdd->bound = PDD_BOUND_SUSPENDED; + mutex_unlock(&p->mutex); + } + + srcu_read_unlock(&kfd_processes_srcu, idx); +} + +void kfd_process_iommu_unbind_callback(struct kfd_dev *dev, unsigned int pasid) { struct kfd_process *p; struct kfd_process_device *pdd; @@ -421,31 +472,23 @@ void kfd_unbind_process_from_device(struct kfd_dev *dev, unsigned int pasid) pr_debug("Unbinding process %d from IOMMU\n", pasid); - if ((dev->dbgmgr) && (dev->dbgmgr->pasid == p->pasid)) - kfd_dbgmgr_destroy(dev->dbgmgr); - - pqm_uninit(&p->pqm); - - pdd = kfd_get_process_device_data(dev, p); + mutex_lock(kfd_get_dbgmgr_mutex()); - if (!pdd) { - mutex_unlock(&p->mutex); - return; + if (dev->dbgmgr && dev->dbgmgr->pasid == p->pasid) { + if (!kfd_dbgmgr_unregister(dev->dbgmgr, p)) { + kfd_dbgmgr_destroy(dev->dbgmgr); + dev->dbgmgr = NULL; + } } - if (pdd->reset_wavefronts) { - dbgdev_wave_reset_wavefronts(pdd->dev, p); - pdd->reset_wavefronts = false; - } + mutex_unlock(kfd_get_dbgmgr_mutex()); - /* - * Just mark pdd as unbound, because we still need it - * to call amd_iommu_unbind_pasid() in when the - * process exits. - * We don't call amd_iommu_unbind_pasid() here - * because the IOMMU called us. - */ - pdd->bound = false; + pdd = kfd_get_process_device_data(dev, p); + if (pdd) + /* For GPU relying on IOMMU, we need to dequeue here + * when PASID is still bound. + */ + kfd_process_dequeue_from_device(pdd); mutex_unlock(&p->mutex); } diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c index 03bec765b03d..2bec902fc939 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c @@ -63,6 +63,25 @@ static int find_available_queue_slot(struct process_queue_manager *pqm, return 0; } +void kfd_process_dequeue_from_device(struct kfd_process_device *pdd) +{ + struct kfd_dev *dev = pdd->dev; + + if (pdd->already_dequeued) + return; + + dev->dqm->ops.process_termination(dev->dqm, &pdd->qpd); + pdd->already_dequeued = true; +} + +void kfd_process_dequeue_from_all_devices(struct kfd_process *p) +{ + struct kfd_process_device *pdd; + + list_for_each_entry(pdd, &p->per_device_data, per_device_list) + kfd_process_dequeue_from_device(pdd); +} + int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p) { INIT_LIST_HEAD(&pqm->queues); @@ -78,21 +97,14 @@ int pqm_init(struct process_queue_manager *pqm, struct kfd_process *p) void pqm_uninit(struct process_queue_manager *pqm) { - int retval; struct process_queue_node *pqn, *next; list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) { - retval = pqm_destroy_queue( - pqm, - (pqn->q != NULL) ? - pqn->q->properties.queue_id : - pqn->kq->queue->properties.queue_id); - - if (retval != 0) { - pr_err("failed to destroy queue\n"); - return; - } + uninit_queue(pqn->q); + list_del(&pqn->process_queue_list); + kfree(pqn); } + kfree(pqm->queue_slot_bitmap); pqm->queue_slot_bitmap = NULL; } @@ -130,20 +142,16 @@ int pqm_create_queue(struct process_queue_manager *pqm, struct kfd_dev *dev, struct file *f, struct queue_properties *properties, - unsigned int flags, - enum kfd_queue_type type, unsigned int *qid) { int retval; struct kfd_process_device *pdd; - struct queue_properties q_properties; struct queue *q; struct process_queue_node *pqn; struct kernel_queue *kq; - int num_queues = 0; - struct queue *cur; + enum kfd_queue_type type = properties->type; + unsigned int max_queues = 127; /* HWS limit */ - memcpy(&q_properties, properties, sizeof(struct queue_properties)); q = NULL; kq = NULL; @@ -159,19 +167,18 @@ int pqm_create_queue(struct process_queue_manager *pqm, * If we are just about to create DIQ, the is_debug flag is not set yet * Hence we also check the type as well */ - if ((pdd->qpd.is_debug) || - (type == KFD_QUEUE_TYPE_DIQ)) { - list_for_each_entry(cur, &pdd->qpd.queues_list, list) - num_queues++; - if (num_queues >= dev->device_info->max_no_of_hqd/2) - return -ENOSPC; - } + if ((pdd->qpd.is_debug) || (type == KFD_QUEUE_TYPE_DIQ)) + max_queues = dev->device_info->max_no_of_hqd/2; + + if (pdd->qpd.queue_count >= max_queues) + return -ENOSPC; retval = find_available_queue_slot(pqm, qid); if (retval != 0) return retval; - if (list_empty(&pqm->queues)) { + if (list_empty(&pdd->qpd.queues_list) && + list_empty(&pdd->qpd.priv_queue_list)) { pdd->qpd.pqm = pqm; dev->dqm->ops.register_process(dev->dqm, &pdd->qpd); } @@ -187,14 +194,14 @@ int pqm_create_queue(struct process_queue_manager *pqm, case KFD_QUEUE_TYPE_COMPUTE: /* check if there is over subscription */ if ((sched_policy == KFD_SCHED_POLICY_HWS_NO_OVERSUBSCRIPTION) && - ((dev->dqm->processes_count >= VMID_PER_DEVICE) || + ((dev->dqm->processes_count >= dev->vm_info.vmid_num_kfd) || (dev->dqm->queue_count >= get_queues_num(dev->dqm)))) { pr_err("Over-subscription is not allowed in radeon_kfd.sched_policy == 1\n"); retval = -EPERM; goto err_create_queue; } - retval = create_cp_queue(pqm, dev, &q, &q_properties, f, *qid); + retval = create_cp_queue(pqm, dev, &q, properties, f, *qid); if (retval != 0) goto err_create_queue; pqn->q = q; @@ -231,9 +238,8 @@ int pqm_create_queue(struct process_queue_manager *pqm, list_add(&pqn->process_queue_list, &pqm->queues); if (q) { - *properties = q->properties; pr_debug("PQM done creating queue\n"); - print_queue_properties(properties); + print_queue_properties(&q->properties); } return retval; @@ -243,7 +249,8 @@ err_create_queue: err_allocate_pqn: /* check if queues list is empty unregister process from device */ clear_bit(*qid, pqm->queue_slot_bitmap); - if (list_empty(&pqm->queues)) + if (list_empty(&pdd->qpd.queues_list) && + list_empty(&pdd->qpd.priv_queue_list)) dev->dqm->ops.unregister_process(dev->dqm, &pdd->qpd); return retval; } @@ -290,9 +297,6 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) if (pqn->q) { dqm = pqn->q->device->dqm; retval = dqm->ops.destroy_queue(dqm, &pdd->qpd, pqn->q); - if (retval != 0) - return retval; - uninit_queue(pqn->q); } @@ -300,7 +304,8 @@ int pqm_destroy_queue(struct process_queue_manager *pqm, unsigned int qid) kfree(pqn); clear_bit(qid, pqm->queue_slot_bitmap); - if (list_empty(&pqm->queues)) + if (list_empty(&pdd->qpd.queues_list) && + list_empty(&pdd->qpd.priv_queue_list)) dqm->ops.unregister_process(dqm, &pdd->qpd); return retval; diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 20457bb5a906..b72f8a43d86b 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -23,36 +23,11 @@ #ifndef __AMD_SHARED_H__ #define __AMD_SHARED_H__ -#define AMD_MAX_USEC_TIMEOUT 200000 /* 200 ms */ +#include <drm/amd_asic_type.h> struct seq_file; -/* - * Supported ASIC types - */ -enum amd_asic_type { - CHIP_TAHITI = 0, - CHIP_PITCAIRN, - CHIP_VERDE, - CHIP_OLAND, - CHIP_HAINAN, - CHIP_BONAIRE, - CHIP_KAVERI, - CHIP_KABINI, - CHIP_HAWAII, - CHIP_MULLINS, - CHIP_TOPAZ, - CHIP_TONGA, - CHIP_FIJI, - CHIP_CARRIZO, - CHIP_STONEY, - CHIP_POLARIS10, - CHIP_POLARIS11, - CHIP_POLARIS12, - CHIP_VEGA10, - CHIP_RAVEN, - CHIP_LAST, -}; +#define AMD_MAX_USEC_TIMEOUT 200000 /* 200 ms */ /* * Chip flags @@ -257,43 +232,54 @@ struct amd_ip_funcs { void (*get_clockgating_state)(void *handle, u32 *flags); }; -enum amd_pp_task; +enum amd_pp_task; +enum amd_pp_clock_type; struct pp_states_info; +struct amd_pp_simple_clock_info; +struct amd_pp_display_configuration; +struct amd_pp_clock_info; +struct pp_display_clock_request; +struct pp_wm_sets_with_clock_ranges_soc15; +struct pp_clock_levels_with_voltage; +struct pp_clock_levels_with_latency; +struct amd_pp_clocks; struct amd_pm_funcs { - int (*get_temperature)(void *handle); +/* export for dpm on ci and si */ int (*pre_set_power_state)(void *handle); int (*set_power_state)(void *handle); void (*post_set_power_state)(void *handle); void (*display_configuration_changed)(void *handle); - u32 (*get_sclk)(void *handle, bool low); - u32 (*get_mclk)(void *handle, bool low); void (*print_power_state)(void *handle, void *ps); - void (*debugfs_print_current_performance_level)(void *handle, struct seq_file *m); - int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level); bool (*vblank_too_short)(void *handle); - void (*powergate_uvd)(void *handle, bool gate); - void (*powergate_vce)(void *handle, bool gate); void (*enable_bapm)(void *handle, bool enable); + int (*check_state_equal)(void *handle, + void *cps, + void *rps, + bool *equal); +/* export for sysfs */ + int (*get_temperature)(void *handle); void (*set_fan_control_mode)(void *handle, u32 mode); u32 (*get_fan_control_mode)(void *handle); int (*set_fan_speed_percent)(void *handle, u32 speed); int (*get_fan_speed_percent)(void *handle, u32 *speed); int (*force_clock_level)(void *handle, enum pp_clock_type type, uint32_t mask); int (*print_clock_levels)(void *handle, enum pp_clock_type type, char *buf); + int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level); int (*get_sclk_od)(void *handle); int (*set_sclk_od)(void *handle, uint32_t value); int (*get_mclk_od)(void *handle); int (*set_mclk_od)(void *handle, uint32_t value); - int (*check_state_equal)(void *handle, - void *cps, - void *rps, - bool *equal); - int (*read_sensor)(void *handle, int idx, void *value, - int *size); + int (*read_sensor)(void *handle, int idx, void *value, int *size); + enum amd_dpm_forced_level (*get_performance_level)(void *handle); + enum amd_pm_state_type (*get_current_power_state)(void *handle); + int (*get_fan_speed_rpm)(void *handle, uint32_t *rpm); + int (*get_pp_num_states)(void *handle, struct pp_states_info *data); + int (*get_pp_table)(void *handle, char **table); + int (*set_pp_table)(void *handle, const char *buf, size_t size); + void (*debugfs_print_current_performance_level)(void *handle, struct seq_file *m); - struct amd_vce_state* (*get_vce_clock_state)(void *handle, u32 idx); int (*reset_power_profile_state)(void *handle, struct amd_pp_profile *request); int (*get_power_profile_state)(void *handle, @@ -302,16 +288,39 @@ struct amd_pm_funcs { struct amd_pp_profile *request); int (*switch_power_profile)(void *handle, enum amd_pp_profile_type type); - int (*load_firmware)(void *handle); - int (*wait_for_fw_loading_complete)(void *handle); - enum amd_dpm_forced_level (*get_performance_level)(void *handle); - enum amd_pm_state_type (*get_current_power_state)(void *handle); +/* export to amdgpu */ + void (*powergate_uvd)(void *handle, bool gate); + void (*powergate_vce)(void *handle, bool gate); + struct amd_vce_state* (*get_vce_clock_state)(void *handle, u32 idx); int (*dispatch_tasks)(void *handle, enum amd_pp_task task_id, void *input, void *output); - int (*get_fan_speed_rpm)(void *handle, uint32_t *rpm); - int (*get_pp_num_states)(void *handle, struct pp_states_info *data); - int (*get_pp_table)(void *handle, char **table); - int (*set_pp_table)(void *handle, const char *buf, size_t size); + int (*load_firmware)(void *handle); + int (*wait_for_fw_loading_complete)(void *handle); + int (*set_clockgating_by_smu)(void *handle, uint32_t msg_id); +/* export to DC */ + u32 (*get_sclk)(void *handle, bool low); + u32 (*get_mclk)(void *handle, bool low); + int (*display_configuration_change)(void *handle, + const struct amd_pp_display_configuration *input); + int (*get_display_power_level)(void *handle, + struct amd_pp_simple_clock_info *output); + int (*get_current_clocks)(void *handle, + struct amd_pp_clock_info *clocks); + int (*get_clock_by_type)(void *handle, + enum amd_pp_clock_type type, + struct amd_pp_clocks *clocks); + int (*get_clock_by_type_with_latency)(void *handle, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_latency *clocks); + int (*get_clock_by_type_with_voltage)(void *handle, + enum amd_pp_clock_type type, + struct pp_clock_levels_with_voltage *clocks); + int (*set_watermarks_for_clocks_ranges)(void *handle, + struct pp_wm_sets_with_clock_ranges_soc15 *wm_with_clock_ranges); + int (*display_clock_voltage_request)(void *handle, + struct pp_display_clock_request *clock); + int (*get_display_mode_validation_clocks)(void *handle, + struct amd_pp_simple_clock_info *clocks); }; diff --git a/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_6_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_6_0_d.h index 378f4b6b43da..344237256d02 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_6_0_d.h +++ b/drivers/gpu/drm/amd/include/asic_reg/uvd/uvd_6_0_d.h @@ -36,6 +36,16 @@ #define mmUVD_UDEC_DBW_ADDR_CONFIG 0x3bd5 #define mmUVD_POWER_STATUS_U 0x3bfd #define mmUVD_NO_OP 0x3bff +#define mmUVD_RB_BASE_LO2 0x3c21 +#define mmUVD_RB_BASE_HI2 0x3c22 +#define mmUVD_RB_SIZE2 0x3c23 +#define mmUVD_RB_RPTR2 0x3c24 +#define mmUVD_RB_WPTR2 0x3c25 +#define mmUVD_RB_BASE_LO 0x3c26 +#define mmUVD_RB_BASE_HI 0x3c27 +#define mmUVD_RB_SIZE 0x3c28 +#define mmUVD_RB_RPTR 0x3c29 +#define mmUVD_RB_WPTR 0x3c2a #define mmUVD_LMI_RBC_RB_64BIT_BAR_LOW 0x3c69 #define mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH 0x3c68 #define mmUVD_LMI_RBC_IB_64BIT_BAR_LOW 0x3c67 @@ -43,6 +53,11 @@ #define mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW 0x3c5f #define mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH 0x3c5e #define mmUVD_SEMA_CNTL 0x3d00 +#define mmUVD_RB_WPTR3 0x3d1c +#define mmUVD_RB_RPTR3 0x3d1b +#define mmUVD_RB_BASE_LO3 0x3d1d +#define mmUVD_RB_BASE_HI3 0x3d1e +#define mmUVD_RB_SIZE3 0x3d1f #define mmUVD_LMI_EXT40_ADDR 0x3d26 #define mmUVD_CTX_INDEX 0x3d28 #define mmUVD_CTX_DATA 0x3d29 diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index 181a2c3c6362..f696bbb643ef 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -4292,6 +4292,7 @@ typedef struct _ATOM_DPCD_INFO #define ATOM_VRAM_OPERATION_FLAGS_SHIFT 30 #define ATOM_VRAM_BLOCK_NEEDS_NO_RESERVATION 0x1 #define ATOM_VRAM_BLOCK_NEEDS_RESERVATION 0x0 +#define ATOM_VRAM_BLOCK_SRIOV_MSG_SHARE_RESERVATION 0x2 /***********************************************************************************/ // Structure used in VRAM_UsageByFirmwareTable diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index 030b14649c4e..675988d56392 100644 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -423,6 +423,10 @@ typedef int (*cgs_enter_safe_mode)(struct cgs_device *cgs_device, bool en); typedef void (*cgs_lock_grbm_idx)(struct cgs_device *cgs_device, bool lock); +struct amd_pp_init; +typedef void* (*cgs_register_pp_handle)(struct cgs_device *cgs_device, + int (*call_back_func)(struct amd_pp_init *, void **)); + struct cgs_ops { /* memory management calls (similar to KFD interface) */ cgs_alloc_gpu_mem_t alloc_gpu_mem; @@ -459,6 +463,7 @@ struct cgs_ops { cgs_is_virtualization_enabled_t is_virtualization_enabled; cgs_enter_safe_mode enter_safe_mode; cgs_lock_grbm_idx lock_grbm_idx; + cgs_register_pp_handle register_pp_handle; }; struct cgs_os_ops; /* To be define in OS-specific CGS header */ @@ -537,4 +542,7 @@ struct cgs_device #define cgs_lock_grbm_idx(cgs_device, lock) \ CGS_CALL(lock_grbm_idx, cgs_device, lock) +#define cgs_register_pp_handle(cgs_device, call_back_func) \ + CGS_CALL(register_pp_handle, cgs_device, call_back_func) + #endif /* _CGS_COMMON_H */ diff --git a/drivers/gpu/drm/amd/lib/Kconfig b/drivers/gpu/drm/amd/lib/Kconfig index 03ee7ad21ac3..776ef3434c10 100644 --- a/drivers/gpu/drm/amd/lib/Kconfig +++ b/drivers/gpu/drm/amd/lib/Kconfig @@ -4,7 +4,8 @@ menu "AMD Library routines" # Closed hash table # config CHASH - tristate "Closed hash table" + tristate + default DRM_AMDGPU help Statically sized closed hash table implementation with low memory and CPU overhead. diff --git a/drivers/gpu/drm/amd/lib/chash.c b/drivers/gpu/drm/amd/lib/chash.c index e07e6f3030d6..b8e45f356a1c 100644 --- a/drivers/gpu/drm/amd/lib/chash.c +++ b/drivers/gpu/drm/amd/lib/chash.c @@ -223,8 +223,8 @@ static int chash_table_check(struct __chash_table *table) static void chash_iter_relocate(struct chash_iter dst, struct chash_iter src) { BUG_ON(src.table == dst.table && src.slot == dst.slot); - BUG_ON(src.table->key_size != src.table->key_size); - BUG_ON(src.table->value_size != src.table->value_size); + BUG_ON(src.table->key_size != dst.table->key_size); + BUG_ON(src.table->value_size != dst.table->value_size); if (dst.table->key_size == 4) dst.table->keys32[dst.slot] = src.table->keys32[src.slot]; diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c index 9f3f3b8cf64f..c7e34128cbde 100644 --- a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -30,9 +30,14 @@ #include "pp_instance.h" #include "power_state.h" +#define PP_DPM_DISABLED 0xCCCC + +static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id, + void *input, void *output); + static inline int pp_check(struct pp_instance *handle) { - if (handle == NULL || handle->pp_valid != PP_VALID) + if (handle == NULL) return -EINVAL; if (handle->hwmgr == NULL || handle->hwmgr->smumgr_funcs == NULL) @@ -47,19 +52,57 @@ static inline int pp_check(struct pp_instance *handle) return 0; } +static int amd_powerplay_create(struct amd_pp_init *pp_init, + void **handle) +{ + struct pp_instance *instance; + + if (pp_init == NULL || handle == NULL) + return -EINVAL; + + instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL); + if (instance == NULL) + return -ENOMEM; + + instance->chip_family = pp_init->chip_family; + instance->chip_id = pp_init->chip_id; + instance->pm_en = pp_init->pm_en; + instance->feature_mask = pp_init->feature_mask; + instance->device = pp_init->device; + mutex_init(&instance->pp_lock); + *handle = instance; + return 0; +} + +static int amd_powerplay_destroy(void *handle) +{ + struct pp_instance *instance = (struct pp_instance *)handle; + + kfree(instance->hwmgr->hardcode_pp_table); + instance->hwmgr->hardcode_pp_table = NULL; + + kfree(instance->hwmgr); + instance->hwmgr = NULL; + + kfree(instance); + instance = NULL; + return 0; +} + static int pp_early_init(void *handle) { int ret; - struct pp_instance *pp_handle = (struct pp_instance *)handle; + struct pp_instance *pp_handle = NULL; + + pp_handle = cgs_register_pp_handle(handle, amd_powerplay_create); + + if (!pp_handle) + return -EINVAL; ret = hwmgr_early_init(pp_handle); if (ret) return -EINVAL; - if ((pp_handle->pm_en == 0) - || cgs_is_virtualization_enabled(pp_handle->device)) - return PP_DPM_DISABLED; - return 0; } @@ -71,7 +114,7 @@ static int pp_sw_init(void *handle) ret = pp_check(pp_handle); - if (ret == 0 || ret == PP_DPM_DISABLED) { + if (ret >= 0) { hwmgr = pp_handle->hwmgr; if (hwmgr->smumgr_funcs->smu_init == NULL) @@ -91,7 +134,7 @@ static int pp_sw_fini(void *handle) struct pp_instance *pp_handle = (struct pp_instance *)handle; ret = pp_check(pp_handle); - if (ret == 0 || ret == PP_DPM_DISABLED) { + if (ret >= 0) { hwmgr = pp_handle->hwmgr; if (hwmgr->smumgr_funcs->smu_fini == NULL) @@ -110,7 +153,7 @@ static int pp_hw_init(void *handle) ret = pp_check(pp_handle); - if (ret == 0 || ret == PP_DPM_DISABLED) { + if (ret >= 0) { hwmgr = pp_handle->hwmgr; if (hwmgr->smumgr_funcs->start_smu == NULL) @@ -122,16 +165,17 @@ static int pp_hw_init(void *handle) return -EINVAL;; } if (ret == PP_DPM_DISABLED) - return PP_DPM_DISABLED; + goto exit; + ret = hwmgr_hw_init(pp_handle); + if (ret) + goto exit; } - - ret = hwmgr_hw_init(pp_handle); - if (ret) - goto err; - return 0; -err: + return ret; +exit: pp_handle->pm_en = 0; - return PP_DPM_DISABLED; + cgs_notify_dpm_enabled(hwmgr->device, false); + return 0; + } static int pp_hw_fini(void *handle) @@ -146,6 +190,25 @@ static int pp_hw_fini(void *handle) return 0; } +static int pp_late_init(void *handle) +{ + struct pp_instance *pp_handle = (struct pp_instance *)handle; + int ret = 0; + + ret = pp_check(pp_handle); + if (ret == 0) + pp_dpm_dispatch_tasks(pp_handle, + AMD_PP_TASK_COMPLETE_INIT, NULL, NULL); + + return 0; +} + +static void pp_late_fini(void *handle) +{ + amd_powerplay_destroy(handle); +} + + static bool pp_is_idle(void *handle) { return false; @@ -161,28 +224,6 @@ static int pp_sw_reset(void *handle) return 0; } - -int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id) -{ - struct pp_hwmgr *hwmgr; - struct pp_instance *pp_handle = (struct pp_instance *)handle; - int ret = 0; - - ret = pp_check(pp_handle); - - if (ret != 0) - return ret; - - hwmgr = pp_handle->hwmgr; - - if (hwmgr->hwmgr_func->update_clock_gatings == NULL) { - pr_info("%s was not implemented.\n", __func__); - return 0; - } - - return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id); -} - static int pp_set_powergating_state(void *handle, enum amd_powergating_state state) { @@ -192,7 +233,7 @@ static int pp_set_powergating_state(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -213,39 +254,34 @@ static int pp_suspend(void *handle) int ret = 0; ret = pp_check(pp_handle); - - if (ret == PP_DPM_DISABLED) - return 0; - else if (ret != 0) - return ret; - - return hwmgr_hw_suspend(pp_handle); + if (ret == 0) + hwmgr_hw_suspend(pp_handle); + return 0; } static int pp_resume(void *handle) { struct pp_hwmgr *hwmgr; - int ret, ret1; + int ret; struct pp_instance *pp_handle = (struct pp_instance *)handle; - ret1 = pp_check(pp_handle); + ret = pp_check(pp_handle); - if (ret1 != 0 && ret1 != PP_DPM_DISABLED) - return ret1; + if (ret < 0) + return ret; hwmgr = pp_handle->hwmgr; if (hwmgr->smumgr_funcs->start_smu == NULL) return -EINVAL; - ret = hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr); - if (ret) { + if (hwmgr->smumgr_funcs->start_smu(pp_handle->hwmgr)) { pr_err("smc start failed\n"); hwmgr->smumgr_funcs->smu_fini(pp_handle->hwmgr); - return ret; + return -EINVAL; } - if (ret1 == PP_DPM_DISABLED) + if (ret == PP_DPM_DISABLED) return 0; return hwmgr_hw_resume(pp_handle); @@ -254,11 +290,12 @@ static int pp_resume(void *handle) const struct amd_ip_funcs pp_ip_funcs = { .name = "powerplay", .early_init = pp_early_init, - .late_init = NULL, + .late_init = pp_late_init, .sw_init = pp_sw_init, .sw_fini = pp_sw_fini, .hw_init = pp_hw_init, .hw_fini = pp_hw_fini, + .late_fini = pp_late_fini, .suspend = pp_suspend, .resume = pp_resume, .is_idle = pp_is_idle, @@ -278,6 +315,27 @@ static int pp_dpm_fw_loading_complete(void *handle) return 0; } +static int pp_set_clockgating_by_smu(void *handle, uint32_t msg_id) +{ + struct pp_hwmgr *hwmgr; + struct pp_instance *pp_handle = (struct pp_instance *)handle; + int ret = 0; + + ret = pp_check(pp_handle); + + if (ret) + return ret; + + hwmgr = pp_handle->hwmgr; + + if (hwmgr->hwmgr_func->update_clock_gatings == NULL) { + pr_info("%s was not implemented.\n", __func__); + return 0; + } + + return hwmgr->hwmgr_func->update_clock_gatings(hwmgr, &msg_id); +} + static void pp_dpm_en_umd_pstate(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level *level) { @@ -323,7 +381,7 @@ static int pp_dpm_force_performance_level(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -358,7 +416,7 @@ static enum amd_dpm_forced_level pp_dpm_get_performance_level( ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -377,7 +435,7 @@ static uint32_t pp_dpm_get_sclk(void *handle, bool low) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -401,7 +459,7 @@ static uint32_t pp_dpm_get_mclk(void *handle, bool low) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -424,7 +482,7 @@ static void pp_dpm_powergate_vce(void *handle, bool gate) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return; hwmgr = pp_handle->hwmgr; @@ -446,7 +504,7 @@ static void pp_dpm_powergate_uvd(void *handle, bool gate) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return; hwmgr = pp_handle->hwmgr; @@ -468,7 +526,7 @@ static int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_task task_id, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; mutex_lock(&pp_handle->pp_lock); @@ -488,7 +546,7 @@ static enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -530,7 +588,7 @@ static void pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return; hwmgr = pp_handle->hwmgr; @@ -553,7 +611,7 @@ static uint32_t pp_dpm_get_fan_control_mode(void *handle) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -576,7 +634,7 @@ static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -599,7 +657,7 @@ static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -623,7 +681,7 @@ static int pp_dpm_get_fan_speed_rpm(void *handle, uint32_t *rpm) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -645,7 +703,7 @@ static int pp_dpm_get_temperature(void *handle) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -670,7 +728,7 @@ static int pp_dpm_get_pp_num_states(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -715,7 +773,7 @@ static int pp_dpm_get_pp_table(void *handle, char **table) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -738,7 +796,7 @@ static int pp_dpm_set_pp_table(void *handle, const char *buf, size_t size) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -780,7 +838,7 @@ static int pp_dpm_force_clock_level(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -804,7 +862,7 @@ static int pp_dpm_print_clock_levels(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -827,7 +885,7 @@ static int pp_dpm_get_sclk_od(void *handle) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -850,7 +908,7 @@ static int pp_dpm_set_sclk_od(void *handle, uint32_t value) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -874,7 +932,7 @@ static int pp_dpm_get_mclk_od(void *handle) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -897,7 +955,7 @@ static int pp_dpm_set_mclk_od(void *handle, uint32_t value) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -921,7 +979,7 @@ static int pp_dpm_read_sensor(void *handle, int idx, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -947,7 +1005,7 @@ pp_dpm_get_vce_clock_state(void *handle, unsigned idx) ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return NULL; hwmgr = pp_handle->hwmgr; @@ -1120,53 +1178,16 @@ const struct amd_pm_funcs pp_dpm_funcs = { .get_power_profile_state = pp_dpm_get_power_profile_state, .set_power_profile_state = pp_dpm_set_power_profile_state, .switch_power_profile = pp_dpm_switch_power_profile, + .set_clockgating_by_smu = pp_set_clockgating_by_smu, }; -int amd_powerplay_create(struct amd_pp_init *pp_init, - void **handle) -{ - struct pp_instance *instance; - - if (pp_init == NULL || handle == NULL) - return -EINVAL; - - instance = kzalloc(sizeof(struct pp_instance), GFP_KERNEL); - if (instance == NULL) - return -ENOMEM; - - instance->pp_valid = PP_VALID; - instance->chip_family = pp_init->chip_family; - instance->chip_id = pp_init->chip_id; - instance->pm_en = pp_init->pm_en; - instance->feature_mask = pp_init->feature_mask; - instance->device = pp_init->device; - mutex_init(&instance->pp_lock); - *handle = instance; - return 0; -} - -int amd_powerplay_destroy(void *handle) -{ - struct pp_instance *instance = (struct pp_instance *)handle; - - kfree(instance->hwmgr); - instance->hwmgr = NULL; - - kfree(instance); - instance = NULL; - return 0; -} - int amd_powerplay_reset(void *handle) { struct pp_instance *instance = (struct pp_instance *)handle; int ret; - if (cgs_is_virtualization_enabled(instance->hwmgr->device)) - return PP_DPM_DISABLED; - ret = pp_check(instance); - if (ret != 0) + if (ret) return ret; ret = pp_hw_fini(instance); @@ -1175,7 +1196,7 @@ int amd_powerplay_reset(void *handle) ret = hwmgr_hw_init(instance); if (ret) - return PP_DPM_DISABLED; + return ret; return hwmgr_handle_task(instance, AMD_PP_TASK_COMPLETE_INIT, NULL, NULL); } @@ -1191,7 +1212,7 @@ int amd_powerplay_display_configuration_change(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -1210,7 +1231,7 @@ int amd_powerplay_get_display_power_level(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -1235,7 +1256,7 @@ int amd_powerplay_get_current_clocks(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -1252,7 +1273,7 @@ int amd_powerplay_get_current_clocks(void *handle, ret = phm_get_clock_info(hwmgr, &hwmgr->current_ps->hardware, &hw_clocks, PHM_PerformanceLevelDesignation_Activity); - if (ret != 0) { + if (ret) { pr_info("Error in phm_get_clock_info \n"); mutex_unlock(&pp_handle->pp_lock); return -EINVAL; @@ -1286,7 +1307,7 @@ int amd_powerplay_get_clock_by_type(void *handle, enum amd_pp_clock_type type, s ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; @@ -1309,7 +1330,7 @@ int amd_powerplay_get_clock_by_type_with_latency(void *handle, int ret = 0; ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; if (!clocks) @@ -1331,7 +1352,7 @@ int amd_powerplay_get_clock_by_type_with_voltage(void *handle, int ret = 0; ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; if (!clocks) @@ -1355,7 +1376,7 @@ int amd_powerplay_set_watermarks_for_clocks_ranges(void *handle, int ret = 0; ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; if (!wm_with_clock_ranges) @@ -1379,7 +1400,7 @@ int amd_powerplay_display_clock_voltage_request(void *handle, int ret = 0; ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; if (!clock) @@ -1403,7 +1424,7 @@ int amd_powerplay_get_display_mode_validation_clocks(void *handle, ret = pp_check(pp_handle); - if (ret != 0) + if (ret) return ret; hwmgr = pp_handle->hwmgr; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c index 73bb99d62a44..ad1f6b57884b 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -704,7 +704,7 @@ static int cz_update_sclk_limit(struct pp_hwmgr *hwmgr) clock = hwmgr->display_config.min_core_set_clock; if (clock == 0) - pr_info("min_core_set_clock not set\n"); + pr_debug("min_core_set_clock not set\n"); if (cz_hwmgr->sclk_dpm.hard_min_clk != clock) { cz_hwmgr->sclk_dpm.hard_min_clk = clock; @@ -961,18 +961,13 @@ static void cz_clear_voting_clients(struct pp_hwmgr *hwmgr) static int cz_start_dpm(struct pp_hwmgr *hwmgr) { - int ret = 0; struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); - unsigned long dpm_features = 0; cz_hwmgr->dpm_flags |= DPMFlags_SCLK_Enabled; - dpm_features |= SCLK_DPM_MASK; - ret = smum_send_msg_to_smc_with_parameter(hwmgr, + return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_EnableAllSmuFeatures, - dpm_features); - - return ret; + SCLK_DPM_MASK); } static int cz_stop_dpm(struct pp_hwmgr *hwmgr) @@ -1279,27 +1274,18 @@ static int cz_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating)) - return smum_send_msg_to_smc(hwmgr, - PPSMC_MSG_UVDPowerOFF); + if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) + return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_UVDPowerOFF); return 0; } int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDPowerGating)) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDynamicPowerGating)) { - return smum_send_msg_to_smc_with_parameter( - hwmgr, - PPSMC_MSG_UVDPowerON, 1); - } else { - return smum_send_msg_to_smc_with_parameter( - hwmgr, - PPSMC_MSG_UVDPowerON, 0); - } + if (PP_CAP(PHM_PlatformCaps_UVDPowerGating)) { + return smum_send_msg_to_smc_with_parameter( + hwmgr, + PPSMC_MSG_UVDPowerON, + PP_CAP(PHM_PlatformCaps_UVDDynamicPowerGating) ? 1 : 0); } return 0; @@ -1313,17 +1299,16 @@ int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) if (!bgate) { /* Stable Pstate is enabled and we need to set the UVD DPM to highest level */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState) - || hwmgr->en_umd_pstate) { + if (PP_CAP(PHM_PlatformCaps_StablePState) || + hwmgr->en_umd_pstate) { cz_hwmgr->uvd_dpm.hard_min_clk = ptable->entries[ptable->count - 1].vclk; smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetUvdHardMin, - cz_get_uvd_level(hwmgr, - cz_hwmgr->uvd_dpm.hard_min_clk, - PPSMC_MSG_SetUvdHardMin)); + PPSMC_MSG_SetUvdHardMin, + cz_get_uvd_level(hwmgr, + cz_hwmgr->uvd_dpm.hard_min_clk, + PPSMC_MSG_SetUvdHardMin)); cz_enable_disable_uvd_dpm(hwmgr, true); } else { @@ -1343,17 +1328,16 @@ int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) hwmgr->dyn_state.vce_clock_voltage_dependency_table; /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState) - || hwmgr->en_umd_pstate) { + if (PP_CAP(PHM_PlatformCaps_StablePState) || + hwmgr->en_umd_pstate) { cz_hwmgr->vce_dpm.hard_min_clk = ptable->entries[ptable->count - 1].ecclk; smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetEclkHardMin, - cz_get_eclk_level(hwmgr, - cz_hwmgr->vce_dpm.hard_min_clk, - PPSMC_MSG_SetEclkHardMin)); + PPSMC_MSG_SetEclkHardMin, + cz_get_eclk_level(hwmgr, + cz_hwmgr->vce_dpm.hard_min_clk, + PPSMC_MSG_SetEclkHardMin)); } else { /*Program HardMin based on the vce_arbiter.ecclk */ if (hwmgr->vce_arbiter.ecclk == 0) { @@ -1366,10 +1350,10 @@ int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) } else { cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk; smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetEclkHardMin, - cz_get_eclk_level(hwmgr, - cz_hwmgr->vce_dpm.hard_min_clk, - PPSMC_MSG_SetEclkHardMin)); + PPSMC_MSG_SetEclkHardMin, + cz_get_eclk_level(hwmgr, + cz_hwmgr->vce_dpm.hard_min_clk, + PPSMC_MSG_SetEclkHardMin)); } } return 0; @@ -1377,8 +1361,7 @@ int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating)) + if (PP_CAP(PHM_PlatformCaps_VCEPowerGating)) return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_VCEPowerOFF); return 0; @@ -1386,8 +1369,7 @@ int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr) int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_VCEPowerGating)) + if (PP_CAP(PHM_PlatformCaps_VCEPowerGating)) return smum_send_msg_to_smc(hwmgr, PPSMC_MSG_VCEPowerON); return 0; @@ -1871,6 +1853,33 @@ static int cz_read_sensor(struct pp_hwmgr *hwmgr, int idx, } } +static int cz_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramAddrHiVirtual, + mc_addr_hi); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramAddrLoVirtual, + mc_addr_low); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramAddrHiPhysical, + virtual_addr_hi); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramAddrLoPhysical, + virtual_addr_low); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramBufferSize, + size); + return 0; +} + + static const struct pp_hwmgr_func cz_hwmgr_funcs = { .backend_init = cz_hwmgr_backend_init, .backend_fini = cz_hwmgr_backend_fini, @@ -1894,12 +1903,14 @@ static const struct pp_hwmgr_func cz_hwmgr_funcs = { .get_current_shallow_sleep_clocks = cz_get_current_shallow_sleep_clocks, .get_clock_by_type = cz_get_clock_by_type, .get_max_high_clocks = cz_get_max_high_clocks, + .get_temperature = cz_thermal_get_temperature, .read_sensor = cz_read_sensor, .power_off_asic = cz_power_off_asic, .asic_setup = cz_setup_asic_task, .dynamic_state_management_enable = cz_enable_dpm_tasks, .power_state_set = cz_set_power_state_tasks, .dynamic_state_management_disable = cz_disable_dpm_tasks, + .notify_cac_buffer_info = cz_notify_cac_buffer_info, }; int cz_init_function_pointers(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c index 35e80c969737..ce59e0e67cb2 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -292,7 +292,6 @@ int hwmgr_hw_fini(struct pp_instance *handle) phm_stop_thermal_controller(hwmgr); psm_set_boot_states(hwmgr); - phm_display_configuration_changed(hwmgr); psm_adjust_power_state_dynamic(hwmgr, false, NULL); phm_disable_dynamic_state_management(hwmgr); phm_disable_clock_power_gatings(hwmgr); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c index d09f25485844..8ba75d43fba6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.c @@ -1,1263 +1,1252 @@ #include "pp_overdriver.h" #include <linux/errno.h> -struct phm_fuses_default vega10_fuses_default[] = { - {"0000001000010011111010101001010011011110000011100100100101100100",0x00003C96,0xFFFFE226,0x00000656,0x00002203,0xFFFFF201,0x000003FF,0x00002203,0xFFFFF201,0x000003FF}, - {"0000001000010011111010101001010011011110000010100001100010000100",0x00003CC5,0xFFFFE23A,0x0000064E,0x00002258,0xFFFFF1F7,0x000003FC,0x00002258,0xFFFFF1F7,0x000003FC}, - {"0000001000010011111010101001010011011110000011100011000110100100",0x00003CAF,0xFFFFE36E,0x00000602,0x00001E98,0xFFFFF569,0x00000357,0x00001E98,0xFFFFF569,0x00000357}, - {"0000001000010011111010101001010011011110001011000001000101000100",0x0000391A,0xFFFFE548,0x000005C9,0x00001B98,0xFFFFF707,0x00000324,0x00001B98,0xFFFFF707,0x00000324}, - {"0000001000010011111010101001010011011110001011000001100011000100",0x00003821,0xFFFFE674,0x00000597,0x00002196,0xFFFFF361,0x000003C0,0x00002196,0xFFFFF361,0x000003C0}, - {"0000001000010011111010101001010011011110001001100011100010000100",0x000044A2,0xFFFFDCB7,0x00000738,0x0000325C,0xFFFFE6A7,0x000005E6,0x0000325C,0xFFFFE6A7,0x000005E6}, - {"0000001000010011111010101001010011011110000010000010100100100100",0x00004057,0xFFFFE1CF,0x0000063C,0x00002E2E,0xFFFFEB62,0x000004FD,0x00002E2E,0xFFFFEB62,0x000004FD}, - {"0000001000010011111010101001010011011110001010000100100100100100",0x00003FD0,0xFFFFDF0F,0x000006E5,0x0000267C,0xFFFFEE2D,0x000004AB,0x0000267C,0xFFFFEE2D,0x000004AB}, - {"0000001000010011111010101001010011011110001010000000100100000100",0x00003F13,0xFFFFE010,0x000006AD,0x000020E7,0xFFFFF266,0x000003EC,0x000020E7,0xFFFFF266,0x000003EC}, - {"0000001000010011111010101001010011011110000010000010000001000100",0x00004088,0xFFFFDFAB,0x000006B6,0x0000252B,0xFFFFEFDB,0x00000458,0x0000252B,0xFFFFEFDB,0x00000458}, - {"0000001000010011111010101001010011011110001010000011100010000100",0x00003EF6,0xFFFFE017,0x000006AA,0x00001F67,0xFFFFF369,0x000003BE,0x00001F67,0xFFFFF369,0x000003BE}, - {"0000001000010011111010101001010011011110001011000010000110000100",0x00003CDD,0xFFFFE2A7,0x0000063C,0x000026C6,0xFFFFEF38,0x00000478,0x000026C6,0xFFFFEF38,0x00000478}, - {"0000001000010011111010101001010011011110000100000101000100100100",0x00003FA8,0xFFFFDF02,0x000006F0,0x000027FE,0xFFFFECF6,0x000004EA,0x000027FE,0xFFFFECF6,0x000004EA}, - {"0000001000010011111010101001010011011110001001100011100011000100",0x00004670,0xFFFFDC40,0x00000742,0x00003A7A,0xFFFFE1A7,0x000006B6,0x00003A7A,0xFFFFE1A7,0x000006B6}, - {"0000001000010011111010101001010011011110001011000011000000100100",0x00003CDC,0xFFFFE18C,0x00000683,0x00002A69,0xFFFFEBE7,0x00000515,0x00002A69,0xFFFFEBE7,0x00000515}, - {"0000001000010011111010101001010011011110000011100011100011000100",0x00003CEC,0xFFFFE38E,0x00000601,0x00002752,0xFFFFEFA7,0x00000453,0x00002752,0xFFFFEFA7,0x00000453}, - {"0000001000010011111010101001010011011110001011000001000100100100",0x000037D0,0xFFFFE634,0x000005A7,0x00001CD2,0xFFFFF644,0x00000348,0x00001CD2,0xFFFFF644,0x00000348}, - {"0000001000010011111010101001010011011110001010000011100101100100",0x00003DF5,0xFFFFE0A5,0x00000698,0x00001FD5,0xFFFFF30E,0x000003D1,0x00001FD5,0xFFFFF30E,0x000003D1}, - {"0000001000010011111010101001010011011110000010000010100011000100",0x00004201,0xFFFFE03E,0x00000688,0x00003206,0xFFFFE852,0x0000058A,0x00003206,0xFFFFE852,0x0000058A}, - {"0000001000010011111010101001010011011110001011000001100001100100",0x00003BED,0xFFFFE2F5,0x00000638,0x0000270D,0xFFFFEED0,0x0000048E,0x0000270D,0xFFFFEED0,0x0000048E}, - {"0000001000010011111010101001010011011110000010100001100100000100",0x00003E82,0xFFFFE1BE,0x00000654,0x000025FB,0xFFFFEFFA,0x00000448,0x000025FB,0xFFFFEFFA,0x00000448}, - {"0000001000010011111010101001010011011110001011000100000011000100",0x00003962,0xFFFFE4B9,0x000005EF,0x00002385,0xFFFFF156,0x00000423,0x00002385,0xFFFFF156,0x00000423}, - {"0000001000010011111010101001010011011110001011000000100101000100",0x00003D88,0xFFFFE21A,0x00000655,0x0000295A,0xFFFFED68,0x000004C4,0x0000295A,0xFFFFED68,0x000004C4}, - {"0000001000010011111010101001010011011110001011000001000100000100",0x00003AA4,0xFFFFE4A3,0x000005E0,0x000022EF,0xFFFFF250,0x000003EB,0x000022EF,0xFFFFF250,0x000003EB}, - {"0000001000010011111010101001010011011110000011100010100110100100",0x00003D97,0xFFFFE30D,0x0000060D,0x0000205D,0xFFFFF45D,0x00000380,0x0000205D,0xFFFFF45D,0x00000380}, - {"0000001000010011111010101001010011011110001011000100000010100100",0x000039B6,0xFFFFE446,0x00000605,0x00002325,0xFFFFF16C,0x0000041F,0x00002325,0xFFFFF16C,0x0000041F}, - {"0000001000010011111010101001010011011110001001100011100100000100",0x0000457E,0xFFFFDCF6,0x00000722,0x00003972,0xFFFFE27B,0x0000068E,0x00003972,0xFFFFE27B,0x0000068E}, - {"0000001000010011111010101001010011011110000010100001100100100100",0x00003FB8,0xFFFFE101,0x00000670,0x00002787,0xFFFFEEF5,0x00000471,0x00002787,0xFFFFEEF5,0x00000471}, - {"0000001000010011111010101001010011011110000011100011100010100100",0x00003BB2,0xFFFFE430,0x000005EA,0x000024A5,0xFFFFF162,0x00000409,0x000024A5,0xFFFFF162,0x00000409}, - {"0000001000010011111010101001010011011110000010000010000101000100",0x00003EC5,0xFFFFE1BD,0x0000064F,0x000022F0,0xFFFFF227,0x000003E8,0x000022F0,0xFFFFF227,0x000003E8}, - {"0000001000010011111010101001010011011110001011000011000101100100",0x000038A7,0xFFFFE59F,0x000005C1,0x000021CC,0xFFFFF2DF,0x000003D9,0x000021CC,0xFFFFF2DF,0x000003D9}, - {"0000001000010011111010101001010011011110001100100100000110000100",0x00002995,0xFFFFEF7A,0x0000044C,0x00001552,0xFFFFFB5D,0x00000292,0x00001552,0xFFFFFB5D,0x00000292}, - {"0000001000010011111010101001010011011110001011000100000001100100",0x00003B26,0xFFFFE2D3,0x00000649,0x000023B4,0xFFFFF09B,0x00000449,0x000023B4,0xFFFFF09B,0x00000449}, - {"0000001000010011111010101001010011011110000010000001000100100100",0x000040D2,0xFFFFE00A,0x00000696,0x000022DA,0xFFFFF1E9,0x000003F2,0x000022DA,0xFFFFF1E9,0x000003F2}, - {"0000001000010011111010101001010011011110001011000011100100100100",0x00003C98,0xFFFFE365,0x00000618,0x00002D5D,0xFFFFEB3A,0x0000051D,0x00002D5D,0xFFFFEB3A,0x0000051D}, - {"0000001000010011111010101001010011011110001011000001000010100100",0x00003BBD,0xFFFFE37E,0x00000617,0x0000252E,0xFFFFF06E,0x00000441,0x0000252E,0xFFFFF06E,0x00000441}, - {"0000001000010011111010101001010011011110001001100010100100100100",0x00004363,0xFFFFDF7A,0x000006A0,0x000031F5,0xFFFFE880,0x0000057B,0x000031F5,0xFFFFE880,0x0000057B}, - {"0000001000010011111010101001010011011110000011100011100001000100",0x00003CFC,0xFFFFE2AF,0x0000062E,0x0000212A,0xFFFFF335,0x000003BF,0x0000212A,0xFFFFF335,0x000003BF}, - {"0000001000010011111010101001010011011110000111000100100100100100",0x0000252D,0xFFFFF31B,0x000003C3,0x00001A1A,0xFFFFF882,0x00000325,0x00001A1A,0xFFFFF882,0x00000325}, - {"0000001000010011111010101001010011011110000010100010100110100100",0x00003FE2,0xFFFFDFEF,0x000006AC,0x000025A2,0xFFFFEF84,0x00000462,0x000025A2,0xFFFFEF84,0x00000462}, - {"0000001000010011111010101001010011011110000010000010000011100100",0x000040A5,0xFFFFE13B,0x0000065B,0x00002C13,0xFFFFEC75,0x000004D7,0x00002C13,0xFFFFEC75,0x000004D7}, - {"0000001000010011111010101001010011011110000011100100100010100100",0x00003E42,0xFFFFE1B3,0x00000657,0x0000221D,0xFFFFF273,0x000003DE,0x0000221D,0xFFFFF273,0x000003DE}, - {"0000001000010011111010101001010011011110000010100010000011100100",0x00003E7F,0xFFFFE255,0x00000638,0x00002D30,0xFFFFEB8A,0x00000503,0x00002D30,0xFFFFEB8A,0x00000503}, - {"0000001000010011111010101001010011011110001011000010100111000100",0x00003E56,0xFFFFE16D,0x00000670,0x000028DC,0xFFFFEDA0,0x000004BA,0x000028DC,0xFFFFEDA0,0x000004BA}, - {"0000001000010011111010101001010011011110001001100011000010100100",0x000044AD,0xFFFFDE24,0x000006DD,0x000031AD,0xFFFFE850,0x00000585,0x000031AD,0xFFFFE850,0x00000585}, - {"0000001000010011111010101001010011011110001011000010000011100100",0x00003AF3,0xFFFFE5B0,0x000005A6,0x00002CF6,0xFFFFEC75,0x000004DD,0x00002CF6,0xFFFFEC75,0x000004DD}, - {"0000001000010011111010101001010011011110000010100010000010000100",0x00003E66,0xFFFFE19E,0x0000065B,0x00002332,0xFFFFF1B9,0x000003FD,0x00002332,0xFFFFF1B9,0x000003FD}, - {"0000001000010011111010101001010011011110000010000010100010000100",0x00003FB4,0xFFFFE0A5,0x00000686,0x0000253E,0xFFFFF02E,0x00000444,0x0000253E,0xFFFFF02E,0x00000444}, - {"0000001000010011111010101001010011011110001010000001100010100100",0x00003E28,0xFFFFE14D,0x0000066E,0x00001FE2,0xFFFFF39A,0x000003B1,0x00001FE2,0xFFFFF39A,0x000003B1}, - {"0000001000010011111010101001010011011110001011000000100100000100",0x000039E6,0xFFFFE44B,0x000005FE,0x0000210C,0xFFFFF2F4,0x000003DA,0x0000210C,0xFFFFF2F4,0x000003DA}, - {"0000001000010011111010101001010011011110001011000101000100000100",0x00003A4D,0xFFFFE252,0x0000067A,0x000027E2,0xFFFFECED,0x000004FA,0x000027E2,0xFFFFECED,0x000004FA}, - {"0000001000010011111010101001010011011110000010100010100101100100",0x00004065,0xFFFFE02F,0x0000069B,0x0000299D,0xFFFFED38,0x000004C2,0x0000299D,0xFFFFED38,0x000004C2}, - {"0000001000010011111010101001010011011110000011100010000010100100",0x000039EE,0xFFFFE603,0x00000594,0x0000214F,0xFFFFF429,0x0000038E,0x0000214F,0xFFFFF429,0x0000038E}, - {"0000001000010011111010101001010011011110000011100100100011100100",0x00003BD2,0xFFFFE351,0x00000618,0x000020B8,0xFFFFF377,0x000003B4,0x000020B8,0xFFFFF377,0x000003B4}, - {"0000001000010011111010101001010011011110000010100011000100100100",0x00003FAA,0xFFFFE183,0x0000065E,0x000032AE,0xFFFFE7C2,0x000005A6,0x000032AE,0xFFFFE7C2,0x000005A6}, - {"0000001000010011111010101001010011011110001011000010100110000100",0x00003AFB,0xFFFFE3E4,0x00000608,0x00002293,0xFFFFF21F,0x000003FA,0x00002293,0xFFFFF21F,0x000003FA}, - {"0000001000010011111010101001010011011110001001100010000001100100",0x0000448B,0xFFFFDD5D,0x0000070D,0x00002E4E,0xFFFFE9DF,0x00000551,0x00002E4E,0xFFFFE9DF,0x00000551}, - {"0000001000010011111010101001010011011110000011100010000110000100",0x00003D46,0xFFFFE39B,0x000005F3,0x0000218E,0xFFFFF3CD,0x00000398,0x0000218E,0xFFFFF3CD,0x00000398}, - {"0000001000010011111010101001010011011110000010000100100011100100",0x00003F01,0xFFFFDFD9,0x000006BF,0x000023AF,0xFFFFF04E,0x0000044C,0x000023AF,0xFFFFF04E,0x0000044C}, - {"0000001000010011111010101001010011011110000100000010100110100100",0x0000403D,0xFFFFDF6B,0x000006C9,0x0000270D,0xFFFFEE4B,0x0000049E,0x0000270D,0xFFFFEE4B,0x0000049E}, - {"0000001000010011111010101001010011011110000011100011100101100100",0x00003C11,0xFFFFE35C,0x00000613,0x000020F9,0xFFFFF365,0x000003B9,0x000020F9,0xFFFFF365,0x000003B9}, - {"0000001000010011111010101001010011011110001011000011100010000100",0x00003B58,0xFFFFE37D,0x0000061F,0x00002698,0xFFFFEF46,0x00000478,0x00002698,0xFFFFEF46,0x00000478}, - {"0000001000010011111010101001010011011110001010000100000110100100",0x00003EBC,0xFFFFDF7A,0x000006D6,0x0000212B,0xFFFFF195,0x0000041B,0x0000212B,0xFFFFF195,0x0000041B}, - {"0000001000010011111010101001010011011110000010000100100011000100",0x00004050,0xFFFFDEB3,0x000006FE,0x00002D6C,0xFFFFE961,0x00000582,0x00002D6C,0xFFFFE961,0x00000582}, - {"0000001000010011111010101001010011011110001001100010000001000100",0x000043F0,0xFFFFDD9C,0x00000702,0x00002B31,0xFFFFEBEA,0x000004F7,0x00002B31,0xFFFFEBEA,0x000004F7}, - {"0000001000010011111010101001010011011110000100000000100100100100",0x00003EFA,0xFFFFE093,0x00000696,0x000026DB,0xFFFFEEB3,0x00000489,0x000026DB,0xFFFFEEB3,0x00000489}, - {"0000001000010011111010101001010011011110000010000010000001100100",0x0000425D,0xFFFFDE8D,0x000006E6,0x00002CA4,0xFFFFEAD2,0x00000531,0x00002CA4,0xFFFFEAD2,0x00000531}, - {"0000001000010011111010101001010011011110001001100011100110100100",0x000043B0,0xFFFFDD03,0x00000728,0x00002946,0xFFFFECA6,0x000004DE,0x00002946,0xFFFFECA6,0x000004DE}, - {"0000001000010011111010101001010011011110001010000010100001100100",0x00003F6A,0xFFFFE03A,0x0000069D,0x00002208,0xFFFFF1F8,0x000003F6,0x00002208,0xFFFFF1F8,0x000003F6}, - {"0000001000010011111010101001010011011110001011000010100101100100",0x00003A94,0xFFFFE4A7,0x000005E2,0x000024D0,0xFFFFF100,0x00000426,0x000024D0,0xFFFFF100,0x00000426}, - {"0000001000010011111010101001010011011110001010000001000011000100",0x00003F2F,0xFFFFE0A3,0x00000688,0x00002198,0xFFFFF271,0x000003E2,0x00002198,0xFFFFF271,0x000003E2}, - {"0000001000010011111010101001010011011110000100000100100011100100",0x00003EA5,0xFFFFE032,0x000006AE,0x0000227C,0xFFFFF130,0x00000426,0x0000227C,0xFFFFF130,0x00000426}, - {"0000001000010011111010101001010011011110001001100100000101000100",0x0000442F,0xFFFFDBC4,0x0000078B,0x00003CD6,0xFFFFDE6C,0x0000076C,0x00003CD6,0xFFFFDE6C,0x0000076C}, - {"0000001000010011111010101001010011011110001010000010100010000100",0x00003DDE,0xFFFFE174,0x00000668,0x00001FF4,0xFFFFF38F,0x000003B1,0x00001FF4,0xFFFFF38F,0x000003B1}, - {"0000001000010011111010101001010011011110000010100011000101000100",0x000040B0,0xFFFFE016,0x000006A0,0x00002DBB,0xFFFFEA7F,0x00000537,0x00002DBB,0xFFFFEA7F,0x00000537}, - {"0000001000010011111010101001010011011110001011000011000100000100",0x00003429,0xFFFFEA97,0x000004DD,0x000024D5,0xFFFFF26F,0x000003DF,0x000024D5,0xFFFFF26F,0x000003DF}, - {"0000001000010011111010101001010011011110000011100001100100000100",0x00003AEB,0xFFFFE590,0x000005A3,0x000022CB,0xFFFFF347,0x000003B2,0x000022CB,0xFFFFF347,0x000003B2}, - {"0000001000010011111010101001010011011110001010000011100100000100",0x00003B8E,0xFFFFE2EF,0x00000636,0x00002351,0xFFFFF143,0x0000041C,0x00002351,0xFFFFF143,0x0000041C}, - {"0000001000010011111010101001010011011110001100100100000011000100",0x00002926,0xFFFFF0B0,0x00000410,0x0000194E,0xFFFFF94E,0x000002E9,0x0000194E,0xFFFFF94E,0x000002E9}, - {"0000001000010011111010101001010011011110001010000011000110000100",0x0000402B,0xFFFFDF78,0x000006C2,0x00002273,0xFFFFF16C,0x00000414,0x00002273,0xFFFFF16C,0x00000414}, - {"0000001000010011111010101001010011011110000010100001000010100100",0x00003D6A,0xFFFFE1D3,0x00000659,0x00002006,0xFFFFF394,0x000003B1,0x00002006,0xFFFFF394,0x000003B1}, - {"0000001000010011111010101001010011011110001010000100000001100100",0x00004042,0xFFFFDFD8,0x000006A8,0x00002135,0xFFFFF29F,0x000003D9,0x00002135,0xFFFFF29F,0x000003D9}, - {"0000001000010011111010101001010011011110000010000010000010100100",0x0000405B,0xFFFFE093,0x00000682,0x0000288F,0xFFFFEE3A,0x00000491,0x0000288F,0xFFFFEE3A,0x00000491}, - {"0000001000010011111010101001010011011110001011000100100010100100",0x00003A49,0xFFFFE30C,0x00000648,0x000023F9,0xFFFFF02D,0x00000460,0x000023F9,0xFFFFF02D,0x00000460}, - {"0000001000010011111010101001010011011110001010000010100101100100",0x00003D59,0xFFFFE1CC,0x0000065B,0x00002013,0xFFFFF37D,0x000003B6,0x00002013,0xFFFFF37D,0x000003B6}, - {"0000001000010011111010101001010011011110001011000011100110000100",0x000040C1,0xFFFFDF8C,0x000006CA,0x00003271,0xFFFFE6CA,0x000005EA,0x00003271,0xFFFFE6CA,0x000005EA}, - {"0000001000010011111010101001010011011110001001100010000011100100",0x000042E9,0xFFFFDFDC,0x0000068C,0x00002ED9,0xFFFFEAAF,0x0000051B,0x00002ED9,0xFFFFEAAF,0x0000051B}, - {"0000001000010011111010101001010011011110000010000011000010000100",0x000042ED,0xFFFFDE50,0x000006F0,0x00002FCF,0xFFFFE8BB,0x0000058C,0x00002FCF,0xFFFFE8BB,0x0000058C}, - {"0000001000010011111010101001010011011110000010100100000100000100",0x00003EBD,0xFFFFE099,0x00000698,0x00002709,0xFFFFEE7B,0x00000495,0x00002709,0xFFFFEE7B,0x00000495}, - {"0000001000010011111010101001010011011110001010000100100100000100",0x00003F71,0xFFFFDF82,0x000006C9,0x0000219B,0xFFFFF1AD,0x0000040F,0x0000219B,0xFFFFF1AD,0x0000040F}, - {"0000001000010011111010101001010011011110001010000000100011100100",0x00003E73,0xFFFFE080,0x0000069B,0x000020E7,0xFFFFF273,0x000003E9,0x000020E7,0xFFFFF273,0x000003E9}, - {"0000001000010011111010101001010011011110000011100011000110000100",0x00003E14,0xFFFFE278,0x0000062C,0x00002275,0xFFFFF2B3,0x000003CE,0x00002275,0xFFFFF2B3,0x000003CE}, - {"0000001000010011111010101001010011011110001011000010000110100100",0x00003ABB,0xFFFFE3B9,0x00000615,0x00002192,0xFFFFF28F,0x000003EB,0x00002192,0xFFFFF28F,0x000003EB}, - {"0000001000010011111010101001010011011110001010000011000100100100",0x00003D53,0xFFFFE255,0x00000643,0x0000275B,0xFFFFEEED,0x00000479,0x0000275B,0xFFFFEEED,0x00000479}, - {"0000001000010011111010101001010011011110001001100010100001100100",0x000043E3,0xFFFFDDC3,0x000006FB,0x00002B6B,0xFFFFEBD6,0x000004FA,0x00002B6B,0xFFFFEBD6,0x000004FA}, - {"0000001000010011111010101001010011011110000011100010000101000100",0x00003BDE,0xFFFFE507,0x000005B4,0x000022CE,0xFFFFF358,0x000003AB,0x000022CE,0xFFFFF358,0x000003AB}, - {"0000001000010011111010101001010011011110001100100011000101100100",0x00002460,0xFFFFF3B5,0x000003A2,0x000014E7,0xFFFFFC32,0x0000027C,0x000014E7,0xFFFFFC32,0x0000027C}, - {"0000001000010011111010101001010011011110001010000010000011000100",0x00003D20,0xFFFFE298,0x0000062F,0x00002080,0xFFFFF3AF,0x000003A8,0x00002080,0xFFFFF3AF,0x000003A8}, - {"0000001000010011111010101001010011011110000010000001100100000100",0x00003E14,0xFFFFE221,0x00000641,0x000021BB,0xFFFFF2EA,0x000003CA,0x000021BB,0xFFFFF2EA,0x000003CA}, - {"0000001000010011111010101001010011011110000010100100000011000100",0x00003DE1,0xFFFFE14E,0x00000677,0x00002468,0xFFFFF068,0x00000440,0x00002468,0xFFFFF068,0x00000440}, - {"0000001000010011111010101001010011011110001001100001000010000100",0x00004372,0xFFFFDDF8,0x000006F5,0x00002B3F,0xFFFFEBE8,0x000004F8,0x00002B3F,0xFFFFEBE8,0x000004F8}, - {"0000001000010011111010101001010011011110000010100010100011000100",0x00003E4F,0xFFFFE2A3,0x0000062B,0x00002F5A,0xFFFFEA37,0x0000053B,0x00002F5A,0xFFFFEA37,0x0000053B}, - {"0000001000010011111010101001010011011110001010000101000011100100",0x00003E07,0xFFFFE02F,0x000006B6,0x0000216B,0xFFFFF1A3,0x00000416,0x0000216B,0xFFFFF1A3,0x00000416}, - {"0000001000010011111010101001010011011110001010000011100010100100",0x00003DAB,0xFFFFE128,0x0000067F,0x0000216F,0xFFFFF236,0x000003F3,0x0000216F,0xFFFFF236,0x000003F3}, - {"0000001000010011111010101001010011011110001011000010100100100100",0x0000364B,0xFFFFE8CB,0x0000052A,0x00002568,0xFFFFF1B2,0x00000400,0x00002568,0xFFFFF1B2,0x00000400}, - {"0000001000010011111010101001010011011110001001100001000001100100",0x00004219,0xFFFFDE87,0x000006E8,0x00002C59,0xFFFFEAEE,0x00000529,0x00002C59,0xFFFFEAEE,0x00000529}, - {"0000001000010011111010101001010011011110000011100001100101000100",0x000039A8,0xFFFFE602,0x00000594,0x00001D06,0xFFFFF6F0,0x00000316,0x00001D06,0xFFFFF6F0,0x00000316}, - {"0000001000010011111010101001010011011110001001100001000011100100",0x00004052,0xFFFFE01C,0x00000698,0x00002310,0xFFFFF1A1,0x000003FE,0x00002310,0xFFFFF1A1,0x000003FE}, - {"0000001000010011111010101001010011011110000011100010100000100100",0x00003C1C,0xFFFFE3EB,0x000005F1,0x00002289,0xFFFFF2CF,0x000003C9,0x00002289,0xFFFFF2CF,0x000003C9}, - {"0000001000010011111010101001010011011110000011100101000100100100",0x00003F19,0xFFFFE085,0x0000069E,0x00002B94,0xFFFFEB72,0x0000051D,0x00002B94,0xFFFFEB72,0x0000051D}, - {"0000001000010011111010101001010011011110000011100100000110100100",0x00003C51,0xFFFFE2AD,0x00000638,0x0000206B,0xFFFFF361,0x000003BE,0x0000206B,0xFFFFF361,0x000003BE}, - {"0000001000010011111010101001010011011110001001100001000011000100",0x000040B9,0xFFFFDFBB,0x000006AB,0x0000241F,0xFFFFF0CC,0x00000425,0x0000241F,0xFFFFF0CC,0x00000425}, - {"0000001000010011111010101001010011011110000010100010000001100100",0x00003E62,0xFFFFE12C,0x00000678,0x00002445,0xFFFFF09E,0x00000435,0x00002445,0xFFFFF09E,0x00000435}, - {"0000001000010011111010101001010011011110000011100001100110000100",0x00003C97,0xFFFFE399,0x000005FB,0x0000209D,0xFFFFF41D,0x0000038F,0x0000209D,0xFFFFF41D,0x0000038F}, - {"0000001000010011111010101001010011011110000011100011000101000100",0x00003FF9,0xFFFFE1E9,0x0000063E,0x00002E96,0xFFFFEAF5,0x00000516,0x00002E96,0xFFFFEAF5,0x00000516}, - {"0000001000010011111010101001010011011110000010100011000010000100",0x00003F04,0xFFFFE109,0x0000067A,0x000026E1,0xFFFFEF0B,0x00000476,0x000026E1,0xFFFFEF0B,0x00000476}, - {"0000001000010011111010101001010011011110000100000001000100100100",0x00003E3E,0xFFFFE187,0x00000660,0x00002049,0xFFFFF38D,0x000003B0,0x00002049,0xFFFFF38D,0x000003B0}, - {"0000001000010011111010101001010011011110001010000010100101000100",0x00003D58,0xFFFFE253,0x0000063D,0x00002158,0xFFFFF308,0x000003C3,0x00002158,0xFFFFF308,0x000003C3}, - {"0000001000010011111010101001010011011110000010000100000011000100",0x00004074,0xFFFFDF8D,0x000006C0,0x00002799,0xFFFFEE19,0x000004A5,0x00002799,0xFFFFEE19,0x000004A5}, - {"0000001000010011111010101001010011011110001010000001100100100100",0x00003DAF,0xFFFFE1C9,0x00000659,0x000020E5,0xFFFFF313,0x000003C6,0x000020E5,0xFFFFF313,0x000003C6}, - {"0000001000010011111010101001010011011110000010100011100101100100",0x000041DD,0xFFFFDDFA,0x0000071B,0x0000348D,0xFFFFE4B4,0x0000064C,0x0000348D,0xFFFFE4B4,0x0000064C}, - {"0000001000010011111010101001010011011110001011000010100010000100",0x00003947,0xFFFFE5AE,0x000005B8,0x000024A6,0xFFFFF140,0x0000041D,0x000024A6,0xFFFFF140,0x0000041D}, - {"0000001000010011111010101001010011011110000100000001100001000100",0x00003D35,0xFFFFE197,0x0000066E,0x00002248,0xFFFFF1BC,0x00000408,0x00002248,0xFFFFF1BC,0x00000408}, - {"0000001000010011111010101001010011011110000010100001100011100100",0x00003F4F,0xFFFFE13E,0x0000066D,0x00002AF0,0xFFFFEC99,0x000004DB,0x00002AF0,0xFFFFEC99,0x000004DB}, - {"0000001000010011111010101001010011011110001001100011100101000100",0x0000430F,0xFFFFDDFB,0x000006FC,0x00002D4D,0xFFFFEA55,0x00000540,0x00002D4D,0xFFFFEA55,0x00000540}, - {"0000001000010011111010101001010011011110000011100010100101000100",0x00003B22,0xFFFFE543,0x000005B1,0x000022E1,0xFFFFF31B,0x000003B9,0x000022E1,0xFFFFF31B,0x000003B9}, - {"0000001000010011111010101001010011011110000011100010000010000100",0x00003978,0xFFFFE611,0x00000592,0x00001C36,0xFFFFF771,0x00000302,0x00001C36,0xFFFFF771,0x00000302}, - {"0000001000010011111010101001010011011110001001100010000101100100",0x000044DF,0xFFFFDDAB,0x000006F2,0x00002CEA,0xFFFFEB47,0x00000507,0x00002CEA,0xFFFFEB47,0x00000507}, - {"0000001000010011111010101001010011011110000010100011100011000100",0x00003E9B,0xFFFFE12C,0x0000067C,0x00002B79,0xFFFFEBD9,0x00000503,0x00002B79,0xFFFFEBD9,0x00000503}, - {"0000001000010011111010101001010011011110001001100011000001000100",0x00004464,0xFFFFDCD3,0x00000731,0x00002D14,0xFFFFEA2D,0x0000054E,0x00002D14,0xFFFFEA2D,0x0000054E}, - {"0000001000010011111010101001010011011110001010000001000100100100",0x00003FB3,0xFFFFE052,0x00000693,0x000020AC,0xFFFFF311,0x000003C6,0x000020AC,0xFFFFF311,0x000003C6}, - {"0000001000010011111010101001010011011110001011000001000010000100",0x00003BDA,0xFFFFE2FB,0x00000636,0x0000261E,0xFFFFEF72,0x00000471,0x0000261E,0xFFFFEF72,0x00000471}, - {"0000001000010011111010101001010011011110001011000001100101100100",0x00003D72,0xFFFFE28A,0x0000063E,0x000029D8,0xFFFFED54,0x000004C7,0x000029D8,0xFFFFED54,0x000004C7}, - {"0000001000010011111010101001010011011110001011000010100000100100",0x00003E26,0xFFFFE102,0x00000694,0x00002DD1,0xFFFFE9CA,0x0000056D,0x00002DD1,0xFFFFE9CA,0x0000056D}, - {"0000001000010011111010101001010011011110000100000100000100100100",0x000041CD,0xFFFFDE97,0x000006ED,0x00002DE5,0xFFFFE9B9,0x00000565,0x00002DE5,0xFFFFE9B9,0x00000565}, - {"0000001000010011111010101001010011011110000010100010100110000100",0x00003F30,0xFFFFE06E,0x00000698,0x000024FF,0xFFFFEFFC,0x0000044F,0x000024FF,0xFFFFEFFC,0x0000044F}, - {"0000001000010011111010101001010011011110001011000011100011000100",0x0000378B,0xFFFFE6B4,0x00000594,0x000023A7,0xFFFFF1DC,0x00000407,0x000023A7,0xFFFFF1DC,0x00000407}, - {"0000001000010011111010101001010011011110000011100100000101100100",0x00003CD7,0xFFFFE28D,0x00000636,0x00002036,0xFFFFF3B5,0x000003AA,0x00002036,0xFFFFF3B5,0x000003AA}, - {"0000001000010011111010101001010011011110000010100011100010000100",0x00003EF9,0xFFFFE0AA,0x0000068D,0x000024D3,0xFFFFF02F,0x00000445,0x000024D3,0xFFFFF02F,0x00000445}, - {"0000001000010011111010101001010011011110001010000011100101000100",0x00003D08,0xFFFFE1BB,0x00000665,0x00002159,0xFFFFF26F,0x000003E6,0x00002159,0xFFFFF26F,0x000003E6}, - {"0000001000010011111010101001010011011110001011000010000011000100",0x000038A9,0xFFFFE6CA,0x00000580,0x000025D3,0xFFFFF101,0x00000421,0x000025D3,0xFFFFF101,0x00000421}, - {"0000001000010011111010101001010011011110000010100010000010100100",0x00003E45,0xFFFFE1F8,0x0000064D,0x000027E3,0xFFFFEEBB,0x0000047F,0x000027E3,0xFFFFEEBB,0x0000047F}, - {"0000001000010011111010101001010011011110000011100011100001100100",0x00003F76,0xFFFFE128,0x0000066E,0x0000286B,0xFFFFEE4C,0x00000493,0x0000286B,0xFFFFEE4C,0x00000493}, - {"0000001000010011111010101001010011011110001001100100000100000100",0x0000440D,0xFFFFDCA2,0x0000074F,0x00003817,0xFFFFE256,0x000006AF,0x00003817,0xFFFFE256,0x000006AF}, - {"0000001000010011111010101001010011011110000100000101000100000100",0x00003EE1,0xFFFFDFA7,0x000006D4,0x000027EA,0xFFFFED2B,0x000004DE,0x000027EA,0xFFFFED2B,0x000004DE}, - {"0000001000010011111010101001010011011110001011000011100001100100",0x00003C62,0xFFFFE285,0x0000064A,0x00002520,0xFFFFF001,0x0000045C,0x00002520,0xFFFFF001,0x0000045C}, - {"0000001000010011111010101001010011011110001100100011100101100100",0x0000272E,0xFFFFF17A,0x000003FA,0x0000150B,0xFFFFFBD5,0x00000284,0x0000150B,0xFFFFFBD5,0x00000284}, - {"0000001000010011111010101001010011011110001001100001100100100100",0x00004275,0xFFFFDF69,0x000006A5,0x000025AA,0xFFFFF05C,0x0000042B,0x000025AA,0xFFFFF05C,0x0000042B}, - {"0000001000010011111010101001010011011110000011100100000011100100",0x00003CAA,0xFFFFE392,0x000005FF,0x000023A8,0xFFFFF20E,0x000003E9,0x000023A8,0xFFFFF20E,0x000003E9}, - {"0000001000010011111010101001010011011110001011000101000011000100",0x00003CF8,0xFFFFE0FB,0x000006A6,0x00002CA7,0xFFFFE9FF,0x0000056E,0x00002CA7,0xFFFFE9FF,0x0000056E}, - {"0000001000010011111010101001010011011110001010000010000100100100",0x00003D00,0xFFFFE296,0x00000633,0x000021C1,0xFFFFF2C8,0x000003CF,0x000021C1,0xFFFFF2C8,0x000003CF}, - {"0000001000010011111010101001010011011110001010000011100011100100",0x00003B46,0xFFFFE301,0x00000632,0x0000204C,0xFFFFF33B,0x000003C8,0x0000204C,0xFFFFF33B,0x000003C8}, - {"0000001000010011111010101001010011011110001000000100000101100100",0x00002026,0xFFFFF5CE,0x00000368,0x00001598,0xFFFFFB29,0x000002C3,0x00001598,0xFFFFFB29,0x000002C3}, - {"0000001000010011111010101001010011011110001010000011000101100100",0x00003DCA,0xFFFFE178,0x00000668,0x00001FDB,0xFFFFF39D,0x000003AF,0x00001FDB,0xFFFFF39D,0x000003AF}, - {"0000001000010011111010101001010011011110001011000100100011000100",0x00003A59,0xFFFFE327,0x00000642,0x000024B9,0xFFFFEFC4,0x00000471,0x000024B9,0xFFFFEFC4,0x00000471}, - {"0000001000010011111010101001010011011110001011000010100101000100",0x00003C26,0xFFFFE440,0x000005EB,0x00002C0F,0xFFFFEC88,0x000004E0,0x00002C0F,0xFFFFEC88,0x000004E0}, - {"0000001000010011111010101001010011011110000010000011100010000100",0x00004149,0xFFFFDEB8,0x000006E7,0x0000280A,0xFFFFED89,0x000004C2,0x0000280A,0xFFFFED89,0x000004C2}, - {"0000001000010011111010101001010011011110000011100100000100100100",0x00003EB4,0xFFFFE1E5,0x0000064D,0x0000299F,0xFFFFEDB3,0x000004A9,0x0000299F,0xFFFFEDB3,0x000004A9}, - {"0000001000010011111010101001010011011110001011000011100110100100",0x00003BBF,0xFFFFE268,0x0000065A,0x00002504,0xFFFFEFB0,0x00000470,0x00002504,0xFFFFEFB0,0x00000470}, - {"0000001000010011111010101001010011011110000010000100100100000100",0x00004203,0xFFFFDDC6,0x00000720,0x0000303B,0xFFFFE78F,0x000005D0,0x0000303B,0xFFFFE78F,0x000005D0}, - {"0000001000010011111010101001010011011110000011100011100110000100",0x00003DA3,0xFFFFE244,0x0000063E,0x000021B4,0xFFFFF2DA,0x000003CD,0x000021B4,0xFFFFF2DA,0x000003CD}, - {"0000001000010011111010101001010011011110000010100011100011100100",0x00004035,0xFFFFE065,0x0000069B,0x00003323,0xFFFFE6D6,0x000005D8,0x00003323,0xFFFFE6D6,0x000005D8}, - {"0000001000010011111010101001010011011110001011000001000101100100",0x00003944,0xFFFFE4E5,0x000005E2,0x00001F3C,0xFFFFF456,0x0000039D,0x00001F3C,0xFFFFF456,0x0000039D}, - {"0000001000010011111010101001010011011110000001100001100100000100",0x000032D8,0xFFFFEAE8,0x000004E6,0x00001812,0xFFFFFA1C,0x000002BC,0x00001812,0xFFFFFA1C,0x000002BC}, - {"0000001000010011111100001111110101000010110100100010100101000100",0x000041F6,0xFFFFE025,0x0000069A,0x0000241E,0xFFFFF1B4,0x00000402,0x0000241E,0xFFFFF1B4,0x00000402}, - {"0000001000010011111100001111111010011001000011000011000010100100",0x00003300,0xFFFFEB60,0x000004C1,0x00001E15,0xFFFFF6A6,0x0000033B,0x00001E15,0xFFFFF6A6,0x0000033B}, - {"0000001000010011111010101001010011011110000001000000100010100100",0x000037F0,0xFFFFE68F,0x0000059B,0x00001F8A,0xFFFFF467,0x000003A3,0x00001F8A,0xFFFFF467,0x000003A3}, - {"0000001000010011111100001111111010011001000110000010100110000100",0x000025D8,0xFFFFF2AA,0x000003C3,0x000018A8,0xFFFFF9BE,0x000002D2,0x000018A8,0xFFFFF9BE,0x000002D2}, - {"0000001000010011111100001111111010011001000001100010000011000100",0x0000364F,0xFFFFE988,0x000004FC,0x00001E51,0xFFFFF633,0x0000034F,0x00001E51,0xFFFFF633,0x0000034F}, - {"0000001000010011111010101001010011011110000001100001000101000100",0x00002288,0xFFFFF483,0x0000036C,0x0000280F,0xFFFFEF39,0x0000047B,0x0000280F,0xFFFFEF39,0x0000047B}, - {"0000001000010011111100001111111010011001000010000010000010000100",0x00003322,0xFFFFEA7E,0x000004ED,0x00001DAD,0xFFFFF62B,0x00000355,0x00001DAD,0xFFFFF62B,0x00000355}, - {"0000001000010011111010101001010011011110000000100101000011100100",0x00002B7B,0xFFFFEE4F,0x0000045B,0x00001AA2,0xFFFFF710,0x0000033E,0x00001AA2,0xFFFFF710,0x0000033E}, - {"0000001000010011111100001111111010011001000001000010000011000100",0x000034CC,0xFFFFEA79,0x000004E4,0x00001B05,0xFFFFF8B3,0x000002EC,0x00001B05,0xFFFFF8B3,0x000002EC}, - {"0000001000010011111100001111110101000010110111000010100001100100",0x00003837,0xFFFFE5ED,0x000005C3,0x00001ACB,0xFFFFF7B2,0x00000314,0x00001ACB,0xFFFFF7B2,0x00000314}, - {"0000001000010011111100001111111010011001000001000100000101100100",0x0000352D,0xFFFFE88F,0x00000548,0x000021E6,0xFFFFF3B5,0x000003AA,0x000021E6,0xFFFFF3B5,0x000003AA}, - {"0000001000010011111100001111111010011001000010100100100010000100",0x00003300,0xFFFFE835,0x0000057B,0x00001A85,0xFFFFF715,0x00000336,0x00001A85,0xFFFFF715,0x00000336}, - {"0000001000010011111010101001010011011110000001000100100010100100",0x000033FA,0xFFFFE851,0x00000565,0x00001A8E,0xFFFFF727,0x0000033B,0x00001A8E,0xFFFFF727,0x0000033B}, - {"0000001000010011111100001111110101000010110110100011100100100100",0x000039D3,0xFFFFE5D3,0x000005B0,0x00001888,0xFFFFF978,0x000002C8,0x00001888,0xFFFFF978,0x000002C8}, - {"0000001000010011111100001111111010011001000011100100100001100100",0x00002F6B,0xFFFFEC53,0x000004B9,0x00001C15,0xFFFFF71B,0x00000337,0x00001C15,0xFFFFF71B,0x00000337}, - {"0000001000010011111100001111111010011001000001100100000101000100",0x0000384D,0xFFFFE737,0x00000569,0x00001D2D,0xFFFFF673,0x00000343,0x00001D2D,0xFFFFF673,0x00000343}, - {"0000001000010011111100001111111010011001000001100010000010100100",0x00003A49,0xFFFFE70B,0x0000055F,0x00001A63,0xFFFFF8CD,0x000002E2,0x00001A63,0xFFFFF8CD,0x000002E2}, - {"0000001000010011111100001111111010011001000001000010100110000100",0x0000311E,0xFFFFEB97,0x000004C6,0x00001EAE,0xFFFFF5A9,0x00000367,0x00001EAE,0xFFFFF5A9,0x00000367}, - {"0000001000010011111100001111111010011001000011100001000100100100",0x000027D3,0xFFFFF075,0x00000417,0x00002001,0xFFFFF44A,0x000003A2,0x00002001,0xFFFFF44A,0x000003A2}, - {"0000001000010011111100001111111010011001000001100100100100000100",0x00003B72,0xFFFFE4BD,0x000005DC,0x00001D76,0xFFFFF606,0x0000035A,0x00001D76,0xFFFFF606,0x0000035A}, - {"0000001000010011111100001111111010011001000100000001000100100100",0x00002E0F,0xFFFFECA7,0x000004AE,0x00001DC6,0xFFFFF5BF,0x0000036A,0x00001DC6,0xFFFFF5BF,0x0000036A}, - {"0000001000010011111100001111111010011001000000100011100010100100",0x000032C7,0xFFFFEA7A,0x000004F0,0x00001A7B,0xFFFFF827,0x00000301,0x00001A7B,0xFFFFF827,0x00000301}, - {"0000001000010011111010101001010011011110000001000100100010000100",0x0000312D,0xFFFFEA39,0x00000515,0x00001948,0xFFFFF800,0x00000318,0x00001948,0xFFFFF800,0x00000318}, - {"0000001000010011111010101001010011011110000001100010000010000100",0x00003611,0xFFFFE8D7,0x00000533,0x00001929,0xFFFFF965,0x000002D2,0x00001929,0xFFFFF965,0x000002D2}, - {"0000001000010011111100001111111010011001001011000011000011100100",0x00002FE2,0xFFFFED89,0x00000470,0x00001A3C,0xFFFFF955,0x000002D5,0x00001A3C,0xFFFFF955,0x000002D5}, - {"0000001000010011111010101001010011011110000000100000100010100100",0x000035FF,0xFFFFE884,0x00000548,0x0000182A,0xFFFFF9AB,0x000002CF,0x0000182A,0xFFFFF9AB,0x000002CF}, - {"0000001000010011111100001111111010011001000000100010000011100100",0x00003597,0xFFFFE904,0x00000528,0x00001A94,0xFFFFF840,0x00000300,0x00001A94,0xFFFFF840,0x00000300}, - {"0000001000010011111100001111111010011001000110000001100101000100",0x000026CB,0xFFFFF1FB,0x000003E4,0x000017CC,0xFFFFFA25,0x000002C8,0x000017CC,0xFFFFFA25,0x000002C8}, - {"0000001000010011111010101001010011011110000001100000100011000100",0x00003274,0xFFFFEA39,0x0000050C,0x00001B20,0xFFFFF7C1,0x00000314,0x00001B20,0xFFFFF7C1,0x00000314}, - {"0000001000010011111100001111110101000010110110000010100100100100",0x0000280B,0xFFFFF283,0x000003B5,0x000018D0,0xFFFFF992,0x000002EC,0x000018D0,0xFFFFF992,0x000002EC}, - {"0000001000010011111100001111111010011001000001100010000100000100",0x000033AB,0xFFFFEB1B,0x000004C4,0x00001FEE,0xFFFFF53A,0x00000378,0x00001FEE,0xFFFFF53A,0x00000378}, - {"0000001000010011111100001111111010011001000010100011100101100100",0x00002F79,0xFFFFEB0C,0x000004FA,0x00001E57,0xFFFFF4BF,0x0000039B,0x00001E57,0xFFFFF4BF,0x0000039B}, - {"0000001000010011111100001111111010011001000001000100100011100100",0x00003487,0xFFFFE8F2,0x00000539,0x0000185B,0xFFFFF9AE,0x000002BA,0x0000185B,0xFFFFF9AE,0x000002BA}, - {"0000001000010011111100001111111010011001000010100001100010100100",0x00003500,0xFFFFE793,0x0000058A,0x00001AA2,0xFFFFF792,0x0000031D,0x00001AA2,0xFFFFF792,0x0000031D}, - {"0000001000010011111100001111111010011001000010000001000101100100",0x00003943,0xFFFFE54D,0x000005D9,0x00001BC8,0xFFFFF6E0,0x00000339,0x00001BC8,0xFFFFF6E0,0x00000339}, - {"0000001000010011111010101001010011011110000001000011000010100100",0x0000306D,0xFFFFEC5E,0x000004A5,0x00001A3A,0xFFFFF85F,0x00000304,0x00001A3A,0xFFFFF85F,0x00000304}, - {"0000001000010011111100001111110101000010110110000011000010000100",0x00002BA4,0xFFFFEE8D,0x0000046A,0x0000198C,0xFFFFF88E,0x00000307,0x0000198C,0xFFFFF88E,0x00000307}, - {"0000001000010011111100001111110101000010110100100001100011100100",0x00003D30,0xFFFFE2F6,0x0000062A,0x000025DC,0xFFFFF074,0x00000435,0x000025DC,0xFFFFF074,0x00000435}, - {"0000001000010011111100001111110101000010110110000011100101100100",0x00002CD6,0xFFFFED79,0x0000049B,0x000016D0,0xFFFFFA53,0x000002BB,0x000016D0,0xFFFFFA53,0x000002BB}, - {"0000001000010011111100001111111010011001000101100011000101100100",0x00002484,0xFFFFF3BD,0x000003A0,0x000015B8,0xFFFFFB6B,0x000002A4,0x000015B8,0xFFFFFB6B,0x000002A4}, - {"0000001000010011111100001111111010011001000011100011100101000100",0x000038AE,0xFFFFE6D1,0x00000587,0x00001A2A,0xFFFFF8F1,0x000002D4,0x00001A2A,0xFFFFF8F1,0x000002D4}, - {"0000001000010011111100001111111010011001000001000100100101000100",0x000036FD,0xFFFFE76C,0x00000576,0x00001EE4,0xFFFFF58D,0x00000361,0x00001EE4,0xFFFFF58D,0x00000361}, - {"0000001000010011111100001111110101000010110110000011000010100100",0x00002BCF,0xFFFFEF28,0x00000448,0x00001B93,0xFFFFF7BA,0x00000327,0x00001B93,0xFFFFF7BA,0x00000327}, - {"0000001000010011111100001111111010011001000001100010100010000100",0x00003834,0xFFFFE818,0x0000053B,0x00001AFE,0xFFFFF85C,0x000002F3,0x00001AFE,0xFFFFF85C,0x000002F3}, - {"0000001000010011111100001111111010011001001100100011000110100100",0x00002EF7,0xFFFFEBFC,0x000004CE,0x00001897,0xFFFFF8EF,0x000002EC,0x00001897,0xFFFFF8EF,0x000002EC}, - {"0000001000010011111100001111111010011001001011000001100011000100",0x000035BD,0xFFFFE8BB,0x0000053B,0x00001F22,0xFFFFF561,0x00000373,0x00001F22,0xFFFFF561,0x00000373}, - {"0000001000010011111100001111111010011001000110000011100110000100",0x00002D42,0xFFFFEE1D,0x00000478,0x000016F0,0xFFFFFAAE,0x000002B3,0x000016F0,0xFFFFFAAE,0x000002B3}, - {"0000001000010011111010101001010011011110000001000101000100100100",0x00002F98,0xFFFFEB3C,0x000004F0,0x00001903,0xFFFFF818,0x00000319,0x00001903,0xFFFFF818,0x00000319}, - {"0000001000010011111100001111110101000010110101000010000101000100",0x00004081,0xFFFFDF13,0x000006F3,0x00002A6D,0xFFFFEC1B,0x00000509,0x00002A6D,0xFFFFEC1B,0x00000509}, - {"0000001000010011111010101001010011011110000001000000100100000100",0x00002D68,0xFFFFED21,0x00000498,0x00001FF6,0xFFFFF427,0x000003B0,0x00001FF6,0xFFFFF427,0x000003B0}, - {"0000001000010011111100001111111010011001000000100011100010000100",0x00003243,0xFFFFEA5C,0x000004FD,0x000020FB,0xFFFFF39E,0x000003C0,0x000020FB,0xFFFFF39E,0x000003C0}, - {"0000001000010011111100001111110101000010110110000100100010100100",0x00002F20,0xFFFFEC19,0x000004C6,0x00001748,0xFFFFF99F,0x000002DA,0x00001748,0xFFFFF99F,0x000002DA}, - {"0000001000010011111100001111111010011001000100000011100110000100",0x00002D68,0xFFFFED21,0x00000498,0x00001A43,0xFFFFF843,0x000002F9,0x00001A43,0xFFFFF843,0x000002F9}, - {"0000001000010011111100001111111010011001000000100010000010100100",0x0000396E,0xFFFFE616,0x000005A9,0x00001A51,0xFFFFF850,0x000002FA,0x00001A51,0xFFFFF850,0x000002FA}, - {"0000001000010011111100001111111010011001000001000011000101000100",0x0000305C,0xFFFFED4B,0x0000046C,0x00001CF9,0xFFFFF7BA,0x00000304,0x00001CF9,0xFFFFF7BA,0x00000304}, - {"0000001000010011111100001111110101000010110110100100000101100100",0x0000343C,0xFFFFE869,0x00000559,0x00001CE2,0xFFFFF614,0x00000359,0x00001CE2,0xFFFFF614,0x00000359}, - {"0000001000010011111100001111111010011001000110000011100101100100",0x00002782,0xFFFFF1FE,0x000003D9,0x000015DC,0xFFFFFB8B,0x00000290,0x000015DC,0xFFFFFB8B,0x00000290}, - {"0000001000010011111100001111111010011001000110000001100011000100",0x00002B9C,0xFFFFEF63,0x00000443,0x00001369,0xFFFFFD51,0x00000244,0x00001369,0xFFFFFD51,0x00000244}, - {"0000001000010011111100001111111010011001000010100010000010000100",0x000035F8,0xFFFFE743,0x00000592,0x000018D8,0xFFFFF8EE,0x000002E4,0x000018D8,0xFFFFF8EE,0x000002E4}, - {"0000001000010011111010101001010011011110000001100010100001000100",0x00002B72,0xFFFFEF1E,0x0000043C,0x00002647,0xFFFFF092,0x0000043E,0x00002647,0xFFFFF092,0x0000043E}, - {"0000001000010011111100001111111010011001000100000010000110000100",0x00002EC9,0xFFFFEC5F,0x000004B8,0x000018B6,0xFFFFF936,0x000002D8,0x000018B6,0xFFFFF936,0x000002D8}, - {"0000001000010011111100001111111010011001000001100100000010000100",0x000038A7,0xFFFFE6AC,0x00000589,0x00001C42,0xFFFFF70B,0x00000329,0x00001C42,0xFFFFF70B,0x00000329}, - {"0000001000010011111100001111111010011001001100000000100010100100",0x00002F6B,0xFFFFEBF6,0x000004CF,0x000018AE,0xFFFFF928,0x000002E3,0x000018AE,0xFFFFF928,0x000002E3}, - {"0000001000010011111100001111110101000010110110100101000100000100",0x000029CD,0xFFFFEEE1,0x00000459,0x00001AB5,0xFFFFF76F,0x00000324,0x00001AB5,0xFFFFF76F,0x00000324}, - {"0000001000010011111010101001010011011110000001100011100011000100",0x00003921,0xFFFFE71D,0x00000577,0x00001646,0xFFFFFB24,0x00000293,0x00001646,0xFFFFFB24,0x00000293}, - {"0000001000010011111010101001010011011110000001000100000101100100",0x00003940,0xFFFFE521,0x000005E8,0x00001947,0xFFFFF839,0x0000030D,0x00001947,0xFFFFF839,0x0000030D}, - {"0000001000010011111100001111110101000010110100100100000101100100",0x00003DCA,0xFFFFE211,0x00000659,0x0000250E,0xFFFFF072,0x00000443,0x0000250E,0xFFFFF072,0x00000443}, - {"0000001000010011111100001111111010011001000011000000100100000100",0x00002E95,0xFFFFEC20,0x000004C9,0x000015B4,0xFFFFFAD3,0x0000029D,0x000015B4,0xFFFFFAD3,0x0000029D}, - {"0000001000010011111100001111111010011001000001000001000010000100",0x00002C11,0xFFFFEE6E,0x00000468,0x00001901,0xFFFFF924,0x000002E7,0x00001901,0xFFFFF924,0x000002E7}, - {"0000001000010011111010101001010011011110000001100010000100000100",0x0000293F,0xFFFFF158,0x000003E6,0x0000183F,0xFFFFF9F6,0x000002D2,0x0000183F,0xFFFFF9F6,0x000002D2}, - {"0000001000010011111100001111111010011001000011100001000100000100",0x00002A67,0xFFFFEF34,0x0000043E,0x00001C6F,0xFFFFF6F1,0x0000032B,0x00001C6F,0xFFFFF6F1,0x0000032B}, - {"0000001000010011111010101001010011011110000001100101000100100100",0x00002F8D,0xFFFFEB77,0x000004DA,0x00001C0D,0xFFFFF627,0x00000365,0x00001C0D,0xFFFFF627,0x00000365}, - {"0000001000010011111100001111111010011001000011000011100011000100",0x00003476,0xFFFFEA5B,0x000004E7,0x00001DBF,0xFFFFF6C7,0x00000333,0x00001DBF,0xFFFFF6C7,0x00000333}, - {"0000001000010011111100001111111010011001000011100000100101000100",0x00003336,0xFFFFE92F,0x00000546,0x00001614,0xFFFFFAE0,0x00000296,0x00001614,0xFFFFFAE0,0x00000296}, - {"0000001000010011111100001111111010011001000101100010000101100100",0x00002513,0xFFFFF323,0x000003BC,0x000016DB,0xFFFFFA79,0x000002CD,0x000016DB,0xFFFFFA79,0x000002CD}, - {"0000001000010011111100001111111010011001000010100010100101000100",0x000035A7,0xFFFFE78E,0x00000584,0x00001B0D,0xFFFFF77D,0x0000031F,0x00001B0D,0xFFFFF77D,0x0000031F}, - {"0000001000010011111100001111111010011001001100100011100011100100",0x00003171,0xFFFFEB98,0x000004C6,0x00001C76,0xFFFFF71F,0x0000032F,0x00001C76,0xFFFFF71F,0x0000032F}, - {"0000001000010011111100001111110101000010110110100001000010000100",0x00002C52,0xFFFFED2E,0x000004A7,0x00002182,0xFFFFF2F4,0x000003E4,0x00002182,0xFFFFF2F4,0x000003E4}, - {"0000001000010011111100001111111010011001000100000010100100100100",0x000032E1,0xFFFFEB39,0x000004D0,0x00001B55,0xFFFFF859,0x000002FA,0x00001B55,0xFFFFF859,0x000002FA}, - {"0000001000010011111100001111111010011001000110000100100010100100",0x000029B6,0xFFFFEFF7,0x00000430,0x0000151B,0xFFFFFBC6,0x0000027F,0x0000151B,0xFFFFFBC6,0x0000027F}, - {"0000001000010011111100001111110101000010110110100001100101100100",0x00002FF7,0xFFFFEB67,0x000004DA,0x000020E9,0xFFFFF363,0x000003CE,0x000020E9,0xFFFFF363,0x000003CE}, - {"0000001000010011111100001111110101000010110110100101000100100100",0x00003CDD,0xFFFFE2B2,0x00000649,0x00001B18,0xFFFFF739,0x00000329,0x00001B18,0xFFFFF739,0x00000329}, - {"0000001000010011111100001111111010011001000001100010100010100100",0x00003C82,0xFFFFE5C6,0x0000058E,0x00001F3F,0xFFFFF5AD,0x00000361,0x00001F3F,0xFFFFF5AD,0x00000361}, - {"0000001000010011111100001111110101000010110111000100000010000100",0x0000319B,0xFFFFEA15,0x0000051B,0x00001CC9,0xFFFFF62E,0x00000358,0x00001CC9,0xFFFFF62E,0x00000358}, - {"0000001000010011111010101001010011011110000001100011100011100100",0x000032B6,0xFFFFEB2B,0x000004D6,0x000018E0,0xFFFFF966,0x000002DE,0x000018E0,0xFFFFF966,0x000002DE}, - {"0000001000010011111010101001010011011110000000100011100110000100",0x0000300A,0xFFFFEBA6,0x000004D1,0x00001CFD,0xFFFFF5F6,0x0000036D,0x00001CFD,0xFFFFF5F6,0x0000036D}, - {"0000001000010011111100001111110101000010110110000010100110000100",0x000026A9,0xFFFFF15D,0x00000400,0x00001561,0xFFFFFB1F,0x000002A0,0x00001561,0xFFFFFB1F,0x000002A0}, - {"0000001000010011111100001111111010011001000011100101000100100100",0x00003123,0xFFFFEAD2,0x000004FA,0x000018CB,0xFFFFF8F5,0x000002EC,0x000018CB,0xFFFFF8F5,0x000002EC}, - {"0000001000010011111100001111111010011001000110000100000011000100",0x00003577,0xFFFFE935,0x00000533,0x000016CD,0xFFFFFB44,0x00000289,0x000016CD,0xFFFFFB44,0x00000289}, - {"0000001000010011111100001111111010011001001010000010000110000100",0x00002875,0xFFFFF170,0x000003F3,0x00001567,0xFFFFFBD5,0x00000289,0x00001567,0xFFFFFBD5,0x00000289}, - {"0000001000010011111100001111111010011001000010000100000010000100",0x00003AE2,0xFFFFE538,0x000005C1,0x00001CB4,0xFFFFF6A3,0x0000033C,0x00001CB4,0xFFFFF6A3,0x0000033C}, - {"0000001000010011111100001111111010011001000011000011100011100100",0x000031DF,0xFFFFEC2A,0x000004A3,0x00001EF0,0xFFFFF626,0x00000352,0x00001EF0,0xFFFFF626,0x00000352}, - {"0000001000010011111100001111110101000010110100100101000101000100",0x00004A6A,0xFFFFDB15,0x00000758,0x000027F3,0xFFFFEEEE,0x00000479,0x000027F3,0xFFFFEEEE,0x00000479}, - {"0000001000010011111010101001010011011110000001100011100100000100",0x00002BB9,0xFFFFEF5D,0x00000433,0x00001589,0xFFFFFB57,0x00000295,0x00001589,0xFFFFFB57,0x00000295}, - {"0000001000010011111100001111111010011001000001000010000101100100",0x000033A0,0xFFFFE98F,0x00000528,0x00001CB4,0xFFFFF706,0x0000032D,0x00001CB4,0xFFFFF706,0x0000032D}, - {"0000001000010011111100001111111010011001000101100011000001100100",0x0000248E,0xFFFFF380,0x000003AC,0x000016EA,0xFFFFFA6C,0x000002CE,0x000016EA,0xFFFFFA6C,0x000002CE}, - {"0000001000010011111100001111111010011001000000100010000110100100",0x00002FE2,0xFFFFEB2F,0x000004E9,0x00001D4E,0xFFFFF56B,0x00000380,0x00001D4E,0xFFFFF56B,0x00000380}, - {"0000001000010011111100001111111010011001000010100010100010000100",0x00003283,0xFFFFE9E7,0x0000051D,0x00000694,0xFFFFFD32,0x000003C3,0x00000694,0xFFFFFD32,0x000003C3}, - {"0000001000010011111100001111110101000010110110000101000011000100",0x00002EE4,0xFFFFEBFD,0x000004D3,0x0000151A,0xFFFFFAF6,0x000002A4,0x0000151A,0xFFFFFAF6,0x000002A4}, - {"0000001000010011111100001111110101000010110111000001100011100100",0x0000302D,0xFFFFEB7F,0x000004DA,0x00001E6D,0xFFFFF54B,0x00000380,0x00001E6D,0xFFFFF54B,0x00000380}, - {"0000001000010011111100001111110101000010110110100101000011000100",0x000033DA,0xFFFFE7FB,0x0000057F,0x00001DED,0xFFFFF50E,0x0000038D,0x00001DED,0xFFFFF50E,0x0000038D}, - {"0000001000010011111100001111111010011001001011000100000010000100",0x000030B5,0xFFFFEBB8,0x000004C4,0x00001C3F,0xFFFFF726,0x0000032A,0x00001C3F,0xFFFFF726,0x0000032A}, - {"0000001000010011111100001111111010011001000010000011000111000100",0x00003BBD,0xFFFFE55C,0x000005B8,0x000019DB,0xFFFFF8BB,0x000002EF,0x000019DB,0xFFFFF8BB,0x000002EF}, - {"0000001000010011111100001111111010011001000011100011100010000100",0x00002964,0xFFFFF051,0x0000040E,0x000025CD,0xFFFFF11B,0x0000041F,0x000025CD,0xFFFFF11B,0x0000041F}, - {"0000001000010011111100001111110101000010110111000100100010000100",0x000033F5,0xFFFFE863,0x00000560,0x00001BCE,0xFFFFF689,0x0000034B,0x00001BCE,0xFFFFF689,0x0000034B}, - {"0000001000010011111100001111111010011001000010100010100001100100",0x00003294,0xFFFFE924,0x00000548,0x00001D41,0xFFFFF580,0x0000037D,0x00001D41,0xFFFFF580,0x0000037D}, - {"0000001000010011111100001111110101000010110111000011100110100100",0x000034FB,0xFFFFE7FE,0x0000056D,0x00001CB1,0xFFFFF635,0x00000357,0x00001CB1,0xFFFFF635,0x00000357}, - {"0000001000010011111100001111111010011001000010100001000010100100",0x00002E28,0xFFFFEBB9,0x000004E0,0x00001B20,0xFFFFF6E3,0x0000033C,0x00001B20,0xFFFFF6E3,0x0000033C}, - {"0000001000010011111100001111110101000010110110100001100100000100",0x00002799,0xFFFFF0F4,0x000003FC,0x00001C9D,0xFFFFF6A1,0x00000345,0x00001C9D,0xFFFFF6A1,0x00000345}, - {"0000001000010011111100001111111010011001000001100100000100000100",0x00003AEA,0xFFFFE5DB,0x0000059D,0x00001B61,0xFFFFF7F0,0x00000301,0x00001B61,0xFFFFF7F0,0x00000301}, - {"0000001000010011111010101001010011011110000001000001100110000100",0x000031F6,0xFFFFEAB8,0x000004F3,0x00001D90,0xFFFFF622,0x00000359,0x00001D90,0xFFFFF622,0x00000359}, - {"0000001000010011111100001111111010011001000011000100000001100100",0x000031B8,0xFFFFEA61,0x0000050F,0x0000199D,0xFFFFF87C,0x000002FD,0x0000199D,0xFFFFF87C,0x000002FD}, - {"0000001000010011111100001111110101000010110100100011000101000100",0x00004514,0xFFFFDDFF,0x000006F6,0x000022CD,0xFFFFF29F,0x000003D9,0x000022CD,0xFFFFF29F,0x000003D9}, - {"0000001000010011111010101001010011011110000001000011000101100100",0x00002F30,0xFFFFECB8,0x000004A0,0x00001B07,0xFFFFF7E2,0x00000313,0x00001B07,0xFFFFF7E2,0x00000313}, - {"0000001000010011111100001111110101000010110111000011000010100100",0x0000383B,0xFFFFE702,0x00000581,0x00001A08,0xFFFFF8CA,0x000002E2,0x00001A08,0xFFFFF8CA,0x000002E2}, - {"0000001000010011111100001111111010011001000000100010000101100100",0x00002CC5,0xFFFFEDF8,0x00000465,0x00001F47,0xFFFFF4B2,0x00000393,0x00001F47,0xFFFFF4B2,0x00000393}, - {"0000001000010011111100001111111010011001000101100010000111000100",0x00002304,0xFFFFF453,0x00000384,0x0000170A,0xFFFFFA3F,0x000002CE,0x0000170A,0xFFFFFA3F,0x000002CE}, - {"0000001000010011111100001111111010011001000010100101000100100100",0x0000337E,0xFFFFE850,0x0000056E,0x00001BDD,0xFFFFF668,0x00000353,0x00001BDD,0xFFFFF668,0x00000353}, - {"0000001000010011111100001111111010011001000011100100100100100100",0x00002E2F,0xFFFFEC9B,0x000004AE,0x00001C4D,0xFFFFF6D3,0x00000338,0x00001C4D,0xFFFFF6D3,0x00000338}, - {"0000001000010011111010101001010011011110000001100001000100100100",0x00002DDD,0xFFFFEDA4,0x00000477,0x00002010,0xFFFFF4BB,0x00000390,0x00002010,0xFFFFF4BB,0x00000390}, - {"0000001000010011111100001111110101000010110110100100100011100100",0x0000290C,0xFFFFEF61,0x00000445,0x00002133,0xFFFFF324,0x000003D8,0x00002133,0xFFFFF324,0x000003D8}, - {"0000001000010011111100001111111010011001000001100010100100100100",0x0000371E,0xFFFFE8D5,0x00000524,0x00001C3A,0xFFFFF7AE,0x00000314,0x00001C3A,0xFFFFF7AE,0x00000314}, - {"0000001000010011111100001111110101000010110110000011100011100100",0x00002A58,0xFFFFF007,0x00000429,0x000018A6,0xFFFFF98F,0x000002E1,0x000018A6,0xFFFFF98F,0x000002E1}, - {"0000001000010011111100001111111010011001000000100011000010000100",0x00002FED,0xFFFFEC48,0x000004AA,0x00001E9D,0xFFFFF584,0x00000370,0x00001E9D,0xFFFFF584,0x00000370}, - {"0000001000010011111100001111111010011001000110000001100010000100",0x00002829,0xFFFFF15F,0x000003F7,0x0000157E,0xFFFFFBD4,0x00000282,0x0000157E,0xFFFFFBD4,0x00000282}, - {"0000001000010011111100001111111010011001000100000001100100100100",0x000030CF,0xFFFFEB8D,0x000004CE,0x00001A4C,0xFFFFF868,0x000002F7,0x00001A4C,0xFFFFF868,0x000002F7}, - {"0000001000010011111100001111110101000010110110100010000010000100",0x00002C8F,0xFFFFEDD2,0x0000047D,0x00001CCE,0xFFFFF6A1,0x00000343,0x00001CCE,0xFFFFF6A1,0x00000343}, - {"0000001000010011111100001111111010011001000110000010000101100100",0x00002A84,0xFFFFEFBA,0x0000043E,0x000015EF,0xFFFFFB4B,0x0000029E,0x000015EF,0xFFFFFB4B,0x0000029E}, - {"0000001000010011111100001111111010011001000011000010100010100100",0x000034CA,0xFFFFEA08,0x000004FF,0x00001C19,0xFFFFF7ED,0x00000309,0x00001C19,0xFFFFF7ED,0x00000309}, - {"0000001000010011111100001111111010011001000101100011100110100100",0x00002187,0xFFFFF4B0,0x0000037E,0x0000154A,0xFFFFFB0C,0x000002AE,0x0000154A,0xFFFFFB0C,0x000002AE}, - {"0000001000010011111100001111110101000010110110100011100001000100",0x00002F4F,0xFFFFEB3C,0x000004F8,0x0000181F,0xFFFFF92D,0x000002DF,0x0000181F,0xFFFFF92D,0x000002DF}, - {"0000001000010011111100001111111010011001000001000001000011100100",0x0000290C,0xFFFFF0B1,0x000003FC,0x00001DB0,0xFFFFF636,0x00000355,0x00001DB0,0xFFFFF636,0x00000355}, - {"0000001000010011111100001111111010011001000010100001000001100100",0x000034C1,0xFFFFE888,0x0000055A,0x000019BF,0xFFFFF881,0x000002FB,0x000019BF,0xFFFFF881,0x000002FB}, - {"0000001000010011111100001111110101000010110111000001100011000100",0x00003139,0xFFFFEA98,0x00000504,0x000019F2,0xFFFFF820,0x0000030B,0x000019F2,0xFFFFF820,0x0000030B}, - {"0000001000010011111100001111110101000010110110000011000101000100",0x00002CAC,0xFFFFEEB2,0x00000458,0x0000152C,0xFFFFFBEF,0x0000027B,0x0000152C,0xFFFFFBEF,0x0000027B}, - {"0000001000010011111100001111111010011001001011000011100011100100",0x00003577,0xFFFFE99C,0x0000050D,0x00001E64,0xFFFFF679,0x0000033F,0x00001E64,0xFFFFF679,0x0000033F}, - {"0000001000010011111100001111110101000010110110100100000100000100",0x0000263A,0xFFFFF1E4,0x000003D4,0x00001F68,0xFFFFF4ED,0x00000386,0x00001F68,0xFFFFF4ED,0x00000386}, - {"0000001000010011111100001111110101000010110110000001100110000100",0x00002CE9,0xFFFFED63,0x00000497,0x00001810,0xFFFFF94D,0x000002E3,0x00001810,0xFFFFF94D,0x000002E3}, - {"0000001000010011111010101001010011011110000001000100000100000100",0x0000318A,0xFFFFEAC8,0x000004F5,0x0000195C,0xFFFFF896,0x000002FB,0x0000195C,0xFFFFF896,0x000002FB}, - {"0000001000010011111100001111110101000010110110000011100100000100",0x00002C41,0xFFFFEEC6,0x0000045D,0x000017DD,0xFFFFFA16,0x000002CB,0x000017DD,0xFFFFFA16,0x000002CB}, - {"0000001000010011111100001111111010011001000000100011000110100100",0x00002DD4,0xFFFFEC98,0x000004AD,0x00001BD7,0xFFFFF69F,0x00000347,0x00001BD7,0xFFFFF69F,0x00000347}, - {"0000001000010011111100001111110101000010110110100011100101000100",0x00003351,0xFFFFE9B2,0x0000051A,0x00001CA1,0xFFFFF6A4,0x00000341,0x00001CA1,0xFFFFF6A4,0x00000341}, - {"0000001000010011111100001111111010011001000000100001000100000100",0x0000322D,0xFFFFE9BE,0x00000527,0x00001CF9,0xFFFFF5EB,0x00000366,0x00001CF9,0xFFFFF5EB,0x00000366}, - {"0000001000010011111100001111111010011001000011000010100011000100",0x00003678,0xFFFFE9A8,0x00000503,0x00001AD4,0xFFFFF8F6,0x000002E3,0x00001AD4,0xFFFFF8F6,0x000002E3}, - {"0000001000010011111100001111111010011001000101100001100100100100",0x0000260E,0xFFFFF2C1,0x000003CA,0x00001139,0xFFFFFE48,0x00000236,0x00001139,0xFFFFFE48,0x00000236}, - {"0000001000010011111100001111111010011001000010100010000101100100",0x000033D3,0xFFFFE872,0x00000565,0x00001B72,0xFFFFF713,0x00000332,0x00001B72,0xFFFFF713,0x00000332}, - {"0000001000010011111100001111111010011001001100100011100001000100",0x0000309B,0xFFFFEB42,0x000004E4,0x00001918,0xFFFFF8C8,0x000002F2,0x00001918,0xFFFFF8C8,0x000002F2}, - {"0000001000010011111100001111111010011001000110000010100001100100",0x000028B8,0xFFFFF105,0x00000402,0x000018BB,0xFFFFF9BC,0x000002D3,0x000018BB,0xFFFFF9BC,0x000002D3}, - {"0000001000010011111100001111111010011001000010100001100010000100",0x00003123,0xFFFFE9D1,0x00000534,0x00001B19,0xFFFFF6FE,0x0000033C,0x00001B19,0xFFFFF6FE,0x0000033C}, - {"0000001000010011111100001111111010011001000000100010000101000100",0x00003216,0xFFFFEA8E,0x000004F6,0x00001F72,0xFFFFF4CE,0x0000038B,0x00001F72,0xFFFFF4CE,0x0000038B}, - {"0000001000010011111100001111111010011001000101100010100101100100",0x00002564,0xFFFFF32D,0x000003B6,0x00001685,0xFFFFFADB,0x000002BB,0x00001685,0xFFFFFADB,0x000002BB}, - {"0000001000010011111100001111110101000010110110100010100100100100",0x00002E60,0xFFFFED13,0x00000497,0x00001CA5,0xFFFFF6B9,0x00000346,0x00001CA5,0xFFFFF6B9,0x00000346}, - {"0000001000010011111100001111111010011001000011100011100110100100",0x0000336D,0xFFFFE934,0x0000053B,0x00001B3E,0xFFFFF763,0x00000327,0x00001B3E,0xFFFFF763,0x00000327}, - {"0000001000010011111100001111111010011001000100000001000010000100",0x0000274A,0xFFFFF119,0x000003FA,0x00001D75,0xFFFFF5CD,0x0000036F,0x00001D75,0xFFFFF5CD,0x0000036F}, - {"0000001000010011111100001111110101000010110110100010000101100100",0x0000366B,0xFFFFE70A,0x0000059A,0x00001ED8,0xFFFFF501,0x00000389,0x00001ED8,0xFFFFF501,0x00000389}, - {"0000001000010011111100001111111010011001001000100011100101100100",0x00003164,0xFFFFEAB4,0x000004FA,0x00001C52,0xFFFFF6E0,0x00000336,0x00001C52,0xFFFFF6E0,0x00000336}, - {"0000001000010011111100001111110101000010110100100011000001100100",0x00004224,0xFFFFDF7F,0x000006C1,0x00002A52,0xFFFFED5E,0x000004BB,0x00002A52,0xFFFFED5E,0x000004BB}, - {"0000001000010011111100001111111010011001000100000010100001100100",0x000030E3,0xFFFFEB07,0x000004ED,0x00001FD3,0xFFFFF46D,0x000003A1,0x00001FD3,0xFFFFF46D,0x000003A1}, - {"0000001000010011111100001111110101000010110110000010100010000100",0x00002AEB,0xFFFFEF1B,0x00000454,0x00001829,0xFFFFF995,0x000002DD,0x00001829,0xFFFFF995,0x000002DD}, - {"0000001000010011111100001111110101000010110111000101000011100100",0x0000346B,0xFFFFE7A2,0x0000058B,0x000020C5,0xFFFFF2E8,0x000003EC,0x000020C5,0xFFFFF2E8,0x000003EC}, - {"0000001000010011111100001111110101000010110111000100000101100100",0x000039CF,0xFFFFE5D7,0x000005A9,0x00001D66,0xFFFFF5D6,0x00000366,0x00001D66,0xFFFFF5D6,0x00000366}, - {"0000001000010011111100001111111010011001000001000001100011100100",0x000034AC,0xFFFFE9AE,0x00000515,0x00001A28,0xFFFFF904,0x000002DC,0x00001A28,0xFFFFF904,0x000002DC}, - {"0000001000010011111100001111110101000010110111000010000010000100",0x00002D68,0xFFFFED21,0x00000498,0x00001C6F,0xFFFFF686,0x0000034C,0x00001C6F,0xFFFFF686,0x0000034C}, - {"0000001000010011111100001111111010011001000010000010000011000100",0x0000328B,0xFFFFEBA1,0x000004B4,0x00001DA3,0xFFFFF683,0x00000349,0x00001DA3,0xFFFFF683,0x00000349}, - {"0000001000010011111100001111111010011001000110000010100011000100",0x000027DC,0xFFFFF295,0x000003BF,0x000019C1,0xFFFFF98E,0x000002E8,0x000019C1,0xFFFFF98E,0x000002E8}, - {"0000001000010011111100001111111010011001000110000100000010000100",0x00002756,0xFFFFF1D7,0x000003DF,0x000015D9,0xFFFFFB51,0x00000298,0x000015D9,0xFFFFFB51,0x00000298}, - {"0000001000010011111100001111111010011001000010000011100010000100",0x00003526,0xFFFFE907,0x00000526,0x000017AB,0xFFFFFA12,0x000002AB,0x000017AB,0xFFFFFA12,0x000002AB}, - {"0000001000010011111100001111110101000010110110100001100011100100",0x0000351B,0xFFFFE8B7,0x00000540,0x00001A86,0xFFFFF821,0x00000303,0x00001A86,0xFFFFF821,0x00000303}, - {"0000001000010011111100001111111010011001000101100100000101000100",0x000024B2,0xFFFFF34E,0x000003B1,0x000018E2,0xFFFFF926,0x000002FC,0x000018E2,0xFFFFF926,0x000002FC}, - {"0000001000010011111100001111110101000010110110000010100010100100",0x00002F36,0xFFFFED5D,0x00000486,0x0000157A,0xFFFFFB85,0x00000293,0x0000157A,0xFFFFFB85,0x00000293}, - {"0000001000010011111100001111110101000010110111000101000011000100",0x00003A6E,0xFFFFE456,0x000005FD,0x00001F68,0xFFFFF3D1,0x000003C3,0x00001F68,0xFFFFF3D1,0x000003C3}, - {"0000001000010011111100001111111010011001000010100011000110100100",0x00002BC3,0xFFFFED2D,0x000004A7,0x00001C3F,0xFFFFF609,0x00000364,0x00001C3F,0xFFFFF609,0x00000364}, - {"0000001000010011111100001111111010011001000011100010000010000100",0x000032E1,0xFFFFEA83,0x000004F6,0x00001B37,0xFFFFF842,0x000002F5,0x00001B37,0xFFFFF842,0x000002F5}, - {"0000001000010011111100001111110101000010110110000011000110000100",0x000028E3,0xFFFFF07F,0x00000412,0x00001676,0xFFFFFA68,0x000002BE,0x00001676,0xFFFFFA68,0x000002BE}, - {"0000001000010011111100001111110101000010110100100001000100000100",0x0000444C,0xFFFFDDAD,0x00000712,0x00002634,0xFFFFEF89,0x0000046C,0x00002634,0xFFFFEF89,0x0000046C}, - {"0000001000010011111100001111111010011001000001000001100011000100",0x00003121,0xFFFFEBBB,0x000004C6,0x00001C98,0xFFFFF72B,0x0000032D,0x00001C98,0xFFFFF72B,0x0000032D}, - {"0000001000010011111100001111110101000010110110000100000010100100",0x00002C31,0xFFFFEDC4,0x00000490,0x0000162D,0xFFFFFA8E,0x000002B4,0x0000162D,0xFFFFFA8E,0x000002B4}, - {"0000001000010011111100001111110101000010110110100001100011000100",0x00002749,0xFFFFF112,0x000003FC,0x00001C85,0xFFFFF6B8,0x00000342,0x00001C85,0xFFFFF6B8,0x00000342}, - {"0000001000010011111100001111111010011001000001000100000100000100",0x00003159,0xFFFFEB99,0x000004C2,0x00001BD0,0xFFFFF7CA,0x00000307,0x00001BD0,0xFFFFF7CA,0x00000307}, - {"0000001000010011111100001111111010011001000101100100000101100100",0x00002610,0xFFFFF1FD,0x000003EC,0x000016BE,0xFFFFFA53,0x000002CB,0x000016BE,0xFFFFFA53,0x000002CB}, - {"0000001000010011111100001111111010011001000000100011000110000100",0x000037B5,0xFFFFE63D,0x000005B5,0x00002285,0xFFFFF25D,0x000003F7,0x00002285,0xFFFFF25D,0x000003F7}, - {"0000001000010011111100001111111010011001000010100010100010100100",0x00002FEE,0xFFFFEB47,0x000004EF,0x00001CBE,0xFFFFF64E,0x00000358,0x00001CBE,0xFFFFF64E,0x00000358}, - {"0000001000010011111100001111111010011001000100000101000100000100",0x00002E90,0xFFFFEC48,0x000004C0,0x00001A47,0xFFFFF7D1,0x0000031A,0x00001A47,0xFFFFF7D1,0x0000031A}, - {"0000001000010011111100001111110101000010110110100100000010000100",0x000034AB,0xFFFFE84A,0x00000559,0x00001A72,0xFFFFF79A,0x0000031C,0x00001A72,0xFFFFF79A,0x0000031C}, - {"0000001000010011111100001111111010011001000110000011100010000100",0x00002F7B,0xFFFFECFC,0x0000049C,0x00001814,0xFFFFFA22,0x000002C2,0x00001814,0xFFFFFA22,0x000002C2}, - {"0000001000010011111100001111111010011001000000100001100101100100",0x00003618,0xFFFFE709,0x00000596,0x00001EBF,0xFFFFF482,0x000003A5,0x00001EBF,0xFFFFF482,0x000003A5}, - {"0000001000010011111010101001010011011110000000100100100100000100",0x0000341B,0xFFFFE8B2,0x0000054F,0x00001D26,0xFFFFF578,0x00000388,0x00001D26,0xFFFFF578,0x00000388}, - {"0000001000010011111100001111111010011001000100000010000101000100",0x000030F6,0xFFFFEB89,0x000004CD,0x000019C0,0xFFFFF8CC,0x000002E6,0x000019C0,0xFFFFF8CC,0x000002E6}, - {"0000001000010011111100001111111010011001001010000100000110100100",0x00002B76,0xFFFFEF6C,0x00000444,0x00001563,0xFFFFFBBE,0x0000028D,0x00001563,0xFFFFFBBE,0x0000028D}, - {"0000001000010011111100001111110101000010110110000001100001100100",0x00002BA2,0xFFFFEE31,0x0000047F,0x00001A3D,0xFFFFF7F3,0x00000320,0x00001A3D,0xFFFFF7F3,0x00000320}, - {"0000001000010011111100001111111010011001001011000100100011100100",0x00003545,0xFFFFE87A,0x0000054A,0x00001B5A,0xFFFFF7B0,0x0000030C,0x00001B5A,0xFFFFF7B0,0x0000030C}, - {"0000001000010011111010101001010011011110000001000010100101000100",0x00003879,0xFFFFE73F,0x00000578,0x00001649,0xFFFFFB57,0x00000283,0x00001649,0xFFFFFB57,0x00000283}, - {"0000001000010011111100001111110101000010110110000100000011000100",0x00002772,0xFFFFF0F1,0x00000410,0x0000142F,0xFFFFFBCF,0x00000287,0x0000142F,0xFFFFFBCF,0x00000287}, - {"0000001000010011111100001111110101000010110110100011000110000100",0x00003228,0xFFFFE98E,0x00000535,0x00001F48,0xFFFFF495,0x00000399,0x00001F48,0xFFFFF495,0x00000399}, - {"0000001000010011111100001111111010011001000011100100000011100100",0x00002887,0xFFFFF119,0x000003E8,0x000021AA,0xFFFFF3F5,0x000003A5,0x000021AA,0xFFFFF3F5,0x000003A5}, - {"0000001000010011111100001111110101000010110110100010100010100100",0x0000301F,0xFFFFEBB2,0x000004D2,0x00001C02,0xFFFFF736,0x0000032B,0x00001C02,0xFFFFF736,0x0000032B}, - {"0000001000010011111100001111111010011001000110000010000010100100",0x00002E13,0xFFFFEE3F,0x00000468,0x000016AC,0xFFFFFB32,0x0000029E,0x000016AC,0xFFFFFB32,0x0000029E}, - {"0000001000010011111100001111111010011001000001000100100100100100",0x00003478,0xFFFFE8F9,0x00000538,0x00001DAB,0xFFFFF645,0x00000345,0x00001DAB,0xFFFFF645,0x00000345}, - {"0000001000010011111100001111111010011001000001100000100011000100",0x000030C6,0xFFFFEB6C,0x000004D4,0x0000184A,0xFFFFF934,0x000002E1,0x0000184A,0xFFFFF934,0x000002E1}, - {"0000001000010011111100001111111010011001000010100010000001000100",0x00002F1B,0xFFFFEBD3,0x000004D3,0x000019E7,0xFFFFF813,0x0000030D,0x000019E7,0xFFFFF813,0x0000030D}, - {"0000001000010011111100001111111010011001000000100011100100000100",0x00003214,0xFFFFEAE9,0x000004E0,0x0000178F,0xFFFFFA1C,0x000002B1,0x0000178F,0xFFFFFA1C,0x000002B1}, - {"0000001000010011111100001111110101000010110111000011000101000100",0x0000399C,0xFFFFE738,0x0000055E,0x00001EA1,0xFFFFF5E7,0x0000035A,0x00001EA1,0xFFFFF5E7,0x0000035A}, - {"0000001000010011111100001111111010011001000001100101000011000100",0x00003A01,0xFFFFE5B2,0x000005B6,0x00001D95,0xFFFFF5D2,0x0000036A,0x00001D95,0xFFFFF5D2,0x0000036A}, - {"0000001000010011111100001111111010011001000001000011100010000100",0x0000310D,0xFFFFEB78,0x000004D0,0x00001C06,0xFFFFF76E,0x0000031A,0x00001C06,0xFFFFF76E,0x0000031A}, - {"0000001000010011111100001111111010011001000001100011100001100100",0x00003CD1,0xFFFFE42F,0x000005EB,0x00001933,0xFFFFF91F,0x000002D4,0x00001933,0xFFFFF91F,0x000002D4}, - {"0000001000010011111100001111110101000010110110100011000101100100",0x00003119,0xFFFFEB1B,0x000004E1,0x00001FC7,0xFFFFF46A,0x000003A2,0x00001FC7,0xFFFFF46A,0x000003A2}, - {"0000001000010011111010101001010011011110000001100100100010100100",0x0000390D,0xFFFFE566,0x000005D8,0x00001EC6,0xFFFFF4DC,0x00000391,0x00001EC6,0xFFFFF4DC,0x00000391}, - {"0000001000010011111100001111110101000010110110100001000011000100",0x00003446,0xFFFFE858,0x00000561,0x00001FDB,0xFFFFF3FF,0x000003B9,0x00001FDB,0xFFFFF3FF,0x000003B9}, - {"0000001000010011111100001111111010011001000001000100100100000100",0x000032BA,0xFFFFEA07,0x00000511,0x00001B25,0xFFFFF7C9,0x0000030D,0x00001B25,0xFFFFF7C9,0x0000030D}, - {"0000001000010011111100001111111010011001000011100001100001100100",0x00002CCF,0xFFFFEDE5,0x00000478,0x00001BC8,0xFFFFF761,0x00000326,0x00001BC8,0xFFFFF761,0x00000326}, - {"0000001000010011111100001111111010011001000001100010100110000100",0x0000400E,0xFFFFE1CB,0x00000652,0x00001AF8,0xFFFFF7B9,0x00000312,0x00001AF8,0xFFFFF7B9,0x00000312}, - {"0000001000010011111100001111111010011001000001000000100011100100",0x00002F24,0xFFFFEC2A,0x000004C7,0x00001B94,0xFFFFF748,0x00000333,0x00001B94,0xFFFFF748,0x00000333}, - {"0000001000010011111100001111110101000010110100100001100100100100",0x00003FDA,0xFFFFE1C1,0x0000064B,0x00002427,0xFFFFF180,0x0000040C,0x00002427,0xFFFFF180,0x0000040C}, - {"0000001000010011111100001111111010011001000010100001100011000100",0x00002F6B,0xFFFFEBA7,0x000004DD,0x00001C25,0xFFFFF6C1,0x00000344,0x00001C25,0xFFFFF6C1,0x00000344}, - {"0000001000010011111100001111111010011001000110000010000100000100",0x00002A53,0xFFFFF0EE,0x00000402,0x000017C6,0xFFFFFAA0,0x000002BF,0x000017C6,0xFFFFFAA0,0x000002BF}, - {"0000001000010011111100001111111010011001000100000101000101000100",0x000031F4,0xFFFFEA34,0x00000517,0x000016FF,0xFFFFFA4E,0x000002AC,0x000016FF,0xFFFFFA4E,0x000002AC}, - {"0000001000010011111100001111111010011001001100100010000101000100",0x00002E24,0xFFFFED46,0x00000489,0x00001712,0xFFFFFA5D,0x000002AC,0x00001712,0xFFFFFA5D,0x000002AC}, - {"0000001000010011111100001111111010011001000110000010100000100100",0x000028CD,0xFFFFF0E3,0x0000040E,0x00001606,0xFFFFFB37,0x000002A4,0x00001606,0xFFFFFB37,0x000002A4}, - {"0000001000010011111100001111111010011001000000100010000011000100",0x00003184,0xFFFFEB88,0x000004C3,0x000018DA,0xFFFFF939,0x000002DB,0x000018DA,0xFFFFF939,0x000002DB}, - {"0000001000010011111100001111111010011001000101100010000100100100",0x0000239B,0xFFFFF470,0x00000386,0x00001714,0xFFFFFA9F,0x000002C8,0x00001714,0xFFFFFA9F,0x000002C8}, - {"0000001000010011111100001111110101000010110111000011100011100100",0x00003641,0xFFFFE92B,0x00000515,0x00001BE2,0xFFFFF795,0x0000031B,0x00001BE2,0xFFFFF795,0x0000031B}, - {"0000001000010011111100001111111010011001001011000001000101000100",0x00003278,0xFFFFEA17,0x00000510,0x00001B71,0xFFFFF778,0x0000031D,0x00001B71,0xFFFFF778,0x0000031D}, - {"0000001000010011111100001111111010011001000001100010100001000100",0x000035B9,0xFFFFE8DA,0x0000052D,0x00001A6A,0xFFFFF83B,0x000002FF,0x00001A6A,0xFFFFF83B,0x000002FF}, - {"0000001000010011111100001111111010011001000011100001100011000100",0x00002E5E,0xFFFFED32,0x0000048B,0x00001E7D,0xFFFFF60E,0x0000034E,0x00001E7D,0xFFFFF60E,0x0000034E}, - {"0000001000010011111100001111111010011001000100000001100110100100",0x00003178,0xFFFFEA52,0x00000513,0x00001AD0,0xFFFFF793,0x0000031F,0x00001AD0,0xFFFFF793,0x0000031F}, - {"0000001000010011111100001111110101000010110101000100000100000100",0x00003A2C,0xFFFFE346,0x00000641,0x000023D0,0xFFFFF0CE,0x00000433,0x000023D0,0xFFFFF0CE,0x00000433}, - {"0000001000010011111100001111110101000010110110000001100011000100",0x000028FD,0xFFFFF02A,0x0000042B,0x0000152B,0xFFFFFB90,0x00000289,0x0000152B,0xFFFFFB90,0x00000289}, - {"0000001000010011111100001111111010011001000011100011000010000100",0x000030DE,0xFFFFEBDF,0x000004BE,0x00001CDC,0xFFFFF747,0x0000031C,0x00001CDC,0xFFFFF747,0x0000031C}, - {"0000001000010011111100001111111010011001000000100001100101000100",0x000036CB,0xFFFFE6EE,0x00000596,0x00002096,0xFFFFF3C2,0x000003BB,0x00002096,0xFFFFF3C2,0x000003BB}, - {"0000001000010011111100001111111010011001000011000100100011000100",0x00003172,0xFFFFEAC1,0x000004F4,0x00001C87,0xFFFFF6CD,0x00000337,0x00001C87,0xFFFFF6CD,0x00000337}, - {"0000001000010011111100001111110101000010110100100100100001100100",0x00004A18,0xFFFFDB34,0x00000758,0x0000213C,0xFFFFF3A2,0x000003AC,0x0000213C,0xFFFFF3A2,0x000003AC}, - {"0000001000010011111100001111111010011001000000100010000100000100",0x000031F3,0xFFFFEB73,0x000004C6,0x00001B23,0xFFFFF7CB,0x0000031A,0x00001B23,0xFFFFF7CB,0x0000031A}, - {"0000001000010011111100001111111010011001000010100010100100100100",0x000031C0,0xFFFFEABA,0x000004F7,0x00001A5A,0xFFFFF845,0x000002FF,0x00001A5A,0xFFFFF845,0x000002FF}, - {"0000001000010011111100001111111010011001000100000100100101000100",0x00003B77,0xFFFFE3B3,0x00000623,0x00001BCA,0xFFFFF6F8,0x00000333,0x00001BCA,0xFFFFF6F8,0x00000333}, - {"0000001000010011111100001111111010011001000010100011100101000100",0x000035AF,0xFFFFE76D,0x00000588,0x00001C16,0xFFFFF6AB,0x00000341,0x00001C16,0xFFFFF6AB,0x00000341}, - {"0000001000010011111010101001010011011110000001000011100011000100",0x000032AD,0xFFFFEA8E,0x000004F8,0x00001A3A,0xFFFFF832,0x0000030E,0x00001A3A,0xFFFFF832,0x0000030E}, - {"0000001000010011111100001111111010011001000100000100100010000100",0x00002E92,0xFFFFEBD2,0x000004DA,0x00001E04,0xFFFFF51E,0x0000038A,0x00001E04,0xFFFFF51E,0x0000038A}, - {"0000001000010011111100001111110101000010110101000100000010100100",0x00003E57,0xFFFFE0F7,0x0000068F,0x000021F1,0xFFFFF1C6,0x00000411,0x000021F1,0xFFFFF1C6,0x00000411}, - {"0000001000010011111100001111111010011001000010000010000110100100",0x00003598,0xFFFFE8BB,0x00000535,0x00001B62,0xFFFFF764,0x00000326,0x00001B62,0xFFFFF764,0x00000326}, - {"0000001000010011111100001111111010011001000010100011100010000100",0x00002B15,0xFFFFEDEC,0x00000487,0x00001E8B,0xFFFFF4AB,0x0000039F,0x00001E8B,0xFFFFF4AB,0x0000039F}, - {"0000001000010011111010101001010011011110000001100000100100000100",0x0000267E,0xFFFFF1A7,0x000003E1,0x000021C1,0xFFFFF2E9,0x000003EA,0x000021C1,0xFFFFF2E9,0x000003EA}, - {"0000001000010011111010101001010011011110000000100011100110100100",0x00002ED7,0xFFFFEC88,0x000004A6,0x00001DEC,0xFFFFF57C,0x00000378,0x00001DEC,0xFFFFF57C,0x00000378}, - {"0000001000010011111010101001010011011110000001000100000110100100",0x00003365,0xFFFFE946,0x00000536,0x000019E9,0xFFFFF7E0,0x0000031D,0x000019E9,0xFFFFF7E0,0x0000031D}, - {"0000001000010011111100001111111010011001000110000001100011100100",0x000029A4,0xFFFFF0FD,0x000003FE,0x0000163F,0xFFFFFB68,0x00000299,0x0000163F,0xFFFFFB68,0x00000299}, - {"0000001000010011111010101001010011011110000000100001100100000100",0x0000348D,0xFFFFE9F7,0x00000509,0x000017A0,0xFFFFFA59,0x000002B6,0x000017A0,0xFFFFFA59,0x000002B6}, - {"0000001000010011111100001111111010011001000001100001000011000100",0x00003144,0xFFFFEB23,0x000004D9,0x00001C9B,0xFFFFF664,0x00000351,0x00001C9B,0xFFFFF664,0x00000351}, - {"0000001000010011111010101001010011011110000001100010000011100100",0x00002E95,0xFFFFEE1A,0x00000463,0x00001707,0xFFFFFAB7,0x000002B3,0x00001707,0xFFFFFAB7,0x000002B3}, - {"0000001000010011111100001111110101000010110101000001100001100100",0x0000489C,0xFFFFDA43,0x000007AC,0x00002866,0xFFFFED6B,0x000004D0,0x00002866,0xFFFFED6B,0x000004D0}, - {"0000001000010011111100001111111010011001000101100001100001000100",0x00002895,0xFFFFF10A,0x0000040A,0x000013E9,0xFFFFFC9F,0x0000026E,0x000013E9,0xFFFFFC9F,0x0000026E}, - {"0000001000010011111100001111111010011001000001100001100101100100",0x000033A0,0xFFFFE9B1,0x00000510,0x00001D96,0xFFFFF5AE,0x0000036F,0x00001D96,0xFFFFF5AE,0x0000036F}, - {"0000001000010011111100001111111010011001000010000011100110000100",0x0000327C,0xFFFFEAEA,0x000004DD,0x00001D45,0xFFFFF649,0x00000356,0x00001D45,0xFFFFF649,0x00000356}, - {"0000001000010011111010101001010011011110000000100100100010100100",0x000031DF,0xFFFFE9AB,0x0000052F,0x000019C8,0xFFFFF7B7,0x00000321,0x000019C8,0xFFFFF7B7,0x00000321}, - {"0000001000010011111100001111111010011001000101100100000010100100",0x00002BCC,0xFFFFEEF4,0x0000045C,0x000015CD,0xFFFFFB58,0x0000029E,0x000015CD,0xFFFFFB58,0x0000029E}, - {"0000001000010011111100001111111010011001000001100011100011100100",0x00003534,0xFFFFEA10,0x000004EB,0x00001BB6,0xFFFFF7B9,0x00000314,0x00001BB6,0xFFFFF7B9,0x00000314}, - {"0000001000010011111100001111111010011001000001000001100110000100",0x00002F4F,0xFFFFEC35,0x000004B9,0x0000205D,0xFFFFF47F,0x00000392,0x0000205D,0xFFFFF47F,0x00000392}, - {"0000001000010011111100001111111010011001000011000010000010100100",0x00003295,0xFFFFEB1C,0x000004D6,0x000019C1,0xFFFFF931,0x000002D5,0x000019C1,0xFFFFF931,0x000002D5}, - {"0000001000010011111100001111111010011001000000100100000101000100",0x00003557,0xFFFFE7F7,0x00000568,0x00002342,0xFFFFF1F9,0x00000405,0x00002342,0xFFFFF1F9,0x00000405}, - {"0000001000010011111100001111111010011001000001000101000011000100",0x00003487,0xFFFFE872,0x0000055D,0x000019D7,0xFFFFF823,0x0000030C,0x000019D7,0xFFFFF823,0x0000030C}, - {"0000001000010011111100001111111010011001001011000011100101000100",0x0000378F,0xFFFFE7A6,0x00000566,0x00001875,0xFFFFFA04,0x000002AF,0x00001875,0xFFFFFA04,0x000002AF}, - {"0000001000010011111010101001010011011110000000100011000011100100",0x00002A67,0xFFFFF157,0x000003DD,0x000017BD,0xFFFFFA53,0x000002D1,0x000017BD,0xFFFFFA53,0x000002D1}, - {"0000001000010011111100001111110101000010110100100010000011100100",0x000030B5,0xFFFFEB32,0x000004D9,0x00002129,0xFFFFF38A,0x000003BB,0x00002129,0xFFFFF38A,0x000003BB}, - {"0000001000010011111100001111111010011001000001100001000010100100",0x00003786,0xFFFFE703,0x00000584,0x00001D63,0xFFFFF5DC,0x00000367,0x00001D63,0xFFFFF5DC,0x00000367}, - {"0000001000010011111100001111110101000010110110100010000011000100",0x0000346A,0xFFFFE93E,0x0000052C,0x00001B27,0xFFFFF79D,0x0000031F,0x00001B27,0xFFFFF79D,0x0000031F}, - {"0000001000010011111100001111111010011001000011100011000000100100",0x0000294E,0xFFFFF0A5,0x00000409,0x00001928,0xFFFFF93B,0x000002E6,0x00001928,0xFFFFF93B,0x000002E6}, - {"0000001000010011111100001111110101000010110101000001000011000100",0x00003E09,0xFFFFE0FF,0x00000694,0x000025A0,0xFFFFEF0F,0x0000048F,0x000025A0,0xFFFFEF0F,0x0000048F}, - {"0000001000010011111100001111111010011001000010100010100101100100",0x00003197,0xFFFFEA06,0x00000520,0x00001B42,0xFFFFF73B,0x0000032A,0x00001B42,0xFFFFF73B,0x0000032A}, - {"0000001000010011111100001111111010011001000101100001100001100100",0x000022CB,0xFFFFF3FC,0x000003A3,0x00001449,0xFFFFFBD0,0x00000297,0x00001449,0xFFFFFBD0,0x00000297}, - {"0000001000010011111100001111110101000010110110000010100101000100",0x00002A79,0xFFFFEFD2,0x00000433,0x00001585,0xFFFFFB92,0x0000028E,0x00001585,0xFFFFFB92,0x0000028E}, - {"0000001000010011111100001111111010011001000011000100000110000100",0x00003249,0xFFFFEA92,0x000004F4,0x000019CB,0xFFFFF8CF,0x000002E1,0x000019CB,0xFFFFF8CF,0x000002E1}, - {"0000001000010011111010101001010011011110000000100001100010100100",0x00002CEA,0xFFFFEE46,0x00000463,0x00001A5E,0xFFFFF83C,0x0000030D,0x00001A5E,0xFFFFF83C,0x0000030D}, - {"0000001000010011111100001111110101000010110111000101000101000100",0x00003AE2,0xFFFFE422,0x00000600,0x00001C65,0xFFFFF62F,0x0000034B,0x00001C65,0xFFFFF62F,0x0000034B}, - {"0000001000010011111100001111111010011001000110000001000110000100",0x000026A0,0xFFFFF1C2,0x000003F8,0x000010E5,0xFFFFFE56,0x0000022A,0x000010E5,0xFFFFFE56,0x0000022A}, - {"0000001000010011111100001111111010011001001010000010100110100100",0x00002A7B,0xFFFFF063,0x00000417,0x000016FC,0xFFFFFAD7,0x000002B1,0x000016FC,0xFFFFFAD7,0x000002B1}, - {"0000001000010011111100001111111010011001001100100001000011000100",0x00003092,0xFFFFEAB9,0x00000507,0x00001AE3,0xFFFFF783,0x00000323,0x00001AE3,0xFFFFF783,0x00000323}, - {"0000001000010011111100001111111010011001000001000011100011100100",0x00003265,0xFFFFEBE8,0x000004AA,0x00001D65,0xFFFFF73F,0x00000321,0x00001D65,0xFFFFF73F,0x00000321}, - {"0000001000010011111010101001010011011110000000100011000010000100",0x00002F14,0xFFFFECC2,0x000004A4,0x00001A8D,0xFFFFF7F3,0x0000031D,0x00001A8D,0xFFFFF7F3,0x0000031D}, - {"0000001000010011111100001111110101000010110111000001000011100100",0x000035FB,0xFFFFE6D3,0x000005AC,0x00001B19,0xFFFFF712,0x00000338,0x00001B19,0xFFFFF712,0x00000338}, - {"0000001000010011111100001111110101000010110110100010000100100100",0x00003519,0xFFFFE8CC,0x0000053A,0x00001A0F,0xFFFFF86E,0x000002F5,0x00001A0F,0xFFFFF86E,0x000002F5}, - {"0000001000010011111100001111111010011001001011000010000101000100",0x0000364C,0xFFFFE879,0x00000541,0x00001A42,0xFFFFF8BA,0x000002E2,0x00001A42,0xFFFFF8BA,0x000002E2}, - {"0000001000010011111010101001010011011110000000100001100011000100",0x000029BA,0xFFFFF09A,0x00000408,0x00001986,0xFFFFF8D9,0x000002FE,0x00001986,0xFFFFF8D9,0x000002FE}, - {"0000001000010011111100001111110101000010110110100011100011100100",0x00003507,0xFFFFE961,0x00000518,0x00001B79,0xFFFFF775,0x00000325,0x00001B79,0xFFFFF775,0x00000325}, - {"0000001000010011111100001111110101000010110111000011000110000100",0x00003AD5,0xFFFFE415,0x00000613,0x00001CB4,0xFFFFF66D,0x00000348,0x00001CB4,0xFFFFF66D,0x00000348}, - {"0000001000010011111100001111111010011001000101100100000011100100",0x000023D1,0xFFFFF42B,0x0000038F,0x00001546,0xFFFFFBA0,0x0000029F,0x00001546,0xFFFFFBA0,0x0000029F}, - {"0000001000010011111100001111111010011001000010100001100100100100",0x0000399E,0xFFFFE518,0x000005E7,0x00001990,0xFFFFF871,0x000002FB,0x00001990,0xFFFFF871,0x000002FB}, - {"0000001000010011111100001111110101000010110110000010100101100100",0x00002EDE,0xFFFFEC93,0x000004B8,0x0000152C,0xFFFFFBB3,0x0000027E,0x0000152C,0xFFFFFBB3,0x0000027E}, - {"0000001000010011111010101001010011011110000001000010100101100100",0x00003140,0xFFFFEBC9,0x000004BB,0x000016BE,0xFFFFFB0A,0x00000288,0x000016BE,0xFFFFFB0A,0x00000288}, - {"0000001000010011111100001111111010011001000001100100000001100100",0x000030F6,0xFFFFEB89,0x000004CD,0x0000185D,0xFFFFF95A,0x000002D9,0x0000185D,0xFFFFF95A,0x000002D9}, - {"0000001000010011111100001111111010011001000000100011100001000100",0x0000389C,0xFFFFE65A,0x000005A2,0x0000195D,0xFFFFF8C8,0x000002E8,0x0000195D,0xFFFFF8C8,0x000002E8}, - {"0000001000010011111100001111111010011001000001000010000100000100",0x0000362B,0xFFFFE9EC,0x000004F6,0x00001605,0xFFFFFC1C,0x00000263,0x00001605,0xFFFFFC1C,0x00000263}, - {"0000001000010011111100001111111010011001001010100001100101100100",0x00002946,0xFFFFF04F,0x00000426,0x000015BA,0xFFFFFB2F,0x000002A3,0x000015BA,0xFFFFFB2F,0x000002A3}, - {"0000001000010011111100001111111010011001000010000010000110000100",0x0000368E,0xFFFFE837,0x0000054A,0x000017D7,0xFFFFF9EB,0x000002BA,0x000017D7,0xFFFFF9EB,0x000002BA}, - {"0000001000010011111100001111110101000010110110100010100001000100",0x00002E74,0xFFFFEBE8,0x000004DA,0x00001DD6,0xFFFFF57E,0x00000379,0x00001DD6,0xFFFFF57E,0x00000379}, - {"0000001000010011111100001111111010011001000001000001100101000100",0x0000322D,0xFFFFEAA8,0x000004F5,0x00001B55,0xFFFFF7DD,0x0000030B,0x00001B55,0xFFFFF7DD,0x0000030B}, - {"0000001000010011111100001111111010011001000110000001100100000100",0x00002A29,0xFFFFF07B,0x00000416,0x00001671,0xFFFFFB3E,0x0000029F,0x00001671,0xFFFFFB3E,0x0000029F}, - {"0000001000010011111100001111110101000010110110100010000100000100",0x000030F6,0xFFFFEB89,0x000004CD,0x00001815,0xFFFFF9AE,0x000002C9,0x00001815,0xFFFFF9AE,0x000002C9}, - {"0000001000010011111100001111111010011001000011100001000011100100",0x0000265F,0xFFFFF1CB,0x000003D5,0x00001ED2,0xFFFFF539,0x0000037A,0x00001ED2,0xFFFFF539,0x0000037A}, - {"0000001000010011111100001111111010011001000101100010000110000100",0x000027A8,0xFFFFF10D,0x00000413,0x000014B5,0xFFFFFBA1,0x00000299,0x000014B5,0xFFFFFBA1,0x00000299}, - {"0000001000010011111100001111111010011001000001000011000001100100",0x00002CEE,0xFFFFEDF6,0x00000476,0x00001A99,0xFFFFF83E,0x00000305,0x00001A99,0xFFFFF83E,0x00000305}, - {"0000001000010011111100001111111010011001000001100100000011000100",0x0000346C,0xFFFFEA17,0x000004EF,0x00001D38,0xFFFFF69F,0x0000033D,0x00001D38,0xFFFFF69F,0x0000033D}, - {"0000001000010011111100001111110101000010110110100010100101000100",0x00002DBB,0xFFFFED35,0x00000490,0x000018C1,0xFFFFF930,0x000002DA,0x000018C1,0xFFFFF930,0x000002DA}, - {"0000001000010011111100001111111010011001000001000010100100100100",0x000038DF,0xFFFFE8A7,0x0000051E,0x00001B59,0xFFFFF915,0x000002D3,0x00001B59,0xFFFFF915,0x000002D3}, - {"0000001000010011111100001111111010011001000010000000100101000100",0x00003384,0xFFFFE979,0x00000524,0x00001AF3,0xFFFFF74C,0x0000032F,0x00001AF3,0xFFFFF74C,0x0000032F}, - {"0000001000010011111100001111111010011001000110000001100001100100",0x0000258B,0xFFFFF2AE,0x000003CB,0x0000190C,0xFFFFF93E,0x000002EF,0x0000190C,0xFFFFF93E,0x000002EF}, - {"0000001000010011111100001111111010011001000100000011100010000100",0x000034F1,0xFFFFE84B,0x0000055E,0x00001CB8,0xFFFFF670,0x0000034A,0x00001CB8,0xFFFFF670,0x0000034A}, - {"0000001000010011111100001111111010011001000011000010000100000100",0x000030FB,0xFFFFECD2,0x00000488,0x00001BF4,0xFFFFF821,0x00000302,0x00001BF4,0xFFFFF821,0x00000302}, - {"0000001000010011111100001111111010011001000001100011000001000100",0x000036A6,0xFFFFE815,0x00000556,0x000018FD,0xFFFFF925,0x000002DF,0x000018FD,0xFFFFF925,0x000002DF}, - {"0000001000010011111010101001010011011110000000100011000001000100",0x0000302A,0xFFFFEB79,0x000004E0,0x00001C11,0xFFFFF694,0x00000358,0x00001C11,0xFFFFF694,0x00000358}, - {"0000001000010011111100001111111010011001000110000001000100100100",0x00002555,0xFFFFF2C4,0x000003CB,0x000017E3,0xFFFFFA1F,0x000002CB,0x000017E3,0xFFFFFA1F,0x000002CB}, - {"0000001000010011111100001111111010011001000010100011000101100100",0x000032A3,0xFFFFE933,0x00000544,0x000019D3,0xFFFFF81A,0x00000306,0x000019D3,0xFFFFF81A,0x00000306}, - {"0000001000010011111100001111110101000010110110000101000100000100",0x00002B91,0xFFFFED81,0x000004A9,0x0000158B,0xFFFFFAB9,0x000002AC,0x0000158B,0xFFFFFAB9,0x000002AC}, - {"0000001000010011111100001111111010011001000011100010000011000100",0x00003537,0xFFFFE912,0x0000052C,0x00001C8A,0xFFFFF754,0x0000031B,0x00001C8A,0xFFFFF754,0x0000031B}, - {"0000001000010011111010101001010011011110000001100011000110000100",0x000032E1,0xFFFFEA5A,0x000004F9,0x000017B4,0xFFFFF9D9,0x000002C2,0x000017B4,0xFFFFF9D9,0x000002C2}, - {"0000001000010011111100001111110101000010110100100001000011000100",0x00003B76,0xFFFFE330,0x00000636,0x000026FB,0xFFFFEF06,0x00000481,0x000026FB,0xFFFFEF06,0x00000481}, - {"0000001000010011111100001111111010011001000001000010000101000100",0x0000320C,0xFFFFEB84,0x000004C3,0x00001A3A,0xFFFFF8E9,0x000002DF,0x00001A3A,0xFFFFF8E9,0x000002DF}, - {"0000001000010011111100001111111010011001000000100011100110000100",0x0000317D,0xFFFFEA1F,0x00000515,0x00002100,0xFFFFF31B,0x000003DD,0x00002100,0xFFFFF31B,0x000003DD}, - {"0000001000010011111100001111110101000010110101000011000101100100",0x00003DCB,0xFFFFE0B4,0x000006B4,0x00002160,0xFFFFF269,0x000003F0,0x00002160,0xFFFFF269,0x000003F0}, - {"0000001000010011111100001111111010011001000101100001100011000100",0x00002737,0xFFFFF218,0x000003E1,0x000015B5,0xFFFFFB8F,0x0000029C,0x000015B5,0xFFFFFB8F,0x0000029C}, - {"0000001000010011111010101001010011011110000000100011000110000100",0x0000318F,0xFFFFEB3F,0x000004D8,0x00001938,0xFFFFF8E9,0x000002EB,0x00001938,0xFFFFF8E9,0x000002EB}, - {"0000001000010011111100001111111010011001000100000100100011000100",0x000031BD,0xFFFFE9DE,0x00000527,0x000018A7,0xFFFFF8CA,0x000002ED,0x000018A7,0xFFFFF8CA,0x000002ED}, - {"0000001000010011111100001111110101000010110110100011100010000100",0x00002F77,0xFFFFEC2F,0x000004B4,0x00001D25,0xFFFFF61B,0x0000035D,0x00001D25,0xFFFFF61B,0x0000035D}, - {"0000001000010011111100001111111010011001000011100100100100000100",0x00002CCA,0xFFFFEDB3,0x0000047C,0x00001FBD,0xFFFFF4A7,0x00000391,0x00001FBD,0xFFFFF4A7,0x00000391}, - {"0000001000010011111100001111110101000010110101000011100010100100",0x00003FF6,0xFFFFE058,0x000006A2,0x000024CD,0xFFFFF026,0x00000452,0x000024CD,0xFFFFF026,0x00000452}, - {"0000001000010011111100001111111010011001000010100011100011100100",0x00003161,0xFFFFEAC8,0x000004F3,0x00001BB6,0xFFFFF72A,0x0000032B,0x00001BB6,0xFFFFF72A,0x0000032B}, - {"0000001000010011111100001111110101000010110110000011100010100100",0x00002EA0,0xFFFFECA6,0x000004B7,0x000018C2,0xFFFFF94E,0x000002E1,0x000018C2,0xFFFFF94E,0x000002E1}, - {"0000001000010011111100001111111010011001000110000010000110000100",0x00002F62,0xFFFFEC9E,0x000004B8,0x00001531,0xFFFFFBCD,0x00000285,0x00001531,0xFFFFFBCD,0x00000285}, - {"0000001000010011111100001111111010011001000001000100000010100100",0x00003013,0xFFFFEBD6,0x000004C2,0x00001B01,0xFFFFF802,0x000002FF,0x00001B01,0xFFFFF802,0x000002FF}, - {"0000001000010011111100001111111010011001000110000011000001100100",0x00002972,0xFFFFF08D,0x00000417,0x00001A32,0xFFFFF8A4,0x00000305,0x00001A32,0xFFFFF8A4,0x00000305}, - {"0000001000010011111100001111110101000010110110000010000011100100",0x00002E95,0xFFFFED94,0x00000487,0x00001529,0xFFFFFC26,0x00000271,0x00001529,0xFFFFFC26,0x00000271}, - {"0000001000010011111100001111111010011001000010100001000010000100",0x00002D6A,0xFFFFEC79,0x000004C1,0x00001AE2,0xFFFFF725,0x00000337,0x00001AE2,0xFFFFF725,0x00000337}, - {"0000001000010011111100001111111010011001000000100001100010000100",0x000036B4,0xFFFFE704,0x00000591,0x00001E7E,0xFFFFF51C,0x00000383,0x00001E7E,0xFFFFF51C,0x00000383}, - {"0000001000010011111100001111111010011001000001000001100001000100",0x00002A6F,0xFFFFEF70,0x00000443,0x00001BAA,0xFFFFF752,0x00000336,0x00001BAA,0xFFFFF752,0x00000336}, - {"0000001000010011111100001111111010011001000110000011100101000100",0x00002C66,0xFFFFEF5F,0x0000043A,0x000019F7,0xFFFFF931,0x000002EC,0x000019F7,0xFFFFF931,0x000002EC}, - {"0000001000010011111010101001010011011110000001100011000111000100",0x00003852,0xFFFFE6AB,0x00000590,0x000019C1,0xFFFFF8B1,0x000002E5,0x000019C1,0xFFFFF8B1,0x000002E5}, - {"0000001000010011111100001111110101000010110110100011000100100100",0x00003521,0xFFFFE932,0x00000523,0x000018A9,0xFFFFF96B,0x000002D0,0x000018A9,0xFFFFF96B,0x000002D0}, - {"0000001000010011111100001111111010011001000001100010000101100100",0x000031B9,0xFFFFEB36,0x000004D0,0x00001D65,0xFFFFF612,0x0000035D,0x00001D65,0xFFFFF612,0x0000035D}, - {"0000001000010011111100001111110101000010110101000001000001100100",0x00003ED0,0xFFFFE135,0x00000679,0x00002351,0xFFFFF0FE,0x00000433,0x00002351,0xFFFFF0FE,0x00000433}, - {"0000001000010011111100001111111010011001000010100010000011100100",0x000033ED,0xFFFFE91A,0x00000541,0x00001C93,0xFFFFF6A0,0x0000034A,0x00001C93,0xFFFFF6A0,0x0000034A}, - {"0000001000010011111010101001010011011110000000100001100001000100",0x0000356F,0xFFFFE8F7,0x00000530,0x000016BF,0xFFFFFA85,0x000002AB,0x000016BF,0xFFFFFA85,0x000002AB}, - {"0000001000010011111100001111111010011001000110000100000011100100",0x00002304,0xFFFFF4F3,0x00000364,0x000017CC,0xFFFFFA41,0x000002CA,0x000017CC,0xFFFFFA41,0x000002CA}, - {"0000001000010011111100001111111010011001000101100001000101100100",0x00002887,0xFFFFEFD7,0x00000450,0x00001474,0xFFFFFB94,0x00000299,0x00001474,0xFFFFFB94,0x00000299}, - {"0000001000010011111100001111111010011001000001100011000001100100",0x00003D0B,0xFFFFE416,0x000005EF,0x00001C7E,0xFFFFF71D,0x00000325,0x00001C7E,0xFFFFF71D,0x00000325}, - {"0000001000010011111100001111111010011001000010000001000011100100",0x00003185,0xFFFFEAFA,0x000004E4,0x00001A12,0xFFFFF83C,0x00000303,0x00001A12,0xFFFFF83C,0x00000303}, - {"0000001000010011111100001111111010011001000010100001100101000100",0x00003032,0xFFFFEAE6,0x000004FC,0x00001B2A,0xFFFFF73F,0x0000032B,0x00001B2A,0xFFFFF73F,0x0000032B}, - {"0000001000010011111100001111110101000010110110000011100011000100",0x00002691,0xFFFFF22D,0x000003D6,0x00001700,0xFFFFFA6E,0x000002C0,0x00001700,0xFFFFFA6E,0x000002C0}, - {"0000001000010011111100001111111010011001000000100001100010100100",0x00002B2F,0xFFFFEEC4,0x0000044B,0x0000215F,0xFFFFF33F,0x000003D2,0x0000215F,0xFFFFF33F,0x000003D2}, - {"0000001000010011111100001111111010011001000010100100000110000100",0x000034AA,0xFFFFE706,0x000005B1,0x00001B28,0xFFFFF6B5,0x00000349,0x00001B28,0xFFFFF6B5,0x00000349}, - {"0000001000010011111100001111110101000010110110100010100101100100",0x0000307E,0xFFFFEB38,0x000004E6,0x00001A22,0xFFFFF83F,0x00000300,0x00001A22,0xFFFFF83F,0x00000300}, - {"0000001000010011111100001111111010011001000001100001100010100100",0x000038D6,0xFFFFE6D8,0x0000057C,0x00001B24,0xFFFFF7E4,0x00000307,0x00001B24,0xFFFFF7E4,0x00000307}, - {"0000001000010011111100001111111010011001000110000011000001000100",0x00002757,0xFFFFF1E8,0x000003DD,0x000017F5,0xFFFFFA15,0x000002C8,0x000017F5,0xFFFFFA15,0x000002C8}, - {"0000001000010011111100001111111010011001000010000011000110000100",0x000031FC,0xFFFFEB3E,0x000004CE,0x00001B4C,0xFFFFF7AD,0x00000319,0x00001B4C,0xFFFFF7AD,0x00000319}, - {"0000001000010011111100001111111010011001001100000001100001100100",0x00002933,0xFFFFF073,0x0000040E,0x00001C3C,0xFFFFF701,0x0000033C,0x00001C3C,0xFFFFF701,0x0000033C}, - {"0000001000010011111100001111110101000010110100100001100010100100",0x000040BB,0xFFFFE066,0x0000069A,0x0000257F,0xFFFFF08A,0x00000435,0x0000257F,0xFFFFF08A,0x00000435}, - {"0000001000010011111100001111111010011001000100000001000010100100",0x0000305B,0xFFFFEB9B,0x000004CB,0x00001996,0xFFFFF846,0x00000308,0x00001996,0xFFFFF846,0x00000308}, - {"0000001000010011111100001111111010011001000001100100100010000100",0x000039C0,0xFFFFE5D3,0x000005B0,0x00001A8D,0xFFFFF7DA,0x00000313,0x00001A8D,0xFFFFF7DA,0x00000313}, - {"0000001000010011111010101001010011011110000000100001000010100100",0x00002E23,0xFFFFED3F,0x0000048F,0x0000189D,0xFFFFF94C,0x000002DE,0x0000189D,0xFFFFF94C,0x000002DE}, - {"0000001000010011111010101001010011011110000000100001100110000100",0x0000332B,0xFFFFE9F1,0x00000516,0x000018E6,0xFFFFF8FE,0x000002EC,0x000018E6,0xFFFFF8FE,0x000002EC}, - {"0000001000010011111100001111111010011001000010000011100011000100",0x000034A0,0xFFFFEA44,0x000004E4,0x00001ECD,0xFFFFF5B4,0x00000364,0x00001ECD,0xFFFFF5B4,0x00000364}, - {"0000001000010011111100001111110101000010110100100100000100000100",0x0000448C,0xFFFFDF34,0x000006A8,0x0000231C,0xFFFFF286,0x000003D9,0x0000231C,0xFFFFF286,0x000003D9}, - {"0000001000010011111010101001010011011110000001100010000101000100",0x00002D8C,0xFFFFEE65,0x00000456,0x000018B1,0xFFFFF9C8,0x000002C8,0x000018B1,0xFFFFF9C8,0x000002C8}, - {"0000001000010011111100001111111010011001000001100001100100000100",0x00003527,0xFFFFE9BF,0x000004FD,0x00001D23,0xFFFFF69F,0x00000342,0x00001D23,0xFFFFF69F,0x00000342}, - {"0000001000010011111100001111110101000010110111000011100010100100",0x00002C51,0xFFFFEDC3,0x00000483,0x00001BE0,0xFFFFF720,0x0000032D,0x00001BE0,0xFFFFF720,0x0000032D}, - {"0000001000010011111100001111111010011001000010100011000001000100",0x00002C6C,0xFFFFECEB,0x000004B7,0x00001C86,0xFFFFF5E7,0x00000371,0x00001C86,0xFFFFF5E7,0x00000371}, - {"0000001000010011111100001111111010011001000001000101000101000100",0x000037CF,0xFFFFE6BE,0x00000599,0x000018CD,0xFFFFF967,0x000002C7,0x000018CD,0xFFFFF967,0x000002C7}, - {"0000001000010011111100001111111010011001000100000011000101100100",0x00002E6F,0xFFFFED1D,0x0000048E,0x00001ADC,0xFFFFF7F4,0x0000030E,0x00001ADC,0xFFFFF7F4,0x0000030E}, - {"0000001000010011111100001111110101000010110101000010100110000100",0x00003FF3,0xFFFFDF13,0x000006F9,0x000025BF,0xFFFFEEEE,0x00000497,0x000025BF,0xFFFFEEEE,0x00000497}, - {"0000001000010011111100001111110101000010110111000101000100000100",0x00004135,0xFFFFDF97,0x000006CC,0x00001D52,0xFFFFF541,0x00000383,0x00001D52,0xFFFFF541,0x00000383}, - {"0000001000010011111100001111110101000010110111000010000011100100",0x00002EA9,0xFFFFEDDB,0x0000045F,0x0000197C,0xFFFFF8E1,0x000002F0,0x0000197C,0xFFFFF8E1,0x000002F0}, - {"0000001000010011111010101001010011011110000001000011000010000100",0x0000345C,0xFFFFE922,0x00000532,0x00001922,0xFFFFF8C7,0x000002F1,0x00001922,0xFFFFF8C7,0x000002F1}, - {"0000001000010011111100001111111010011001000001100100000100100100",0x000035C4,0xFFFFE8FE,0x00000521,0x00001C87,0xFFFFF6F3,0x00000330,0x00001C87,0xFFFFF6F3,0x00000330}, - {"0000001000010011111100001111110101000010110110000011000101100100",0x00002888,0xFFFFF08A,0x0000041E,0x0000150F,0xFFFFFB87,0x00000291,0x0000150F,0xFFFFFB87,0x00000291}, - {"0000001000010011111100001111111010011001000010100001000100100100",0x000035E9,0xFFFFE657,0x000005CC,0x00001BD6,0xFFFFF664,0x00000355,0x00001BD6,0xFFFFF664,0x00000355}, - {"0000001000010011111100001111111010011001000101100100100011100100",0x00002F94,0xFFFFEBD0,0x000004E5,0x00001333,0xFFFFFCA7,0x00000266,0x00001333,0xFFFFFCA7,0x00000266}, - {"0000001000010011111100001111111010011001000110000001100101100100",0x000029E7,0xFFFFF009,0x00000433,0x0000144A,0xFFFFFC37,0x0000027D,0x0000144A,0xFFFFFC37,0x0000027D}, - {"0000001000010011111100001111111010011001001011000001100101000100",0x00003418,0xFFFFE979,0x00000521,0x00001D33,0xFFFFF66B,0x0000034A,0x00001D33,0xFFFFF66B,0x0000034A}, - {"0000001000010011111010101001010011011110000001000100000011100100",0x00003656,0xFFFFE79D,0x0000057A,0x000017C2,0xFFFFF992,0x000002D4,0x000017C2,0xFFFFF992,0x000002D4}, - {"0000001000010011111100001111111010011001000011000100000011000100",0x00002EB2,0xFFFFECFE,0x00000493,0x00001F2A,0xFFFFF543,0x0000037B,0x00001F2A,0xFFFFF543,0x0000037B}, - {"0000001000010011111100001111111010011001000000100001000100100100",0x00002FC1,0xFFFFEB3F,0x000004E8,0x00001CD0,0xFFFFF5F7,0x00000364,0x00001CD0,0xFFFFF5F7,0x00000364}, - {"0000001000010011111100001111111010011001000011000001000100100100",0x0000307B,0xFFFFEB66,0x000004DE,0x00001953,0xFFFFF8ED,0x000002E4,0x00001953,0xFFFFF8ED,0x000002E4}, - {"0000001000010011111100001111110101000010110110100001100010000100",0x00002CAA,0xFFFFED07,0x000004AC,0x0000251C,0xFFFFF086,0x0000044D,0x0000251C,0xFFFFF086,0x0000044D}, - {"0000001000010011111010101001010011011110000001000011100101000100",0x00002C94,0xFFFFEE5F,0x0000045B,0x000018D7,0xFFFFF900,0x000002EB,0x000018D7,0xFFFFF900,0x000002EB}, - {"0000001000010011111100001111111010011001000000100001100001100100",0x000031F1,0xFFFFE9BE,0x0000052E,0x00001DDF,0xFFFFF558,0x00000380,0x00001DDF,0xFFFFF558,0x00000380}, - {"0000001000010011111100001111111010011001000011100101000011000100",0x00002603,0xFFFFF1E9,0x000003DA,0x00001B37,0xFFFFF75A,0x0000032F,0x00001B37,0xFFFFF75A,0x0000032F}, - {"0000001000010011111100001111110101000010110110100011000001000100",0x00003992,0xFFFFE4F9,0x000005EB,0x00001775,0xFFFFF9B8,0x000002C2,0x00001775,0xFFFFF9B8,0x000002C2}, - {"0000001000010011111100001111111010011001000110000100100101100100",0x000029DA,0xFFFFF052,0x0000041F,0x000016E2,0xFFFFFA99,0x000002BB,0x000016E2,0xFFFFFA99,0x000002BB}, - {"0000001000010011111100001111111010011001000100000001000001100100",0x00002FF2,0xFFFFEB8F,0x000004DF,0x00001AF6,0xFFFFF7A1,0x00000321,0x00001AF6,0xFFFFF7A1,0x00000321}, - {"0000001000010011111100001111111010011001000101100000100011100100",0x00002590,0xFFFFF222,0x000003EE,0x0000130B,0xFFFFFCC9,0x00000268,0x0000130B,0xFFFFFCC9,0x00000268}, - {"0000001000010011111100001111111010011001000000100100000001100100",0x000038A2,0xFFFFE65F,0x000005A2,0x000018B1,0xFFFFF917,0x000002E1,0x000018B1,0xFFFFF917,0x000002E1}, - {"0000001000010011111100001111110101000010110111000100100011100100",0x000035FD,0xFFFFE73C,0x0000058D,0x00001BB3,0xFFFFF6E1,0x00000337,0x00001BB3,0xFFFFF6E1,0x00000337}, - {"0000001000010011111100001111111010011001000100000011100011000100",0x00002AB7,0xFFFFEF98,0x00000429,0x00001F35,0xFFFFF539,0x0000037C,0x00001F35,0xFFFFF539,0x0000037C}, - {"0000001000010011111100001111111010011001000010100000100101000100",0x000034BA,0xFFFFE73D,0x000005A6,0x000018A6,0xFFFFF888,0x000002FB,0x000018A6,0xFFFFF888,0x000002FB}, - {"0000001000010011111100001111111010011001000001100011100001000100",0x000032EA,0xFFFFEA78,0x000004F4,0x00001AB6,0xFFFFF812,0x00000308,0x00001AB6,0xFFFFF812,0x00000308}, - {"0000001000010011111100001111111010011001000011000011000001000100",0x00002BE9,0xFFFFEE9A,0x00000457,0x00001942,0xFFFFF8D2,0x000002F2,0x00001942,0xFFFFF8D2,0x000002F2}, - {"0000001000010011111100001111111010011001000100000101000100100100",0x00002FAB,0xFFFFEB76,0x000004E1,0x00001DCA,0xFFFFF57D,0x00000378,0x00001DCA,0xFFFFF57D,0x00000378}, - {"0000001000010011111100001111111010011001001011100010100001000100",0x0000330A,0xFFFFE9E1,0x0000051B,0x00001CC4,0xFFFFF6DF,0x00000335,0x00001CC4,0xFFFFF6DF,0x00000335}, - {"0000001000010011111100001111111010011001000110000010100010100100",0x000027D8,0xFFFFF276,0x000003BF,0x0000178A,0xFFFFFABF,0x000002B5,0x0000178A,0xFFFFFABF,0x000002B5}, - {"0000001000010011111100001111110101000010110111000011100001100100",0x0000340A,0xFFFFE86D,0x00000562,0x00001B85,0xFFFFF719,0x0000032F,0x00001B85,0xFFFFF719,0x0000032F}, - {"0000001000010011111010101001010011011110000001100011000010000100",0x00003879,0xFFFFE73F,0x00000578,0x0000161C,0xFFFFFB6B,0x00000281,0x0000161C,0xFFFFFB6B,0x00000281}, - {"0000001000010011111100001111111010011001000110000100000001100100",0x00002879,0xFFFFF0F8,0x0000040A,0x00001749,0xFFFFFA37,0x000002CC,0x00001749,0xFFFFFA37,0x000002CC}, - {"0000001000010011111100001111111010011001000001000011100101100100",0x00002C3A,0xFFFFEEA0,0x0000044F,0x00001D57,0xFFFFF6C2,0x00000332,0x00001D57,0xFFFFF6C2,0x00000332}, - {"0000001000010011111010101001010011011110000000100001100101100100",0x000035BB,0xFFFFE90D,0x0000052A,0x000017D9,0xFFFFF9F5,0x000002C3,0x000017D9,0xFFFFF9F5,0x000002C3}, - {"0000001000010011111010101001010011011110000001000001000100100100",0x000031F1,0xFFFFEAD4,0x000004ED,0x00001F10,0xFFFFF539,0x0000037D,0x00001F10,0xFFFFF539,0x0000037D}, - {"0000001000010011111100001111111010011001000100000010100000100100",0x00002A1A,0xFFFFEFAD,0x00000430,0x00001D47,0xFFFFF62F,0x0000035E,0x00001D47,0xFFFFF62F,0x0000035E}, - {"0000001000010011111100001111111010011001000101100100100100100100",0x00002AF0,0xFFFFEEDC,0x00000465,0x0000145F,0xFFFFFBEB,0x00000281,0x0000145F,0xFFFFFBEB,0x00000281}, - {"0000001000010011111100001111111010011001000110000011000101100100",0x00002657,0xFFFFF2E0,0x000003B6,0x00001664,0xFFFFFB37,0x000002A2,0x00001664,0xFFFFFB37,0x000002A2}, - {"0000001000010011111100001111110101000010110100000011100001100100",0x00003183,0xFFFFE9F1,0x0000052B,0x00002020,0xFFFFF3CE,0x000003C1,0x00002020,0xFFFFF3CE,0x000003C1}, - {"0000001000010011111100001111110101000010110001100010100011100100",0x00003240,0xFFFFEB65,0x000004C7,0x00002425,0xFFFFF245,0x000003F3,0x00002425,0xFFFFF245,0x000003F3}, - {"0000001000010011111010101001010011011110001100100001000100000100",0x000023D0,0xFFFFF400,0x00000397,0x00001345,0xFFFFFD6B,0x00000241,0x00001345,0xFFFFFD6B,0x00000241}, - {"0000001000010011111100001111110101000010110011100011100010100100",0x00003440,0xFFFFE872,0x0000055B,0x00002247,0xFFFFF296,0x000003E8,0x00002247,0xFFFFF296,0x000003E8}, - {"0000001000010011111100001111110101000010110100000100100100000100",0x00003275,0xFFFFE970,0x00000538,0x00001F94,0xFFFFF429,0x000003AD,0x00001F94,0xFFFFF429,0x000003AD}, - {"0000001000010011111100001111110101000010110001100100000010100100",0x00003918,0xFFFFE5DA,0x000005B6,0x000024FC,0xFFFFF106,0x00000426,0x000024FC,0xFFFFF106,0x00000426}, - {"0000001000010011111010101001010011011110000001100010000001000100",0x0000334B,0xFFFFEA39,0x000004FD,0x00001983,0xFFFFF8F6,0x000002E2,0x00001983,0xFFFFF8F6,0x000002E2}, - {"0000001000010011111100001111110101000010110001100100100110000100",0x00003B59,0xFFFFE4D0,0x000005DA,0x00002605,0xFFFFF090,0x00000439,0x00002605,0xFFFFF090,0x00000439}, - {"0000001000010011111100001111110101000010110100000011000100100100",0x00003251,0xFFFFEA46,0x00000511,0x00002781,0xFFFFEF84,0x00000470,0x00002781,0xFFFFEF84,0x00000470}, - {"0000001000010011111100001111110101000010110010100011000101100100",0x00003304,0xFFFFE926,0x00000542,0x00001EE9,0xFFFFF4E4,0x0000038B,0x00001EE9,0xFFFFF4E4,0x0000038B}, - {"0000001000010011111100001111110101000010110011000011100011000100",0x00002F4C,0xFFFFEC0C,0x000004C4,0x00001E49,0xFFFFF578,0x00000374,0x00001E49,0xFFFFF578,0x00000374}, - {"0000001000010011111010101001010011011110000111000010000101100100",0x00002034,0xFFFFF692,0x0000034C,0x000014B8,0xFFFFFC5B,0x00000294,0x000014B8,0xFFFFFC5B,0x00000294}, - {"0000001000010011111100001111110101000010110011100100100100100100",0x0000385F,0xFFFFE513,0x000005F3,0x000024E7,0xFFFFF053,0x00000450,0x000024E7,0xFFFFF053,0x00000450}, - {"0000001000010011111010101001010011011110000111000100000011100100",0x00001D70,0xFFFFF821,0x0000030F,0x00001541,0xFFFFFBB4,0x000002B0,0x00001541,0xFFFFFBB4,0x000002B0}, - {"0000001000010011111100001111110101000010110100000010000010000100",0x000034EB,0xFFFFE7FF,0x00000575,0x000019B4,0xFFFFF836,0x00000308,0x000019B4,0xFFFFF836,0x00000308}, - {"0000001000010011111100001111110101000010110100000101000011100100",0x000037C9,0xFFFFE5D4,0x000005CD,0x000026A1,0xFFFFEF0C,0x00000491,0x000026A1,0xFFFFEF0C,0x00000491}, - {"0000001000010011111010101001010011011110000100100001100101000100",0x00002918,0xFFFFF148,0x000003E9,0x00001A49,0xFFFFF94C,0x000002CF,0x00001A49,0xFFFFF94C,0x000002CF}, - {"0000001000010011111100001111110101000010110010100100000001100100",0x00002F90,0xFFFFEAB5,0x00000514,0x00001707,0xFFFFF9C7,0x000002C4,0x00001707,0xFFFFF9C7,0x000002C4}, - {"0000001000010011111010101001010011011110000001100010000001100100",0x0000327E,0xFFFFEA99,0x000004F4,0x0000194F,0xFFFFF929,0x000002DC,0x0000194F,0xFFFFF929,0x000002DC}, - {"0000001000010011111100001111110101000010110001100100000010000100",0x0000326F,0xFFFFE9CF,0x00000519,0x00002240,0xFFFFF299,0x000003E7,0x00002240,0xFFFFF299,0x000003E7}, - {"0000001000010011111010101001010011011110001100100001000100100100",0x000022FB,0xFFFFF4C6,0x00000371,0x00001506,0xFFFFFC73,0x00000265,0x00001506,0xFFFFFC73,0x00000265}, - {"0000001000010011111100001111110101000010110010100011100100100100",0x00003AD6,0xFFFFE470,0x000005FE,0x00001F03,0xFFFFF4F3,0x00000387,0x00001F03,0xFFFFF4F3,0x00000387}, - {"0000001000010011111010101001010011011110001000000001000100100100",0x00001F11,0xFFFFF756,0x00000332,0x00001666,0xFFFFFB8A,0x000002B2,0x00001666,0xFFFFFB8A,0x000002B2}, - {"0000001000010011111010101001010011011110000000100011100010100100",0x00002A5F,0xFFFFEFA7,0x00000430,0x00001943,0xFFFFF8C6,0x000002F7,0x00001943,0xFFFFF8C6,0x000002F7}, - {"0000001000010011111010101001010011011110000101100101000011100100",0x0000235E,0xFFFFF3B4,0x000003B3,0x00001489,0xFFFFFBCF,0x0000029B,0x00001489,0xFFFFFBCF,0x0000029B}, - {"0000001000010011111100001111110101000010110011000011100010100100",0x00003570,0xFFFFE780,0x0000058D,0x00001B1D,0xFFFFF767,0x00000325,0x00001B1D,0xFFFFF767,0x00000325}, - {"0000001000010011111010101001010011011110000001000010000001100100",0x00003678,0xFFFFE7C3,0x00000569,0x00001831,0xFFFFF98E,0x000002C8,0x00001831,0xFFFFF98E,0x000002C8}, - {"0000001000010011111010101001010011011110001000000001100001100100",0x000020B9,0xFFFFF625,0x0000035A,0x000015C5,0xFFFFFB8A,0x000002B5,0x000015C5,0xFFFFFB8A,0x000002B5}, - {"0000001000010011111100001111110101000010110001100011000110000100",0x00003985,0xFFFFE529,0x000005DD,0x00002165,0xFFFFF351,0x000003C5,0x00002165,0xFFFFF351,0x000003C5}, - {"0000001000010011111100001111110101000010110100000010000001100100",0x0000322A,0xFFFFE99D,0x00000535,0x000019A1,0xFFFFF844,0x00000305,0x000019A1,0xFFFFF844,0x00000305}, - {"0000001000010011111100001111110101000010110100000101000100000100",0x000033ED,0xFFFFE834,0x00000571,0x00002094,0xFFFFF33A,0x000003DB,0x00002094,0xFFFFF33A,0x000003DB}, - {"0000001000010011111010101001010011011110001000000100000011000100",0x00001D10,0xFFFFF84D,0x0000030B,0x00001659,0xFFFFFB0A,0x000002CB,0x00001659,0xFFFFFB0A,0x000002CB}, - {"0000001000010011111010101001010011011110000111000001000100100100",0x0000210F,0xFFFFF644,0x00000355,0x00001A4A,0xFFFFF90F,0x00000310,0x00001A4A,0xFFFFF90F,0x00000310}, - {"0000001000010011111010101001010011011110000101100100000101100100",0x00001CA8,0xFFFFF813,0x00000316,0x00001440,0xFFFFFC1C,0x0000029D,0x00001440,0xFFFFFC1C,0x0000029D}, - {"0000001000010011111010101001010011011110001100100001000011000100",0x00002864,0xFFFFF15A,0x000003FA,0x0000137F,0xFFFFFD43,0x00000248,0x0000137F,0xFFFFFD43,0x00000248}, - {"0000001000010011111100001111110101000010110100000100000110000100",0x00002CDB,0xFFFFECFD,0x000004A7,0x00002472,0xFFFFF0E1,0x00000437,0x00002472,0xFFFFF0E1,0x00000437}, - {"0000001000010011111100001111110101000010110011000101000100000100",0x00003348,0xFFFFE8CA,0x00000554,0x00001E91,0xFFFFF4D4,0x00000392,0x00001E91,0xFFFFF4D4,0x00000392}, - {"0000001000010011111100001111110101000010110001100100100101000100",0x00003989,0xFFFFE4BB,0x000005F8,0x00001ACB,0xFFFFF780,0x00000319,0x00001ACB,0xFFFFF780,0x00000319}, - {"0000001000010011111100001111110101000010110010100010000100000100",0x00003238,0xFFFFEA09,0x0000051E,0x00001F08,0xFFFFF4F4,0x0000038C,0x00001F08,0xFFFFF4F4,0x0000038C}, - {"0000001000010011111010101001010011011110000100100000100100000100",0x00002453,0xFFFFF3B0,0x0000038D,0x00001AED,0xFFFFF8A2,0x000002EA,0x00001AED,0xFFFFF8A2,0x000002EA}, - {"0000001000010011111010101001010011011110000111000011000000100100",0x00002459,0xFFFFF409,0x000003A8,0x000017B5,0xFFFFFA53,0x000002E1,0x000017B5,0xFFFFFA53,0x000002E1}, - {"0000001000010011111010101001010011011110000000100001000110000100",0x0000310D,0xFFFFEB78,0x000004D0,0x00001DC9,0xFFFFF5D5,0x00000368,0x00001DC9,0xFFFFF5D5,0x00000368}, - {"0000001000010011111010101001010011011110000000100011000100000100",0x000031BF,0xFFFFECA3,0x00000498,0x00001DC9,0xFFFFF717,0x00000336,0x00001DC9,0xFFFFF717,0x00000336}, - {"0000001000010011111100001111110101000010110011100010000100000100",0x00003896,0xFFFFE5DD,0x000005C5,0x000023E2,0xFFFFF1A1,0x00000416,0x000023E2,0xFFFFF1A1,0x00000416}, - {"0000001000010011111010101001010011011110001100100011100100000100",0x000023CB,0xFFFFF4C8,0x00000372,0x00001C33,0xFFFFF7D5,0x0000032A,0x00001C33,0xFFFFF7D5,0x0000032A}, - {"0000001000010011111100001111110101000010110100000010000011000100",0x00002F6B,0xFFFFEBF0,0x000004CE,0x00001C89,0xFFFFF689,0x0000034D,0x00001C89,0xFFFFF689,0x0000034D}, - {"0000001000010011111100001111110101000010110011100011100100000100",0x00003E72,0xFFFFE211,0x0000065D,0x0000218D,0xFFFFF309,0x000003DC,0x0000218D,0xFFFFF309,0x000003DC}, - {"0000001000010011111010101001010011011110000000100010000010000100",0x00002612,0xFFFFF2C3,0x000003AD,0x000019F7,0xFFFFF891,0x000002FE,0x000019F7,0xFFFFF891,0x000002FE}, - {"0000001000010011111010101001010011011110000101100100000110000100",0x0000205D,0xFFFFF59F,0x00000372,0x000012E6,0xFFFFFD0A,0x00000270,0x000012E6,0xFFFFFD0A,0x00000270}, - {"0000001000010011111100001111110101000010110010100010000100100100",0x00002ECB,0xFFFFEC47,0x000004BD,0x00001936,0xFFFFF8D9,0x000002E4,0x00001936,0xFFFFF8D9,0x000002E4}, - {"0000001000010011111010101001010011011110000001100100100100000100",0x00002BDB,0xFFFFEE6D,0x00000458,0x00001852,0xFFFFF943,0x000002D9,0x00001852,0xFFFFF943,0x000002D9}, - {"0000001000010011111010101001010011011110000100100100100100000100",0x00003387,0xFFFFE958,0x00000534,0x00001932,0xFFFFF8FA,0x000002E4,0x00001932,0xFFFFF8FA,0x000002E4}, - {"0000001000010011111010101001010011011110000000100000100011000100",0x00002E3C,0xFFFFED26,0x00000495,0x00001858,0xFFFFF990,0x000002D1,0x00001858,0xFFFFF990,0x000002D1}, - {"0000001000010011111010101001010011011110000000100010100101100100",0x000033B8,0xFFFFEA5C,0x000004F9,0x00001BD1,0xFFFFF76A,0x0000032E,0x00001BD1,0xFFFFF76A,0x0000032E}, - {"0000001000010011111010101001010011011110000001100010100110000100",0x00002BCE,0xFFFFEEE9,0x00000443,0x00001982,0xFFFFF90D,0x000002DF,0x00001982,0xFFFFF90D,0x000002DF}, - {"0000001000010011111100001111110101000010110100000100100011100100",0x00003495,0xFFFFE7D9,0x0000057B,0x00001D2A,0xFFFFF5A5,0x00000372,0x00001D2A,0xFFFFF5A5,0x00000372}, - {"0000001000010011111100001111110101000010110010100011100011100100",0x000034B1,0xFFFFE88D,0x00000556,0x00002014,0xFFFFF43A,0x000003AA,0x00002014,0xFFFFF43A,0x000003AA}, - {"0000001000010011111100001111110101000010110011000011000100100100",0x00002F96,0xFFFFEC84,0x000004AD,0x000024A2,0xFFFFF1CE,0x0000040A,0x000024A2,0xFFFFF1CE,0x0000040A}, - {"0000001000010011111010101001010011011110000101100001000001100100",0x0000203B,0xFFFFF640,0x00000359,0x000014EC,0xFFFFFC14,0x0000029C,0x000014EC,0xFFFFFC14,0x0000029C}, - {"0000001000010011111100001111110101000010110100000010100110000100",0x000034E2,0xFFFFE7B8,0x00000582,0x00001938,0xFFFFF872,0x000002FA,0x00001938,0xFFFFF872,0x000002FA}, - {"0000001000010011111010101001010011011110000001100011000100100100",0x00002AC7,0xFFFFF0C1,0x000003F5,0x00002268,0xFFFFF39C,0x000003C9,0x00002268,0xFFFFF39C,0x000003C9}, - {"0000001000010011111100001111110101000010110001100011000101000100",0x000036F6,0xFFFFE77F,0x00000571,0x000027D9,0xFFFFEF6F,0x00000461,0x000027D9,0xFFFFEF6F,0x00000461}, - {"0000001000010011111010101001010011011110000100100011000100100100",0x00002BAB,0xFFFFF018,0x00000419,0x00002126,0xFFFFF4E2,0x0000038F,0x00002126,0xFFFFF4E2,0x0000038F}, - {"0000001000010011111010101001010011011110001100100011100100100100",0x000028C4,0xFFFFF161,0x000003F8,0x0000180C,0xFFFFFA4B,0x000002C8,0x0000180C,0xFFFFFA4B,0x000002C8}, - {"0000001000010011111100001111110101000010110010100010100001100100",0x00002F48,0xFFFFEB62,0x000004EE,0x00001912,0xFFFFF8C8,0x000002EA,0x00001912,0xFFFFF8C8,0x000002EA}, - {"0000001000010011111100001111110101000010110011100010100001100100",0x000032DF,0xFFFFE911,0x00000545,0x00001F06,0xFFFFF485,0x0000039C,0x00001F06,0xFFFFF485,0x0000039C}, - {"0000001000010011111100001111110101000010110100000100000101000100",0x000035B8,0xFFFFE74F,0x00000590,0x00001FD7,0xFFFFF410,0x000003AF,0x00001FD7,0xFFFFF410,0x000003AF}, - {"0000001000010011111100001111110101000010110100000101000011000100",0x00003608,0xFFFFE6D7,0x000005A9,0x000024A6,0xFFFFF075,0x00000450,0x000024A6,0xFFFFF075,0x00000450}, - {"0000001000010011111100001111110101000010110010100011100010000100",0x000030AB,0xFFFFEAED,0x000004F5,0x000019EE,0xFFFFF84E,0x000002FC,0x000019EE,0xFFFFF84E,0x000002FC}, - {"0000001000010011111010101001010011011110000001100010000011000100",0x000030C6,0xFFFFEC92,0x0000049E,0x000019BB,0xFFFFF8F1,0x000002F3,0x000019BB,0xFFFFF8F1,0x000002F3}, - {"0000001000010011111100001111110101000010110001100011000010100100",0x00003B27,0xFFFFE544,0x000005C1,0x00002697,0xFFFFF072,0x00000438,0x00002697,0xFFFFF072,0x00000438}, - {"0000001000010011111010101001010011011110000100100100100011100100",0x00002F23,0xFFFFEC48,0x000004B9,0x0000199A,0xFFFFF8CF,0x000002E9,0x0000199A,0xFFFFF8CF,0x000002E9}, - {"0000001000010011111010101001010011011110000001100010100110100100",0x00002BD7,0xFFFFEEAC,0x00000450,0x00001991,0xFFFFF8F4,0x000002E2,0x00001991,0xFFFFF8F4,0x000002E2}, - {"0000001000010011111010101001010011011110000000100010000000100100",0x00003210,0xFFFFEB24,0x000004DE,0x00001BDF,0xFFFFF744,0x00000333,0x00001BDF,0xFFFFF744,0x00000333}, - {"0000001000010011111010101001010011011110001001000100000101000100",0x00002DDC,0xFFFFED0D,0x000004AC,0x000019D0,0xFFFFF869,0x0000030F,0x000019D0,0xFFFFF869,0x0000030F}, - {"0000001000010011111010101001010011011110001000000011100101100100",0x000023E6,0xFFFFF40C,0x000003A9,0x000014EB,0xFFFFFBC4,0x000002AF,0x000014EB,0xFFFFFBC4,0x000002AF}, - {"0000001000010011111100001111110101000010110010100010100110100100",0x000030CE,0xFFFFE9A5,0x0000053C,0x00001C45,0xFFFFF60E,0x0000035D,0x00001C45,0xFFFFF60E,0x0000035D}, - {"0000001000010011111010101001010011011110000101100001000010000100",0x00001E89,0xFFFFF73A,0x00000337,0x0000157C,0xFFFFFBC0,0x000002AA,0x0000157C,0xFFFFFBC0,0x000002AA}, - {"0000001000010011111100001111110101000010110100000100000100100100",0x000036C6,0xFFFFE6CF,0x000005A1,0x00002457,0xFFFFF11D,0x0000042D,0x00002457,0xFFFFF11D,0x0000042D}, - {"0000001000010011111010101001010011011110001100100001100101000100",0x00002815,0xFFFFF19A,0x000003F2,0x000016D2,0xFFFFFB40,0x00000299,0x000016D2,0xFFFFFB40,0x00000299}, - {"0000001000010011111010101001010011011110000111000001100110100100",0x00001FE2,0xFFFFF660,0x00000354,0x000015A7,0xFFFFFB47,0x000002C1,0x000015A7,0xFFFFFB47,0x000002C1}, - {"0000001000010011111010101001010011011110000101100001100101100100",0x00002114,0xFFFFF634,0x00000356,0x000016C1,0xFFFFFB43,0x000002B8,0x000016C1,0xFFFFFB43,0x000002B8}, - {"0000001000010011111100001111110101000010110011000010100011000100",0x000028E3,0xFFFFF075,0x00000414,0x0000203C,0xFFFFF438,0x000003B3,0x0000203C,0xFFFFF438,0x000003B3}, - {"0000001000010011111010101001010011011110000111000011100100100100",0x00001EEB,0xFFFFF7BB,0x0000031A,0x00001580,0xFFFFFBD7,0x000002AD,0x00001580,0xFFFFFBD7,0x000002AD}, - {"0000001000010011111010101001010011011110001001000000100011000100",0x00002BB2,0xFFFFEE72,0x00000470,0x0000192C,0xFFFFF91E,0x000002E7,0x0000192C,0xFFFFF91E,0x000002E7}, - {"0000001000010011111010101001010011011110000001100101000011100100",0x00003A3D,0xFFFFE49D,0x000005F5,0x00001A3B,0xFFFFF7B1,0x00000320,0x00001A3B,0xFFFFF7B1,0x00000320}, - {"0000001000010011111100001111110101000010110011100011000101100100",0x00002E93,0xFFFFEC5A,0x000004B4,0x000025EB,0xFFFFF03C,0x0000044A,0x000025EB,0xFFFFF03C,0x0000044A}, - {"0000001000010011111100001111110101000010110010100010000011000100",0x0000331F,0xFFFFE97A,0x00000531,0x00001A06,0xFFFFF850,0x000002FD,0x00001A06,0xFFFFF850,0x000002FD}, - {"0000001000010011111100001111110101000010110001100011100101100100",0x00003937,0xFFFFE5A0,0x000005C7,0x0000235E,0xFFFFF234,0x000003F2,0x0000235E,0xFFFFF234,0x000003F2}, - {"0000001000010011111010101001010011011110000111100011100100100100",0x00001DD0,0xFFFFF80E,0x00000319,0x000015C7,0xFFFFFB91,0x000002BC,0x000015C7,0xFFFFFB91,0x000002BC}, - {"0000001000010011111100001111110101000010110100000011100101100100",0x00003328,0xFFFFE905,0x0000054A,0x00002054,0xFFFFF3BF,0x000003C0,0x00002054,0xFFFFF3BF,0x000003C0}, - {"0000001000010011111100001111110101000010110011000001000100000100",0x00002FE5,0xFFFFEA65,0x00000520,0x0000188B,0xFFFFF8A7,0x000002F5,0x0000188B,0xFFFFF8A7,0x000002F5}, - {"0000001000010011111100001111110101000010110010100011100010100100",0x00002ED3,0xFFFFEC51,0x000004B9,0x00001888,0xFFFFF96A,0x000002CA,0x00001888,0xFFFFF96A,0x000002CA}, - {"0000001000010011111100001111110101000010110100000011000010000100",0x00002FCC,0xFFFFEB60,0x000004EA,0x00001F8D,0xFFFFF436,0x000003B4,0x00001F8D,0xFFFFF436,0x000003B4}, - {"0000001000010011111100001111110101000010110011100100000010000100",0x0000329F,0xFFFFE8F7,0x0000054F,0x000023DB,0xFFFFF0EE,0x0000043A,0x000023DB,0xFFFFF0EE,0x0000043A}, - {"0000001000010011111010101001010011011110000001000011100010100100",0x000030B5,0xFFFFEBB8,0x000004C4,0x00001AFD,0xFFFFF781,0x00000329,0x00001AFD,0xFFFFF781,0x00000329}, - {"0000001000010011111010101001010011011110000111100001100110100100",0x00001BBF,0xFFFFF8E2,0x000002F7,0x00001722,0xFFFFFA85,0x000002DB,0x00001722,0xFFFFFA85,0x000002DB}, - {"0000001000010011111010101001010011011110000000100010000001000100",0x000030E4,0xFFFFEBE6,0x000004BB,0x00001C80,0xFFFFF6E1,0x0000033E,0x00001C80,0xFFFFF6E1,0x0000033E}, - {"0000001000010011111010101001010011011110000100100010100101000100",0x000030E2,0xFFFFECD0,0x00000492,0x00001CE0,0xFFFFF753,0x0000032F,0x00001CE0,0xFFFFF753,0x0000032F}, - {"0000001000010011111010101001010011011110001100100010100001100100",0x00002513,0xFFFFF323,0x000003BC,0x00001965,0xFFFFF93C,0x000002F0,0x00001965,0xFFFFF93C,0x000002F0}, - {"0000001000010011111010101001010011011110000101100001000010100100",0x00002147,0xFFFFF585,0x0000037A,0x000014CC,0xFFFFFC3B,0x00000296,0x000014CC,0xFFFFFC3B,0x00000296}, - {"0000001000010011111010101001010011011110001100100010000100100100",0x00002507,0xFFFFF432,0x0000038A,0x00001890,0xFFFFFA61,0x000002C6,0x00001890,0xFFFFFA61,0x000002C6}, - {"0000001000010011111010101001010011011110000001100011100010100100",0x0000339B,0xFFFFEA7D,0x000004F0,0x0000191E,0xFFFFF944,0x000002DF,0x0000191E,0xFFFFF944,0x000002DF}, - {"0000001000010011111100001111110101000010110011000010100010100100",0x00002842,0xFFFFF043,0x00000427,0x00001988,0xFFFFF892,0x000002F7,0x00001988,0xFFFFF892,0x000002F7}, - {"0000001000010011111100001111110101000010110001100001100010100100",0x0000389D,0xFFFFE5D8,0x000005BF,0x00001EE1,0xFFFFF4EF,0x00000387,0x00001EE1,0xFFFFF4EF,0x00000387}, - {"0000001000010011111100001111110101000010110011100011000110000100",0x0000396D,0xFFFFE4D7,0x000005F2,0x000020DA,0xFFFFF34E,0x000003CD,0x000020DA,0xFFFFF34E,0x000003CD}, - {"0000001000010011111100001111110101000010110010100011000100000100",0x0000355F,0xFFFFE85A,0x0000055F,0x0000281F,0xFFFFEF28,0x0000047D,0x0000281F,0xFFFFEF28,0x0000047D}, - {"0000001000010011111010101001010011011110000111000101000011100100",0x00002284,0xFFFFF46E,0x00000399,0x00001498,0xFFFFFBE3,0x0000029C,0x00001498,0xFFFFFBE3,0x0000029C}, - {"0000001000010011111010101001010011011110000000100011100101000100",0x000031B6,0xFFFFEB42,0x000004D9,0x00001F54,0xFFFFF4D2,0x00000399,0x00001F54,0xFFFFF4D2,0x00000399}, - {"0000001000010011111100001111110101000010110001100011000001100100",0x000035CE,0xFFFFE79D,0x00000578,0x00001C78,0xFFFFF68C,0x00000344,0x00001C78,0xFFFFF68C,0x00000344}, - {"0000001000010011111010101001010011011110000111100100100101100100",0x00001C0A,0xFFFFF81B,0x00000318,0x00001492,0xFFFFFBCC,0x000002A5,0x00001492,0xFFFFFBCC,0x000002A5}, - {"0000001000010011111010101001010011011110000000100010000110000100",0x00003492,0xFFFFE95C,0x00000526,0x00001A97,0xFFFFF81B,0x0000030B,0x00001A97,0xFFFFF81B,0x0000030B}, - {"0000001000010011111010101001010011011110000101100011000101100100",0x00001E89,0xFFFFF7D0,0x0000031A,0x000017A5,0xFFFFFA99,0x000002D9,0x000017A5,0xFFFFFA99,0x000002D9}, - {"0000001000010011111100001111110101000010110010100100100011000100",0x00002DCC,0xFFFFEBE0,0x000004DE,0x000019BA,0xFFFFF7F5,0x0000030D,0x000019BA,0xFFFFF7F5,0x0000030D}, - {"0000001000010011111010101001010011011110000001000010100110000100",0x000030EF,0xFFFFEBC1,0x000004C0,0x00001AA9,0xFFFFF814,0x0000030A,0x00001AA9,0xFFFFF814,0x0000030A}, - {"0000001000010011111010101001010011011110001001000101000100100100",0x00002EA3,0xFFFFEBF6,0x000004D8,0x00001DCF,0xFFFFF521,0x00000399,0x00001DCF,0xFFFFF521,0x00000399}, - {"0000001000010011111010101001010011011110001100100100000101100100",0x00002B5F,0xFFFFEEA1,0x0000046C,0x000017EB,0xFFFFF9C9,0x000002D4,0x000017EB,0xFFFFF9C9,0x000002D4}, - {"0000001000010011111010101001010011011110000000100100000100000100",0x00002C63,0xFFFFEE82,0x00000455,0x00002268,0xFFFFF29D,0x000003F6,0x00002268,0xFFFFF29D,0x000003F6}, - {"0000001000010011111010101001010011011110000100100001100100000100",0x00002B1A,0xFFFFF016,0x0000041C,0x000019AA,0xFFFFF988,0x000002D2,0x000019AA,0xFFFFF988,0x000002D2}, - {"0000001000010011111100001111110101000010110010100010100101100100",0x0000332F,0xFFFFE934,0x0000053B,0x00001E47,0xFFFFF566,0x00000374,0x00001E47,0xFFFFF566,0x00000374}, - {"0000001000010011111100001111110101000010110010100100100011100100",0x00002995,0xFFFFEEC1,0x00000465,0x0000178F,0xFFFFF995,0x000002C5,0x0000178F,0xFFFFF995,0x000002C5}, - {"0000001000010011111010101001010011011110001000000001100010000100",0x00001C2E,0xFFFFF932,0x000002E9,0x000015C2,0xFFFFFBC5,0x000002AD,0x000015C2,0xFFFFFBC5,0x000002AD}, - {"0000001000010011111100001111110101000010110001100100000011100100",0x00003B08,0xFFFFE4E8,0x000005D8,0x0000209D,0xFFFFF444,0x00000398,0x0000209D,0xFFFFF444,0x00000398}, - {"0000001000010011111010101001010011011110000001000101000011100100",0x00002F1F,0xFFFFEB74,0x000004EB,0x00001F4C,0xFFFFF3D4,0x000003CE,0x00001F4C,0xFFFFF3D4,0x000003CE}, - {"0000001000010011111010101001010011011110000001000011100010000100",0x00003415,0xFFFFE89F,0x00000553,0x0000186B,0xFFFFF8E1,0x000002EF,0x0000186B,0xFFFFF8E1,0x000002EF}, - {"0000001000010011111100001111110101000010110011000001000011000100",0x00003441,0xFFFFE779,0x0000059D,0x000019EA,0xFFFFF7B2,0x0000031F,0x000019EA,0xFFFFF7B2,0x0000031F}, - {"0000001000010011111010101001010011011110000101100100000001100100",0x00002174,0xFFFFF546,0x00000378,0x00001456,0xFFFFFC5F,0x00000284,0x00001456,0xFFFFFC5F,0x00000284}, - {"0000001000010011111100001111110101000010110011100100000011000100",0x00003788,0xFFFFE61E,0x000005BF,0x00001DF4,0xFFFFF562,0x00000374,0x00001DF4,0xFFFFF562,0x00000374}, - {"0000001000010011111010101001010011011110000111100001100001000100",0x00001C41,0xFFFFF8C1,0x000002FC,0x0000171E,0xFFFFFA93,0x000002DE,0x0000171E,0xFFFFFA93,0x000002DE}, - {"0000001000010011111100001111110101000010110010100011100001100100",0x00002B15,0xFFFFEDEC,0x00000487,0x000017E4,0xFFFFF934,0x000002DF,0x000017E4,0xFFFFF934,0x000002DF}, - {"0000001000010011111100001111110101000010110011000011000101000100",0x0000327A,0xFFFFEA71,0x000004FF,0x00001D96,0xFFFFF63B,0x00000351,0x00001D96,0xFFFFF63B,0x00000351}, - {"0000001000010011111010101001010011011110000111100100000001100100",0x000023C6,0xFFFFF3E5,0x000003B6,0x000014DE,0xFFFFFC29,0x00000294,0x000014DE,0xFFFFFC29,0x00000294}, - {"0000001000010011111010101001010011011110000101100100100101000100",0x00001F96,0xFFFFF5FA,0x00000364,0x00001397,0xFFFFFC9D,0x0000027D,0x00001397,0xFFFFFC9D,0x0000027D}, - {"0000001000010011111010101001010011011110000001100011000101000100",0x00002B51,0xFFFFEFB5,0x00000420,0x00001ACA,0xFFFFF824,0x0000030D,0x00001ACA,0xFFFFF824,0x0000030D}, - {"0000001000010011111010101001010011011110000111100100100101000100",0x000020DB,0xFFFFF55B,0x0000037C,0x0000153D,0xFFFFFB5F,0x000002BA,0x0000153D,0xFFFFFB5F,0x000002BA}, - {"0000001000010011111010101001010011011110000000100010000110100100",0x000030BB,0xFFFFEBDA,0x000004BC,0x00001B0E,0xFFFFF7A8,0x0000031E,0x00001B0E,0xFFFFF7A8,0x0000031E}, - {"0000001000010011111100001111110101000010110001100010100100000100",0x000033C4,0xFFFFEA41,0x000004FA,0x000022C6,0xFFFFF363,0x000003BC,0x000022C6,0xFFFFF363,0x000003BC}, - {"0000001000010011111010101001010011011110001001000000100100100100",0x00002D47,0xFFFFEE01,0x00000477,0x000021CD,0xFFFFF36E,0x000003D6,0x000021CD,0xFFFFF36E,0x000003D6}, - {"0000001000010011111010101001010011011110000111100011000110100100",0x00001E7B,0xFFFFF733,0x00000339,0x00001668,0xFFFFFB29,0x000002BF,0x00001668,0xFFFFFB29,0x000002BF}, - {"0000001000010011111100001111110101000010110010100010100110000100",0x00002F7E,0xFFFFEAFF,0x000004FC,0x000018D4,0xFFFFF8BE,0x000002E8,0x000018D4,0xFFFFF8BE,0x000002E8}, - {"0000001000010011111010101001010011011110001100100011100010100100",0x00002635,0xFFFFF2E1,0x000003BC,0x000017A4,0xFFFFFA67,0x000002C3,0x000017A4,0xFFFFFA67,0x000002C3}, - {"0000001000010011111010101001010011011110000100100011000010100100",0x000026CA,0xFFFFF2C1,0x000003B2,0x00001C3E,0xFFFFF7AE,0x0000031F,0x00001C3E,0xFFFFF7AE,0x0000031F}, - {"0000001000010011111010101001010011011110000111000001000001100100",0x00002550,0xFFFFF380,0x000003B5,0x000019F5,0xFFFFF8E7,0x00000313,0x000019F5,0xFFFFF8E7,0x00000313}, - {"0000001000010011111100001111110101000010110010100100100100000100",0x00002FBC,0xFFFFEAF8,0x000004FA,0x000018CC,0xFFFFF8C6,0x000002E8,0x000018CC,0xFFFFF8C6,0x000002E8}, - {"0000001000010011111100001111110101000010110100000001100011100100",0x00002FCC,0xFFFFEB60,0x000004EA,0x00001EFF,0xFFFFF4DA,0x0000038F,0x00001EFF,0xFFFFF4DA,0x0000038F}, - {"0000001000010011111010101001010011011110000101100100000010000100",0x000023E6,0xFFFFF413,0x000003A1,0x00001544,0xFFFFFC16,0x0000028B,0x00001544,0xFFFFFC16,0x0000028B}, - {"0000001000010011111100001111110101000010110011100011000000100100",0x00003251,0xFFFFEAA2,0x000004F5,0x000025B0,0xFFFFF0DF,0x00000431,0x000025B0,0xFFFFF0DF,0x00000431}, - {"0000001000010011111100001111110101000010110100000011100110000100",0x00002F6F,0xFFFFEB67,0x000004E6,0x00002275,0xFFFFF249,0x000003FB,0x00002275,0xFFFFF249,0x000003FB}, - {"0000001000010011111010101001010011011110001100100010100101100100",0x00002597,0xFFFFF34A,0x000003B1,0x00001BCC,0xFFFFF822,0x0000031A,0x00001BCC,0xFFFFF822,0x0000031A}, - {"0000001000010011111100001111110101000010110001100011100001100100",0x00003B1D,0xFFFFE40E,0x0000060D,0x00001F61,0xFFFFF470,0x0000039F,0x00001F61,0xFFFFF470,0x0000039F}, - {"0000001000010011111100001111110101000010110001100100000101000100",0x0000379F,0xFFFFE6DB,0x0000058C,0x00002460,0xFFFFF170,0x00000415,0x00002460,0xFFFFF170,0x00000415}, - {"0000001000010011111010101001010011011110000101100101000101000100",0x00002442,0xFFFFF2FB,0x000003D9,0x00001414,0xFFFFFBDC,0x000002A2,0x00001414,0xFFFFFBDC,0x000002A2}, - {"0000001000010011111010101001010011011110000000100100000011000100",0x00003270,0xFFFFEA0D,0x0000051C,0x00001AFD,0xFFFFF783,0x00000328,0x00001AFD,0xFFFFF783,0x00000328}, - {"0000001000010011111010101001010011011110000101100001000100000100",0x00001B23,0xFFFFF94B,0x000002EB,0x000015F1,0xFFFFFB82,0x000002B4,0x000015F1,0xFFFFFB82,0x000002B4}, - {"0000001000010011111010101001010011011110001100100011100001000100",0x000026AE,0xFFFFF21A,0x000003DB,0x00001827,0xFFFFFA10,0x000002C8,0x00001827,0xFFFFFA10,0x000002C8}, - {"0000001000010011111100001111110101000010110010100100100010000100",0x00002DCF,0xFFFFEBD8,0x000004DB,0x00001A75,0xFFFFF719,0x0000033A,0x00001A75,0xFFFFF719,0x0000033A}, - {"0000001000010011111100001111110101000010110011100100000011100100",0x00003983,0xFFFFE500,0x000005EA,0x000022A6,0xFFFFF25F,0x000003F1,0x000022A6,0xFFFFF25F,0x000003F1}, - {"0000001000010011111010101001010011011110000100100001100011000100",0x00002AD5,0xFFFFF07A,0x00000406,0x000019FB,0xFFFFF961,0x000002D8,0x000019FB,0xFFFFF961,0x000002D8}, - {"0000001000010011111100001111110101000010110010100011100110100100",0x00002A43,0xFFFFEE43,0x00000474,0x00001D65,0xFFFFF538,0x00000387,0x00001D65,0xFFFFF538,0x00000387}, - {"0000001000010011111100001111110101000010110001100010000010000100",0x0000311E,0xFFFFEAF8,0x000004E8,0x00001959,0xFFFFF8E4,0x000002DC,0x00001959,0xFFFFF8E4,0x000002DC}, - {"0000001000010011111100001111110101000010110100000011000110100100",0x0000339A,0xFFFFE8A7,0x00000559,0x00001A04,0xFFFFF7E5,0x00000311,0x00001A04,0xFFFFF7E5,0x00000311}, - {"0000001000010011111010101001010011011110001000000100000101000100",0x000021B3,0xFFFFF50F,0x00000389,0x00001470,0xFFFFFBF7,0x000002A5,0x00001470,0xFFFFFBF7,0x000002A5}, - {"0000001000010011111010101001010011011110000000100001100010000100",0x00003417,0xFFFFE9A6,0x0000051D,0x000018A4,0xFFFFF984,0x000002CF,0x000018A4,0xFFFFF984,0x000002CF}, - {"0000001000010011111010101001010011011110001000000010100110000100",0x00001FED,0xFFFFF6A2,0x00000347,0x00001639,0xFFFFFB59,0x000002BB,0x00001639,0xFFFFFB59,0x000002BB}, - {"0000001000010011111010101001010011011110000100100001100010100100",0x000032D2,0xFFFFEB18,0x000004DC,0x00001A01,0xFFFFF95E,0x000002CF,0x00001A01,0xFFFFF95E,0x000002CF}, - {"0000001000010011111100001111110101000010110100000100000010000100",0x00003147,0xFFFFEA3B,0x00000518,0x0000241D,0xFFFFF11C,0x00000431,0x0000241D,0xFFFFF11C,0x00000431}, - {"0000001000010011111010101001010011011110000111000000100100000100",0x00001D44,0xFFFFF7E7,0x0000031A,0x0000153F,0xFFFFFBBC,0x000002A9,0x0000153F,0xFFFFFBBC,0x000002A9}, - {"0000001000010011111100001111110101000010110011000100000100000100",0x00003690,0xFFFFE6E3,0x000005A4,0x000018DE,0xFFFFF908,0x000002DD,0x000018DE,0xFFFFF908,0x000002DD}, - {"0000001000010011111100001111110101000010110011000010000110000100",0x00003561,0xFFFFE6F8,0x000005AB,0x000018B5,0xFFFFF8A0,0x000002F3,0x000018B5,0xFFFFF8A0,0x000002F3}, - {"0000001000010011111010101001010011011110001100100011000100100100",0x000028F4,0xFFFFF23A,0x000003CE,0x00001BC6,0xFFFFF881,0x00000311,0x00001BC6,0xFFFFF881,0x00000311}, - {"0000001000010011111100001111110101000010110100000011000110000100",0x000035D7,0xFFFFE71C,0x0000059B,0x00001D49,0xFFFFF5C8,0x00000368,0x00001D49,0xFFFFF5C8,0x00000368}, - {"0000001000010011111100001111110101000010110011100001100010100100",0x0000397E,0xFFFFE4CB,0x000005F4,0x00001989,0xFFFFF844,0x000002FD,0x00001989,0xFFFFF844,0x000002FD}, - {"0000001000010011111100001111110101000010110001100010000001100100",0x00003BAB,0xFFFFE332,0x0000063F,0x00001A69,0xFFFFF7B9,0x00000312,0x00001A69,0xFFFFF7B9,0x00000312}, - {"0000001000010011111100001111110101000010110100000011000001100100",0x00002F26,0xFFFFEB82,0x000004E8,0x00001D7D,0xFFFFF590,0x00000379,0x00001D7D,0xFFFFF590,0x00000379}, - {"0000001000010011111010101001010011011110000001100011000110100100",0x00002FDC,0xFFFFEBE0,0x000004C3,0x00001940,0xFFFFF8CC,0x000002EE,0x00001940,0xFFFFF8CC,0x000002EE}, - {"0000001000010011111010101001010011011110000111000000100011100100",0x000021B2,0xFFFFF558,0x00000379,0x00001643,0xFFFFFB1C,0x000002C3,0x00001643,0xFFFFFB1C,0x000002C3}, - {"0000001000010011111010101001010011011110001100100001100100000100",0x00002897,0xFFFFF181,0x000003F7,0x00001990,0xFFFFF994,0x000002E2,0x00001990,0xFFFFF994,0x000002E2}, - {"0000001000010011111010101001010011011110000111100000100100100100",0x00001D19,0xFFFFF829,0x0000031A,0x00001558,0xFFFFFBCA,0x000002AF,0x00001558,0xFFFFFBCA,0x000002AF}, - {"0000001000010011111010101001010011011110000001000011000101000100",0x00003311,0xFFFFEAD9,0x000004E1,0x00001BDC,0xFFFFF79E,0x0000031D,0x00001BDC,0xFFFFF79E,0x0000031D}, - {"0000001000010011111010101001010011011110000111100010100111000100",0x00001E54,0xFFFFF740,0x00000333,0x000016A1,0xFFFFFAF0,0x000002C4,0x000016A1,0xFFFFFAF0,0x000002C4}, - {"0000001000010011111100001111110101000010110011100011100101100100",0x00003266,0xFFFFE9A8,0x00000527,0x00002307,0xFFFFF219,0x000003FC,0x00002307,0xFFFFF219,0x000003FC}, - {"0000001000010011111010101001010011011110001100100001000101000100",0x00001D1F,0xFFFFF82B,0x000002F0,0x000013F0,0xFFFFFD0B,0x0000024E,0x000013F0,0xFFFFFD0B,0x0000024E}, - {"0000001000010011111100001111110101000010110001100100100010100100",0x0000312E,0xFFFFEA67,0x00000502,0x0000222A,0xFFFFF253,0x000003F9,0x0000222A,0xFFFFF253,0x000003F9}, - {"0000001000010011111100001111110101000010110010100100000100100100",0x000032B2,0xFFFFE9AD,0x00000523,0x00001E97,0xFFFFF527,0x0000037F,0x00001E97,0xFFFFF527,0x0000037F}, - {"0000001000010011111010101001010011011110000101100100000011100100",0x00001F6A,0xFFFFF6FC,0x00000338,0x0000164B,0xFFFFFB2C,0x000002C2,0x0000164B,0xFFFFFB2C,0x000002C2}, - {"0000001000010011111010101001010011011110000000100010100011000100",0x00002603,0xFFFFF386,0x00000392,0x00001EE0,0xFFFFF601,0x00000369,0x00001EE0,0xFFFFF601,0x00000369}, - {"0000001000010011111010101001010011011110001000000001000101100100",0x00001D0C,0xFFFFF803,0x00000317,0x00001345,0xFFFFFD52,0x00000260,0x00001345,0xFFFFFD52,0x00000260}, - {"0000001000010011111100001111110101000010110011000001100010000100",0x0000327A,0xFFFFE8E5,0x0000055C,0x00001680,0xFFFFFA2D,0x000002B2,0x00001680,0xFFFFFA2D,0x000002B2}, - {"0000001000010011111100001111110101000010110010100011100101100100",0x000032B8,0xFFFFE91A,0x0000054A,0x00001BAB,0xFFFFF6EC,0x00000338,0x00001BAB,0xFFFFF6EC,0x00000338}, - {"0000001000010011111100001111110101000010110011000011000001000100",0x00002F79,0xFFFFEB63,0x000004EF,0x000017BB,0xFFFFF9B1,0x000002CA,0x000017BB,0xFFFFF9B1,0x000002CA}, - {"0000001000010011111010101001010011011110000001000011100011100100",0x00002AE5,0xFFFFEFCB,0x0000041D,0x0000214A,0xFFFFF3A7,0x000003C7,0x0000214A,0xFFFFF3A7,0x000003C7}, - {"0000001000010011111010101001010011011110001100100010000001100100",0x0000212C,0xFFFFF5BC,0x0000034F,0x000017ED,0xFFFFFA4C,0x000002C1,0x000017ED,0xFFFFFA4C,0x000002C1}, - {"0000001000010011111010101001010011011110000100100001000100100100",0x00002BE7,0xFFFFEF40,0x0000043C,0x00001AE2,0xFFFFF8CF,0x000002E3,0x00001AE2,0xFFFFF8CF,0x000002E3}, - {"0000001000010011111100001111110101000010110100000101000101000100",0x000032DC,0xFFFFE90F,0x00000549,0x00002A2D,0xFFFFECC9,0x000004ED,0x00002A2D,0xFFFFECC9,0x000004ED}, - {"0000001000010011111010101001010011011110000101100001100010100100",0x00001DE3,0xFFFFF80D,0x00000319,0x000016FA,0xFFFFFB42,0x000002BC,0x000016FA,0xFFFFFB42,0x000002BC}, - {"0000001000010011111010101001010011011110000111100010100001000100",0x00001F1B,0xFFFFF6DE,0x00000346,0x00001502,0xFFFFFC23,0x00000298,0x00001502,0xFFFFFC23,0x00000298}, - {"0000001000010011111010101001010011011110000001100001100001100100",0x00003203,0xFFFFEA87,0x000004FE,0x0000194E,0xFFFFF8E3,0x000002EC,0x0000194E,0xFFFFF8E3,0x000002EC}, - {"0000001000010011111100001111110101000010110100000010000101000100",0x0000337A,0xFFFFE8DD,0x00000551,0x00001E3C,0xFFFFF534,0x00000385,0x00001E3C,0xFFFFF534,0x00000385}, - {"0000001000010011111100001111110101000010110010100100100001100100",0x000036F6,0xFFFFE62A,0x000005C5,0x000023C0,0xFFFFF117,0x00000435,0x000023C0,0xFFFFF117,0x00000435}, - {"0000001000010011111100001111110101000010110011000010000101000100",0x00003125,0xFFFFEA4E,0x0000051A,0x00001E6C,0xFFFFF503,0x0000038E,0x00001E6C,0xFFFFF503,0x0000038E}, - {"0000001000010011111010101001010011011110000111000000100010100100",0x00001CD4,0xFFFFF82D,0x0000030E,0x0000156D,0xFFFFFB64,0x000002B8,0x0000156D,0xFFFFFB64,0x000002B8}, - {"0000001000010011111010101001010011011110000000100100000010100100",0x00002F14,0xFFFFEC46,0x000004B8,0x000017F1,0xFFFFF977,0x000002D2,0x000017F1,0xFFFFF977,0x000002D2}, - {"0000001000010011111010101001010011011110000001100100000010100100",0x000031F1,0xFFFFEAD4,0x000004ED,0x0000184C,0xFFFFF983,0x000002D4,0x0000184C,0xFFFFF983,0x000002D4}, - {"0000001000010011111100001111110101000010110100000100100110000100",0x00002EA9,0xFFFFEBD7,0x000004D5,0x0000288D,0xFFFFEDDB,0x000004C0,0x0000288D,0xFFFFEDDB,0x000004C0}, - {"0000001000010011111100001111110101000010110010100011100110000100",0x0000335F,0xFFFFE82C,0x00000579,0x00001DBF,0xFFFFF512,0x0000038C,0x00001DBF,0xFFFFF512,0x0000038C}, - {"0000001000010011111010101001010011011110001000000001000110000100",0x0000224F,0xFFFFF4B5,0x00000391,0x0000138C,0xFFFFFCC3,0x0000027A,0x0000138C,0xFFFFFCC3,0x0000027A}, - {"0000001000010011111010101001010011011110000100100100000010100100",0x0000320D,0xFFFFEACD,0x000004F5,0x00001976,0xFFFFF913,0x000002E2,0x00001976,0xFFFFF913,0x000002E2}, - {"0000001000010011111010101001010011011110001000000010000100000100",0x00001BEB,0xFFFFF99C,0x000002E4,0x000016A4,0xFFFFFB77,0x000002C3,0x000016A4,0xFFFFFB77,0x000002C3}, - {"0000001000010011111010101001010011011110000001100011000001000100",0x0000396E,0xFFFFE616,0x000005A9,0x000018F4,0xFFFFF91A,0x000002E3,0x000018F4,0xFFFFF91A,0x000002E3}, - {"0000001000010011111010101001010011011110000000100010100001100100",0x00003251,0xFFFFEA8E,0x000004FA,0x000018EF,0xFFFFF910,0x000002E4,0x000018EF,0xFFFFF910,0x000002E4}, - {"0000001000010011111010101001010011011110000111000001100100100100",0x00001DAF,0xFFFFF857,0x0000030D,0x00001915,0xFFFFF9D8,0x000002F7,0x00001915,0xFFFFF9D8,0x000002F7}, - {"0000001000010011111010101001010011011110001000000100000110100100",0x000025B6,0xFFFFF26B,0x000003E5,0x00001531,0xFFFFFB68,0x000002AF,0x00001531,0xFFFFFB68,0x000002AF}, - {"0000001000010011111010101001010011011110000001100001100010000100",0x00002B2E,0xFFFFEF2E,0x00000440,0x00001968,0xFFFFF91A,0x000002DF,0x00001968,0xFFFFF91A,0x000002DF}, - {"0000001000010011111010101001010011011110000111000010000001100100",0x00002305,0xFFFFF528,0x00000377,0x000018A4,0xFFFFF9EB,0x000002F0,0x000018A4,0xFFFFF9EB,0x000002F0}, - {"0000001000010011111100001111110101000010110010100100000011000100",0x000032A1,0xFFFFE992,0x0000052E,0x00001A55,0xFFFFF826,0x000002FE,0x00001A55,0xFFFFF826,0x000002FE}, - {"0000001000010011111010101001010011011110000001000010000110000100",0x00002CCD,0xFFFFEE35,0x00000462,0x00001B09,0xFFFFF7E6,0x0000030F,0x00001B09,0xFFFFF7E6,0x0000030F}, - {"0000001000010011111010101001010011011110001100100011000010000100",0x00002602,0xFFFFF2CF,0x000003C5,0x000016EE,0xFFFFFAD4,0x000002B4,0x000016EE,0xFFFFFAD4,0x000002B4}, - {"0000001000010011111100001111110101000010110100000001100101100100",0x00003370,0xFFFFE891,0x00000560,0x000017F0,0xFFFFF930,0x000002DF,0x000017F0,0xFFFFF930,0x000002DF}, - {"0000001000010011111100001111110101000010110010100001100010000100",0x00002EDC,0xFFFFEB6D,0x000004EC,0x000016E6,0xFFFFF9ED,0x000002BC,0x000016E6,0xFFFFF9ED,0x000002BC}, - {"0000001000010011111010101001010011011110000100100010100011000100",0x00002A05,0xFFFFF13D,0x000003F0,0x00002065,0xFFFFF57B,0x00000378,0x00002065,0xFFFFF57B,0x00000378}, - {"0000001000010011111100001111110101000010110011100010000001000100",0x00002F8A,0xFFFFEB6E,0x000004E4,0x00001E3E,0xFFFFF50E,0x0000038D,0x00001E3E,0xFFFFF50E,0x0000038D}, - {"0000001000010011111100001111110101000010110010100011000001000100",0x00002BB5,0xFFFFED6A,0x000004A1,0x000017BF,0xFFFFF937,0x000002E5,0x000017BF,0xFFFFF937,0x000002E5}, - {"0000001000010011111010101001010011011110001000000001100101100100",0x0000202C,0xFFFFF6CE,0x0000033F,0x000015EE,0xFFFFFB83,0x000002B9,0x000015EE,0xFFFFFB83,0x000002B9}, - {"0000001000010011111010101001010011011110000000100010100010000100",0x00002C0C,0xFFFFEF10,0x0000043F,0x00001A73,0xFFFFF83E,0x0000030C,0x00001A73,0xFFFFF83E,0x0000030C}, - {"0000001000010011111010101001010011011110001100100100000100000100",0x0000234F,0xFFFFF460,0x00000385,0x000018C3,0xFFFFF9A5,0x000002DD,0x000018C3,0xFFFFF9A5,0x000002DD}, - {"0000001000010011111100001111110101000010110011100001100100000100",0x00003679,0xFFFFE704,0x00000595,0x00002177,0xFFFFF31A,0x000003D7,0x00002177,0xFFFFF31A,0x000003D7}, - {"0000001000010011111100001111110101000010110010100010100100100100",0x00003008,0xFFFFEBB8,0x000004D5,0x000024FF,0xFFFFF112,0x00000430,0x000024FF,0xFFFFF112,0x00000430}, - {"0000001000010011111100001111110101000010110001100100000110100100",0x00003848,0xFFFFE6A3,0x00000594,0x00002958,0xFFFFEE37,0x000004A0,0x00002958,0xFFFFEE37,0x000004A0}, - {"0000001000010011111100001111110101000010110011000001100100100100",0x00002FDF,0xFFFFEB08,0x000004FD,0x00001D77,0xFFFFF58B,0x0000037A,0x00001D77,0xFFFFF58B,0x0000037A}, - {"0000001000010011111010101001010011011110000001100011000001100100",0x00002EC8,0xFFFFED41,0x00000481,0x00001949,0xFFFFF91C,0x000002DF,0x00001949,0xFFFFF91C,0x000002DF}, - {"0000001000010011111100001111110101000010110100000100000110100100",0x000037C1,0xFFFFE5BA,0x000005D7,0x0000252C,0xFFFFF023,0x00000460,0x0000252C,0xFFFFF023,0x00000460}, - {"0000001000010011111100001111110101000010110011100010100101000100",0x00003716,0xFFFFE70C,0x0000058A,0x000028CC,0xFFFFEE57,0x0000049D,0x000028CC,0xFFFFEE57,0x0000049D}, - {"0000001000010011111100001111110101000010110010100100000011100100",0x000033D1,0xFFFFE8E8,0x00000547,0x00001AB1,0xFFFFF7E5,0x00000309,0x00001AB1,0xFFFFF7E5,0x00000309}, - {"0000001000010011111100001111110101000010110011000010100101000100",0x00002D72,0xFFFFED65,0x0000048E,0x00001E0D,0xFFFFF5A7,0x00000370,0x00001E0D,0xFFFFF5A7,0x00000370}, - {"0000001000010011111010101001010011011110000111000011100110100100",0x00002292,0xFFFFF49F,0x00000393,0x000017F4,0xFFFFF9CD,0x000002F5,0x000017F4,0xFFFFF9CD,0x000002F5}, - {"0000001000010011111010101001010011011110001001000011000001000100",0x000026EE,0xFFFFF18C,0x000003F7,0x000018A7,0xFFFFF95A,0x000002E5,0x000018A7,0xFFFFF95A,0x000002E5}, - {"0000001000010011111010101001010011011110000001000010000101100100",0x00002F62,0xFFFFEC9B,0x000004A4,0x0000194E,0xFFFFF932,0x000002D9,0x0000194E,0xFFFFF932,0x000002D9}, - {"0000001000010011111010101001010011011110000111100011100110000100",0x00001CE8,0xFFFFF7FA,0x0000031C,0x000014CE,0xFFFFFBD4,0x000002AB,0x000014CE,0xFFFFFBD4,0x000002AB}, - {"0000001000010011111010101001010011011110000100100001000011100100",0x00002E5A,0xFFFFEDAB,0x0000047C,0x00001A82,0xFFFFF8F7,0x000002DE,0x00001A82,0xFFFFF8F7,0x000002DE}, - {"0000001000010011111100001111110101000010110011000011000011100100",0x00003057,0xFFFFEC34,0x000004B9,0x00002296,0xFFFFF342,0x000003D0,0x00002296,0xFFFFF342,0x000003D0}, - {"0000001000010011111010101001010011011110000001000001100010100100",0x00002B0F,0xFFFFEF58,0x00000434,0x00001BFD,0xFFFFF721,0x00000330,0x00001BFD,0xFFFFF721,0x00000330}, - {"0000001000010011111010101001010011011110001000000001000010100100",0x00001F01,0xFFFFF751,0x0000032F,0x00001502,0xFFFFFC3E,0x00000296,0x00001502,0xFFFFFC3E,0x00000296}, - {"0000001000010011111100001111110101000010110010100011000001100100",0x00002FF4,0xFFFFEAE2,0x00000503,0x00001B36,0xFFFFF736,0x00000330,0x00001B36,0xFFFFF736,0x00000330}, - {"0000001000010011111100001111110101000010110011100010000001100100",0x00003762,0xFFFFE5AB,0x000005DE,0x000018CB,0xFFFFF896,0x000002F4,0x000018CB,0xFFFFF896,0x000002F4}, - {"0000001000010011111100001111110101000010110011000010000001100100",0x00002890,0xFFFFEF92,0x00000445,0x0000191D,0xFFFFF86F,0x00000302,0x0000191D,0xFFFFF86F,0x00000302}, - {"0000001000010011111010101001010011011110000001000011000001100100",0x00002F76,0xFFFFEC0E,0x000004BF,0x00001F7D,0xFFFFF41A,0x000003C0,0x00001F7D,0xFFFFF41A,0x000003C0}, - {"0000001000010011111010101001010011011110000111100000100010100100",0x00001D55,0xFFFFF7F8,0x0000031E,0x000015DF,0xFFFFFB79,0x000002B7,0x000015DF,0xFFFFFB79,0x000002B7}, - {"0000001000010011111010101001010011011110001000000100100100100100",0x00001FE9,0xFFFFF64A,0x00000353,0x000019E8,0xFFFFF882,0x0000032A,0x000019E8,0xFFFFF882,0x0000032A}, - {"0000001000010011111010101001010011011110000001100011100101100100",0x000030B5,0xFFFFEBB8,0x000004C4,0x00001857,0xFFFFF968,0x000002D8,0x00001857,0xFFFFF968,0x000002D8}, - {"0000001000010011111100001111110101000010110010100010100011000100",0x00003398,0xFFFFE9A3,0x00000524,0x00001FF9,0xFFFFF458,0x000003AD,0x00001FF9,0xFFFFF458,0x000003AD}, - {"0000001000010011111100001111110101000010110011100010100101100100",0x00003897,0xFFFFE5BD,0x000005C8,0x00002519,0xFFFFF0BA,0x00000438,0x00002519,0xFFFFF0BA,0x00000438}, - {"0000001000010011111100001111110101000010110100000100000001100100",0x00003234,0xFFFFE9B1,0x00000530,0x000022CC,0xFFFFF20E,0x00000409,0x000022CC,0xFFFFF20E,0x00000409}, - {"0000001000010011111010101001010011011110001000000101000100000100",0x00001FD2,0xFFFFF641,0x00000354,0x000017C9,0xFFFFF9C0,0x000002FB,0x000017C9,0xFFFFF9C0,0x000002FB}, - {"0000001000010011111100001111110101000010110011100100100011100100",0x00003234,0xFFFFE946,0x0000053D,0x00002267,0xFFFFF1F5,0x0000040D,0x00002267,0xFFFFF1F5,0x0000040D}, - {"0000001000010011111010101001010011011110001000000010100110100100",0x00002330,0xFFFFF474,0x00000399,0x00001490,0xFFFFFC67,0x00000288,0x00001490,0xFFFFFC67,0x00000288}, - {"0000001000010011111100001111110101000010110100000011100100100100",0x000032A3,0xFFFFE9EB,0x0000051B,0x0000234D,0xFFFFF23C,0x000003F7,0x0000234D,0xFFFFF23C,0x000003F7}, - {"0000001000010011111010101001010011011110001000000000100100000100",0x0000217E,0xFFFFF53A,0x00000384,0x00001511,0xFFFFFBF5,0x0000029E,0x00001511,0xFFFFFBF5,0x0000029E}, - {"0000001000010011111100001111110101000010110011100101000011100100",0x0000384F,0xFFFFE562,0x000005E2,0x0000295A,0xFFFFED53,0x000004D3,0x0000295A,0xFFFFED53,0x000004D3}, - {"0000001000010011111100001111110101000010110100000101000100100100",0x00003315,0xFFFFE8D1,0x00000552,0x000025D1,0xFFFFEFAF,0x00000471,0x000025D1,0xFFFFEFAF,0x00000471}, - {"0000001000010011111100001111110101000010110001100100100100100100",0x00004183,0xFFFFDF61,0x000006DA,0x0000193C,0xFFFFF88F,0x000002EC,0x0000193C,0xFFFFF88F,0x000002EC}, - {"0000001000010011111010101001010011011110001001000010000101100100",0x00002DFC,0xFFFFEDF2,0x0000047A,0x00001755,0xFFFFFAC2,0x000002AC,0x00001755,0xFFFFFAC2,0x000002AC}, - {"0000001000010011111100001111110101000010110010100011000110100100",0x000033FE,0xFFFFE774,0x0000059F,0x00001E70,0xFFFFF492,0x000003A0,0x00001E70,0xFFFFF492,0x000003A0}, - {"0000001000010011111100001111110101000010110001100010100110100100",0x000040D7,0xFFFFDFB8,0x000006CE,0x00001AC8,0xFFFFF773,0x0000031D,0x00001AC8,0xFFFFF773,0x0000031D}, - {"0000001000010011111010101001010011011110000111100001000101100100",0x00001D02,0xFFFFF803,0x00000322,0x000015FE,0xFFFFFB71,0x000002BB,0x000015FE,0xFFFFFB71,0x000002BB}, - {"0000001000010011111100001111110101000010110100000010100010000100",0x00002EB0,0xFFFFEC31,0x000004C4,0x00001B3C,0xFFFFF73B,0x00000330,0x00001B3C,0xFFFFF73B,0x00000330}, - {"0000001000010011111100001111110101000010110010100100100110000100",0x00002D9F,0xFFFFECBF,0x000004A8,0x000022B0,0xFFFFF23C,0x000003F9,0x000022B0,0xFFFFF23C,0x000003F9}, - {"0000001000010011111100001111110101000010110011000001100011100100",0x00002C6A,0xFFFFEDAC,0x00000488,0x00002419,0xFFFFF159,0x00000427,0x00002419,0xFFFFF159,0x00000427}, - {"0000001000010011111010101001010011011110000100100001000010100100",0x00002991,0xFFFFF06C,0x0000040E,0x00001AA9,0xFFFFF8D0,0x000002E1,0x00001AA9,0xFFFFF8D0,0x000002E1}, - {"0000001000010011111010101001010011011110000100100011100100000100",0x00002F8E,0xFFFFED1B,0x00000493,0x00001DE4,0xFFFFF69C,0x00000347,0x00001DE4,0xFFFFF69C,0x00000347}, - {"0000001000010011111010101001010011011110001000000100000110000100",0x00002136,0xFFFFF540,0x0000037C,0x000014FF,0xFFFFFB83,0x000002B2,0x000014FF,0xFFFFFB83,0x000002B2}, - {"0000001000010011111010101001010011011110000001100001100011100100",0x0000354C,0xFFFFE97D,0x0000051A,0x00001906,0xFFFFF965,0x000002DD,0x00001906,0xFFFFF965,0x000002DD}, - {"0000001000010011111100001111110101000010110001100010000011000100",0x0000348B,0xFFFFE94D,0x0000051F,0x0000285B,0xFFFFEF1A,0x00000473,0x0000285B,0xFFFFEF1A,0x00000473}, - {"0000001000010011111010101001010011011110001100100001100010100100",0x000026E6,0xFFFFF24E,0x000003D6,0x0000141F,0xFFFFFCCE,0x00000260,0x0000141F,0xFFFFFCCE,0x00000260}, - {"0000001000010011111100001111110101000010110001100100000101100100",0x00003CED,0xFFFFE2A5,0x0000064E,0x00002060,0xFFFFF3E0,0x000003B0,0x00002060,0xFFFFF3E0,0x000003B0}, - {"0000001000010011111010101001010011011110000000100001000010000100",0x000029D4,0xFFFFEFF7,0x00000426,0x00001976,0xFFFFF8E1,0x000002EE,0x00001976,0xFFFFF8E1,0x000002EE}, - {"0000001000010011111100001111110101000010110010100100000010100100",0x00003767,0xFFFFE601,0x000005CC,0x00001D22,0xFFFFF5F4,0x00000361,0x00001D22,0xFFFFF5F4,0x00000361}, - {"0000001000010011111100001111110101000010110001100101000011000100",0x00003CE8,0xFFFFE2E8,0x00000637,0x0000232C,0xFFFFF1E7,0x00000405,0x0000232C,0xFFFFF1E7,0x00000405}, - {"0000001000010011111010101001010011011110001000000001000001100100",0x000023A8,0xFFFFF4CD,0x00000386,0x00001944,0xFFFFF983,0x00000300,0x00001944,0xFFFFF983,0x00000300}, - {"0000001000010011111100001111110101000010110011000011000010100100",0x00003451,0xFFFFE8B9,0x00000551,0x00001AD7,0xFFFFF7BF,0x00000318,0x00001AD7,0xFFFFF7BF,0x00000318}, - {"0000001000010011111100001111110101000010110011100010100110000100",0x0000381B,0xFFFFE5A0,0x000005D0,0x00001E0F,0xFFFFF521,0x00000382,0x00001E0F,0xFFFFF521,0x00000382}, - {"0000001000010011111010101001010011011110001000000011100011000100",0x000023A4,0xFFFFF4A6,0x00000394,0x0000171F,0xFFFFFABB,0x000002D9,0x0000171F,0xFFFFFABB,0x000002D9}, - {"0000001000010011111100001111110101000010110001100010000010100100",0x00003C2B,0xFFFFE447,0x000005F0,0x0000207F,0xFFFFF44E,0x0000039A,0x0000207F,0xFFFFF44E,0x0000039A}, - {"0000001000010011111100001111110101000010110011000011100110000100",0x00002F07,0xFFFFEB70,0x000004E9,0x00001765,0xFFFFF9A5,0x000002C6,0x00001765,0xFFFFF9A5,0x000002C6}, - {"0000001000010011111100001111110101000010110001100010100110000100",0x00003A01,0xFFFFE4E0,0x000005E7,0x0000227A,0xFFFFF292,0x000003E5,0x0000227A,0xFFFFF292,0x000003E5}, - {"0000001000010011111100001111110101000010110011100010000010100100",0x0000376E,0xFFFFE686,0x000005A6,0x00001FCF,0xFFFFF43B,0x000003A8,0x00001FCF,0xFFFFF43B,0x000003A8}, - {"0000001000010011111100001111111111101111010110100100100110000100",0x0000485F,0xFFFFDCC1,0x00000713,0x00002CF8,0xFFFFEC45,0x000004DA,0x00002CF8,0xFFFFEC45,0x000004DA}, - {"0000001000010011111100001111111111101111010111000011000110000100",0x0000331C,0xFFFFE8FF,0x00000541,0x00002366,0xFFFFF19D,0x00000411,0x00002366,0xFFFFF19D,0x00000411}, - {"0000001000010011111100001111111111101111011001000011100001100100",0x00003CF3,0xFFFFE15A,0x00000694,0x00002FB3,0xFFFFE827,0x000005B9,0x00002FB3,0xFFFFE827,0x000005B9}, - {"0000001000010011111010101001010011011110001100100001000100000100",0x000023F3,0xFFFFF3EA,0x0000039A,0x00001345,0xFFFFFD6B,0x00000241,0x00001345,0xFFFFFD6B,0x00000241}, - {"0000001000010011111100001111111111101111010111000010100010100100",0x000038C0,0xFFFFE58A,0x000005CC,0x000023CA,0xFFFFF1AA,0x00000408,0x000023CA,0xFFFFF1AA,0x00000408}, - {"0000001000010011111100001111111111101111011001100010100101000100",0x00004976,0xFFFFDD6A,0x000006D7,0x000033C6,0xFFFFE8EB,0x0000054D,0x000033C6,0xFFFFE8EB,0x0000054D}, - {"0000001000010011111100001111111111101111011001000100100100000100",0x00004049,0xFFFFDF6D,0x000006D8,0x00003129,0xFFFFE716,0x000005E9,0x00003129,0xFFFFE716,0x000005E9}, - {"0000001000010011111100001111111111101111011001100001000101100100",0x000046C2,0xFFFFDCEB,0x0000071C,0x00002E6D,0xFFFFEA8F,0x0000052E,0x00002E6D,0xFFFFEA8F,0x0000052E}, - {"0000001000010011111100001111111111101111011000100011100010100100",0x00004080,0xFFFFE1E1,0x0000063A,0x0000396D,0xFFFFE40A,0x0000062C,0x0000396D,0xFFFFE40A,0x0000062C}, - {"0000001000010011111100001111111111101111010111100010000100100100",0x00003DE0,0xFFFFE358,0x0000060C,0x00002AA2,0xFFFFEDBF,0x000004A0,0x00002AA2,0xFFFFEDBF,0x000004A0}, - {"0000001000010011111100001111111111101111010111100011000101000100",0x00003FC0,0xFFFFE2A1,0x0000061A,0x000027D8,0xFFFFEFEC,0x0000043A,0x000027D8,0xFFFFEFEC,0x0000043A}, - {"0000001000010011111100001111111111101111011001100001100100100100",0x00003FBF,0xFFFFE2F5,0x00000603,0x000032D7,0xFFFFE900,0x00000552,0x000032D7,0xFFFFE900,0x00000552}, - {"0000001000010011111100001111111111101111010111000001000011100100",0x000035EE,0xFFFFE6CA,0x000005A2,0x0000247C,0xFFFFF088,0x00000446,0x0000247C,0xFFFFF088,0x00000446}, - {"0000001000010011111100001111111111101111011001000011100010000100",0x000039C8,0xFFFFE3AE,0x0000062A,0x000028AF,0xFFFFED24,0x000004DF,0x000028AF,0xFFFFED24,0x000004DF}, - {"0000001000010011111100001111111111101111010111000010100010000100",0x00003BDE,0xFFFFE33B,0x00000632,0x00001B6C,0xFFFFF720,0x00000326,0x00001B6C,0xFFFFF720,0x00000326}, - {"0000001000010011111100001111111111101111011100100001000010100100",0x00003818,0xFFFFE57D,0x000005D4,0x000020EF,0xFFFFF327,0x000003CE,0x000020EF,0xFFFFF327,0x000003CE}, - {"0000001000010011111100001111111111101111010111100001100110100100",0x000038DA,0xFFFFE561,0x000005D3,0x0000297D,0xFFFFED6D,0x000004C5,0x0000297D,0xFFFFED6D,0x000004C5}, - {"0000001000010011111100001111111111101111011010000100100010000100",0x000027AC,0xFFFFF0CE,0x00000417,0x00001F5F,0xFFFFF484,0x000003B2,0x00001F5F,0xFFFFF484,0x000003B2}, - {"0000001000010011111100001111111111101111011001100100100010100100",0x00003F02,0xFFFFE222,0x00000643,0x000026D4,0xFFFFF000,0x00000443,0x000026D4,0xFFFFF000,0x00000443}, - {"0000001000010011111100001111111111101111011000100100000101100100",0x00004303,0xFFFFDFE3,0x00000690,0x0000312C,0xFFFFE912,0x00000561,0x0000312C,0xFFFFE912,0x00000561}, - {"0000001000010011111100001111111111101111011000000000100100000100",0x000039E5,0xFFFFE31F,0x00000657,0x00001D23,0xFFFFF51F,0x00000386,0x00001D23,0xFFFFF51F,0x00000386}, - {"0000001000010011111100001111111111101111011001100001000101000100",0x000041FA,0xFFFFE01B,0x00000697,0x00002767,0xFFFFEF90,0x00000455,0x00002767,0xFFFFEF90,0x00000455}, - {"0000001000010011111100001111111111101111011010000011000010100100",0x00002888,0xFFFFF11C,0x00000403,0x00001864,0xFFFFF9D8,0x000002D3,0x00001864,0xFFFFF9D8,0x000002D3}, - {"0000001000010011111010101001010011011110001000000001100001100100",0x0000215C,0xFFFFF5B6,0x0000036D,0x000015C5,0xFFFFFB8A,0x000002B5,0x000015C5,0xFFFFFB8A,0x000002B5}, - {"0000001000010011111100001111111111101111011010000011100110000100",0x00002FAF,0xFFFFEC27,0x000004CA,0x00002184,0xFFFFF39C,0x000003CD,0x00002184,0xFFFFF39C,0x000003CD}, - {"0000001000010011111100001111111111101111010111100001000011000100",0x00004ACE,0xFFFFD9A3,0x000007BC,0x00001A5D,0xFFFFF7F6,0x000002FC,0x00001A5D,0xFFFFF7F6,0x000002FC}, - {"0000001000010011111100001111111111101111010110100011000001000100",0x00003763,0xFFFFE797,0x0000055F,0x000029B5,0xFFFFEEA1,0x00000474,0x000029B5,0xFFFFEEA1,0x00000474}, - {"0000001000010011111100001111111111101111010111100011000101100100",0x00003832,0xFFFFE6F9,0x00000575,0x00002C99,0xFFFFEC42,0x000004E3,0x00002C99,0xFFFFEC42,0x000004E3}, - {"0000001000010011111100001111111111101111011000000100000101100100",0x000041C9,0xFFFFDE33,0x0000071E,0x0000199D,0xFFFFF808,0x000002F9,0x0000199D,0xFFFFF808,0x000002F9}, - {"0000001000010011111100001111111111101111011001000001000101100100",0x0000474A,0xFFFFD96E,0x00000802,0x00002A30,0xFFFFEB57,0x0000053F,0x00002A30,0xFFFFEB57,0x0000053F}, - {"0000001000010011111100001111111111101111010111000011000111000100",0x0000312F,0xFFFFEA6A,0x00000508,0x000029D3,0xFFFFED38,0x000004D3,0x000029D3,0xFFFFED38,0x000004D3}, - {"0000001000010011111100001111111111101111011100100001000011000100",0x00003BD6,0xFFFFE2E7,0x00000644,0x00002093,0xFFFFF37B,0x000003BD,0x00002093,0xFFFFF37B,0x000003BD}, - {"0000001000010011111100001111111111101111011010000100000011100100",0x00002F94,0xFFFFECD4,0x000004A3,0x00002196,0xFFFFF40B,0x000003B5,0x00002196,0xFFFFF40B,0x000003B5}, - {"0000001000010011111100001111111111101111010111100001100101000100",0x0000369B,0xFFFFE762,0x00000571,0x00002726,0xFFFFEF99,0x00000459,0x00002726,0xFFFFEF99,0x00000459}, - {"0000001000010011111100001111111111101111011001000010000001100100",0x00003F57,0xFFFFDF47,0x000006F4,0x00002E5F,0xFFFFE8AE,0x000005AB,0x00002E5F,0xFFFFE8AE,0x000005AB}, - {"0000001000010011111010101001010011011110000010100100000011000100",0x00004313,0xFFFFDD81,0x0000072D,0x00002468,0xFFFFF068,0x00000440,0x00002468,0xFFFFF068,0x00000440}, - {"0000001000010011111100001111111111101111011010000011000001000100",0x00002A35,0xFFFFEFA8,0x00000441,0x00001F3F,0xFFFFF4F3,0x000003A0,0x00001F3F,0xFFFFF4F3,0x000003A0}, - {"0000001000010011111100001111111111101111011001100011000010100100",0x00003E33,0xFFFFE4B0,0x000005AF,0x00002802,0xFFFFF092,0x00000412,0x00002802,0xFFFFF092,0x00000412}, - {"0000001000010011111010101001010011011110001100100011100100000100",0x00002815,0xFFFFF20E,0x000003DD,0x00001C33,0xFFFFF7D5,0x0000032A,0x00001C33,0xFFFFF7D5,0x0000032A}, - {"0000001000010011111100001111111111101111010110100010000110000100",0x00003CC2,0xFFFFE43E,0x000005DE,0x00002C16,0xFFFFECED,0x000004BA,0x00002C16,0xFFFFECED,0x000004BA}, - {"0000001000010011111100001111111111101111010111000100000010000100",0x00003CFA,0xFFFFE1EE,0x00000673,0x00001F7D,0xFFFFF402,0x000003AE,0x00001F7D,0xFFFFF402,0x000003AE}, - {"0000001000010011111100001111111111101111011000100010000100000100",0x0000486E,0xFFFFDD43,0x000006EE,0x000036F0,0xFFFFE609,0x000005D5,0x000036F0,0xFFFFE609,0x000005D5}, - {"0000001000010011111100001111111111101111010111000100100101100100",0x000039FE,0xFFFFE41F,0x00000613,0x0000266C,0xFFFFEF35,0x0000047D,0x0000266C,0xFFFFEF35,0x0000047D}, - {"0000001000010011111010101001010011011110000100100011000100100100",0x00002EA4,0xFFFFEE3B,0x00000462,0x00002126,0xFFFFF4E2,0x0000038F,0x00002126,0xFFFFF4E2,0x0000038F}, - {"0000001000010011111100001111111111101111011010000011100101000100",0x00002D2E,0xFFFFEE7B,0x00000462,0x0000229D,0xFFFFF363,0x000003D4,0x0000229D,0xFFFFF363,0x000003D4}, - {"0000001000010011111100001111111111101111010111100010100001000100",0x0000375C,0xFFFFE695,0x0000059D,0x00002319,0xFFFFF237,0x000003EE,0x00002319,0xFFFFF237,0x000003EE}, - {"0000001000010011111100001111111111101111011100100101000011000100",0x00004522,0xFFFFDC71,0x0000075E,0x0000247E,0xFFFFF0A0,0x0000043C,0x0000247E,0xFFFFF0A0,0x0000043C}, - {"0000001000010011111010101001010011011110000100100100100011100100",0x00002E58,0xFFFFECB9,0x000004A9,0x0000199A,0xFFFFF8CF,0x000002E9,0x0000199A,0xFFFFF8CF,0x000002E9}, - {"0000001000010011111100001111111111101111011001000011100011100100",0x00003791,0xFFFFE5FE,0x000005B6,0x000029F5,0xFFFFED0D,0x000004CD,0x000029F5,0xFFFFED0D,0x000004CD}, - {"0000001000010011111010101001010011011110001001000100000101000100",0x00002E9E,0xFFFFEC8D,0x000004C1,0x000019D0,0xFFFFF869,0x0000030F,0x000019D0,0xFFFFF869,0x0000030F}, - {"0000001000010011111010101001010011011110001000000011100101100100",0x0000237C,0xFFFFF435,0x000003A6,0x000014EB,0xFFFFFBC4,0x000002AF,0x000014EB,0xFFFFFBC4,0x000002AF}, - {"0000001000010011111100001111111111101111011001100010100100100100",0x00003FE5,0xFFFFE4A2,0x000005A0,0x00003416,0xFFFFE995,0x00000523,0x00003416,0xFFFFE995,0x00000523}, - {"0000001000010011111100001111111111101111010111000000100100100100",0x00002B27,0xFFFFED51,0x000004A5,0x000025D1,0xFFFFEF18,0x00000492,0x000025D1,0xFFFFEF18,0x00000492}, - {"0000001000010011111100001111111111101111011010000100100100000100",0x00002D77,0xFFFFED79,0x00000494,0x00002196,0xFFFFF352,0x000003DE,0x00002196,0xFFFFF352,0x000003DE}, - {"0000001000010011111100001111111111101111010111000010000011000100",0x00003750,0xFFFFE6AC,0x00000596,0x00002524,0xFFFFF0B5,0x00000431,0x00002524,0xFFFFF0B5,0x00000431}, - {"0000001000010011111010101001010011011110000100100010100101000100",0x00002896,0xFFFFF1BB,0x000003D9,0x00001CE0,0xFFFFF753,0x0000032F,0x00001CE0,0xFFFFF753,0x0000032F}, - {"0000001000010011111100001111111111101111011001000001100110000100",0x00003CA7,0xFFFFE0F7,0x000006B1,0x00002CB8,0xFFFFE9AB,0x00000587,0x00002CB8,0xFFFFE9AB,0x00000587}, - {"0000001000010011111010101001010011011110001100100010100001100100",0x00002513,0xFFFFF323,0x000003BC,0x00001965,0xFFFFF93C,0x000002F0,0x00001965,0xFFFFF93C,0x000002F0}, - {"0000001000010011111100001111111111101111011001100010000101100100",0x00003914,0xFFFFE683,0x00000586,0x00003120,0xFFFFE9A6,0x00000543,0x00003120,0xFFFFE9A6,0x00000543}, - {"0000001000010011111100001111111111101111011001000011100100000100",0x000040D0,0xFFFFE007,0x000006AC,0x00002B9E,0xFFFFEBF5,0x000004FB,0x00002B9E,0xFFFFEBF5,0x000004FB}, - {"0000001000010011111100001111111111101111010110100100100010000100",0x00004412,0xFFFFDF5F,0x000006A9,0x00002A9E,0xFFFFEDCE,0x00000498,0x00002A9E,0xFFFFEDCE,0x00000498}, - {"0000001000010011111100001111111111101111011000100100100010000100",0x000042A6,0xFFFFDFEF,0x00000696,0x00002E65,0xFFFFEAAE,0x00000529,0x00002E65,0xFFFFEAAE,0x00000529}, - {"0000001000010011111010101001010011011110001100100010000100100100",0x000022E8,0xFFFFF565,0x0000035F,0x00001890,0xFFFFFA61,0x000002C6,0x00001890,0xFFFFFA61,0x000002C6}, - {"0000001000010011111100001111111111101111011000100011100110100100",0x00004637,0xFFFFDDD8,0x000006E9,0x0000349D,0xFFFFE6C8,0x000005C7,0x0000349D,0xFFFFE6C8,0x000005C7}, - {"0000001000010011111010101001010011011110001001100011100100000100",0x00004686,0xFFFFDC58,0x0000073D,0x00003972,0xFFFFE27B,0x0000068E,0x00003972,0xFFFFE27B,0x0000068E}, - {"0000001000010011111100001111111111101111011010000000100011100100",0x00002B35,0xFFFFEE9C,0x0000046C,0x00001F5B,0xFFFFF4A3,0x000003A9,0x00001F5B,0xFFFFF4A3,0x000003A9}, - {"0000001000010011111100001111111111101111011100100100000101000100",0x00003AC9,0xFFFFE3B2,0x0000061B,0x000023A1,0xFFFFF170,0x0000040F,0x000023A1,0xFFFFF170,0x0000040F}, - {"0000001000010011111100001111111111101111010111100001100010000100",0x00003C50,0xFFFFE37E,0x00000617,0x0000218F,0xFFFFF339,0x000003C4,0x0000218F,0xFFFFF339,0x000003C4}, - {"0000001000010011111100001111111111101111011001100011000001000100",0x00003793,0xFFFFE761,0x0000055D,0x000029C7,0xFFFFEE03,0x00000496,0x000029C7,0xFFFFEE03,0x00000496}, - {"0000001000010011111100001111111111101111011001000011100010100100",0x000040B5,0xFFFFDF78,0x000006DA,0x00002DED,0xFFFFEA20,0x00000551,0x00002DED,0xFFFFEA20,0x00000551}, - {"0000001000010011111100001111111111101111011000000001000101000100",0x000039D6,0xFFFFE37D,0x0000063C,0x00001AED,0xFFFFF6E2,0x00000331,0x00001AED,0xFFFFF6E2,0x00000331}, - {"0000001000010011111100001111111111101111011001100010000101000100",0x0000431F,0xFFFFE09B,0x0000066A,0x00002BDF,0xFFFFED93,0x00000496,0x00002BDF,0xFFFFED93,0x00000496}, - {"0000001000010011111100001111111111101111011000100011100001100100",0x00004887,0xFFFFDC65,0x00000721,0x00003669,0xFFFFE5C4,0x000005E9,0x00003669,0xFFFFE5C4,0x000005E9}, - {"0000001000010011111100001111111111101111011001000000100100100100",0x00004120,0xFFFFDDAE,0x00000748,0x0000303B,0xFFFFE70D,0x000005FC,0x0000303B,0xFFFFE70D,0x000005FC}, - {"0000001000010011111100001111111111101111010111100010100010100100",0x0000415D,0xFFFFE0BE,0x0000067B,0x00002FA7,0xFFFFEA28,0x00000538,0x00002FA7,0xFFFFEA28,0x00000538}, - {"0000001000010011111100001111111111101111011010000001100100000100",0x00002B12,0xFFFFEFF9,0x00000428,0x00001DDA,0xFFFFF693,0x00000356,0x00001DDA,0xFFFFF693,0x00000356}, - {"0000001000010011111100001111111111101111010111100011000110000100",0x00003ED3,0xFFFFE28D,0x0000062D,0x00002B00,0xFFFFED4E,0x000004B3,0x00002B00,0xFFFFED4E,0x000004B3}, - {"0000001000010011111100001111111111101111011000100101000010100100",0x00004218,0xFFFFE039,0x0000068F,0x00002F84,0xFFFFEA0C,0x00000541,0x00002F84,0xFFFFEA0C,0x00000541}, - {"0000001000010011111100001111111111101111010110100011100001000100",0x00003FF5,0xFFFFE2A3,0x00000617,0x00003017,0xFFFFEA7A,0x00000520,0x00003017,0xFFFFEA7A,0x00000520}, - {"0000001000010011111100001111111111101111010110100000100010100100",0x00004304,0xFFFFDFCC,0x0000069E,0x00002E0C,0xFFFFEB51,0x00000505,0x00002E0C,0xFFFFEB51,0x00000505}, - {"0000001000010011111100001111111111101111011001000001100101000100",0x00003D3A,0xFFFFE17F,0x00000687,0x0000284C,0xFFFFED83,0x000004CD,0x0000284C,0xFFFFED83,0x000004CD}, - {"0000001000010011111100001111111111101111010111100100000010100100",0x000042F5,0xFFFFDF76,0x000006B2,0x000027B6,0xFFFFEF72,0x00000455,0x000027B6,0xFFFFEF72,0x00000455}, - {"0000001000010011111100001111111111101111010111000011100011000100",0x00004267,0xFFFFDF29,0x000006D5,0x0000298F,0xFFFFEDBD,0x000004AC,0x0000298F,0xFFFFEDBD,0x000004AC}, - {"0000001000010011111010101001010011011110001001000000100100100100",0x0000303E,0xFFFFEC00,0x000004CB,0x000021CD,0xFFFFF36E,0x000003D6,0x000021CD,0xFFFFF36E,0x000003D6}, - {"0000001000010011111100001111111111101111010111100010100011000100",0x00003127,0xFFFFEBDB,0x000004A6,0x00002E95,0xFFFFEB78,0x000004F3,0x00002E95,0xFFFFEB78,0x000004F3}, - {"0000001000010011111010101001010011011110000111000001000001100100",0x00002655,0xFFFFF2D9,0x000003CF,0x000019F5,0xFFFFF8E7,0x00000313,0x000019F5,0xFFFFF8E7,0x00000313}, - {"0000001000010011111010101001010011011110000101100100000010000100",0x00002372,0xFFFFF449,0x0000039B,0x00001544,0xFFFFFC16,0x0000028B,0x00001544,0xFFFFFC16,0x0000028B}, - {"0000001000010011111100001111111111101111011001100010100011000100",0x0000348E,0xFFFFEB20,0x000004B2,0x00002BE8,0xFFFFEE80,0x00000467,0x00002BE8,0xFFFFEE80,0x00000467}, - {"0000001000010011111100001111111111101111010111100001000100000100",0x00004092,0xFFFFE073,0x0000069B,0x00002061,0xFFFFF403,0x000003A0,0x00002061,0xFFFFF403,0x000003A0}, - {"0000001000010011111100001111111111101111011100100010000011100100",0x000039D1,0xFFFFE55D,0x000005CC,0x000025CB,0xFFFFF0C0,0x00000428,0x000025CB,0xFFFFF0C0,0x00000428}, - {"0000001000010011111100001111111111101111010111100100100010000100",0x000042AA,0xFFFFDF68,0x000006C2,0x0000290B,0xFFFFEE78,0x00000485,0x0000290B,0xFFFFEE78,0x00000485}, - {"0000001000010011111100001111111111101111011100100001100011000100",0x0000356F,0xFFFFE7AC,0x0000056E,0x00001BE8,0xFFFFF6E3,0x0000032A,0x00001BE8,0xFFFFF6E3,0x0000032A}, - {"0000001000010011111100001111111111101111010111100001000101000100",0x00003525,0xFFFFE7FF,0x0000055D,0x0000242C,0xFFFFF12E,0x0000041D,0x0000242C,0xFFFFF12E,0x0000041D}, - {"0000001000010011111100001111111111101111010111000100100011000100",0x00003360,0xFFFFE895,0x00000550,0x00002175,0xFFFFF29E,0x000003E9,0x00002175,0xFFFFF29E,0x000003E9}, - {"0000001000010011111100001111111111101111011001000100000010100100",0x00003C94,0xFFFFE1C4,0x0000067E,0x00002E28,0xFFFFE964,0x0000057F,0x00002E28,0xFFFFE964,0x0000057F}, - {"0000001000010011111100001111111111101111011100100100000100100100",0x0000431C,0xFFFFDE4B,0x000006FF,0x00002270,0xFFFFF268,0x000003E5,0x00002270,0xFFFFF268,0x000003E5}, - {"0000001000010011111010101001010011011110000100100001100011000100",0x00002B67,0xFFFFF01D,0x00000414,0x000019FB,0xFFFFF961,0x000002D8,0x000019FB,0xFFFFF961,0x000002D8}, - {"0000001000010011111100001111111111101111010111100011100110000100",0x0000400B,0xFFFFE13D,0x0000066F,0x000024F3,0xFFFFF125,0x00000417,0x000024F3,0xFFFFF125,0x00000417}, - {"0000001000010011111100001111111111101111010110100010000010100100",0x00004460,0xFFFFE00E,0x0000067B,0x000023DF,0xFFFFF2E6,0x000003BB,0x000023DF,0xFFFFF2E6,0x000003BB}, - {"0000001000010011111100001111111111101111011001000001100001100100",0x00003AFB,0xFFFFE2C5,0x00000650,0x00002D46,0xFFFFE9C4,0x00000571,0x00002D46,0xFFFFE9C4,0x00000571}, - {"0000001000010011111100001111111111101111011000100010100100100100",0x00005482,0xFFFFD5BC,0x0000081A,0x00003250,0xFFFFE961,0x00000541,0x00003250,0xFFFFE961,0x00000541}, - {"0000001000010011111100001111111111101111010111000010100101000100",0x00003D27,0xFFFFE2FA,0x00000632,0x00002A4D,0xFFFFED6A,0x000004BB,0x00002A4D,0xFFFFED6A,0x000004BB}, - {"0000001000010011111100001111111111101111011000000001100010100100",0x00003E03,0xFFFFE142,0x00000690,0x00001E08,0xFFFFF555,0x0000036C,0x00001E08,0xFFFFF555,0x0000036C}, - {"0000001000010011111100001111111111101111010111000010000001100100",0x000031B5,0xFFFFE97D,0x00000535,0x0000232E,0xFFFFF166,0x00000422,0x0000232E,0xFFFFF166,0x00000422}, - {"0000001000010011111100001111111111101111010111100001100011100100",0x00003753,0xFFFFE724,0x00000575,0x0000281A,0xFFFFEF1A,0x0000046B,0x0000281A,0xFFFFEF1A,0x0000046B}, - {"0000001000010011111010101001010011011110001000000100000101000100",0x00002071,0xFFFFF5C9,0x0000036F,0x00001470,0xFFFFFBF7,0x000002A5,0x00001470,0xFFFFFBF7,0x000002A5}, - {"0000001000010011111100001111111111101111011010000011000101000100",0x00002799,0xFFFFF223,0x000003CF,0x00001CD3,0xFFFFF74A,0x00000333,0x00001CD3,0xFFFFF74A,0x00000333}, - {"0000001000010011111100001111111111101111011001100001000011000100",0x000040DF,0xFFFFE11C,0x00000664,0x000031D4,0xFFFFE8BC,0x0000056F,0x000031D4,0xFFFFE8BC,0x0000056F}, - {"0000001000010011111100001111111111101111011001000100000011000100",0x00003A4D,0xFFFFE3A6,0x00000627,0x00002871,0xFFFFEDA0,0x000004C0,0x00002871,0xFFFFEDA0,0x000004C0}, - {"0000001000010011111100001111111111101111011010000001100110000100",0x00002AF9,0xFFFFEED7,0x00000464,0x0000219B,0xFFFFF368,0x000003D6,0x0000219B,0xFFFFF368,0x000003D6}, - {"0000001000010011111010101001010011011110001100100011000100100100",0x000026D5,0xFFFFF36C,0x000003A3,0x00001BC6,0xFFFFF881,0x00000311,0x00001BC6,0xFFFFF881,0x00000311}, - {"0000001000010011111100001111111111101111010111100010000001000100",0x0000325D,0xFFFFEA07,0x0000050B,0x000026D1,0xFFFFEFB3,0x0000045A,0x000026D1,0xFFFFEFB3,0x0000045A}, - {"0000001000010011111100001111111111101111011010000010100001100100",0x00002F75,0xFFFFEC64,0x000004BE,0x00001EEB,0xFFFFF559,0x00000386,0x00001EEB,0xFFFFF559,0x00000386}, - {"0000001000010011111100001111111111101111010110100011100010100100",0x00003C2F,0xFFFFE541,0x000005A3,0x000025B6,0xFFFFF16F,0x000003FA,0x000025B6,0xFFFFF16F,0x000003FA}, - {"0000001000010011111100001111111111101111011010000100100100100100",0x00002BC2,0xFFFFEE89,0x0000046A,0x00001D04,0xFFFFF651,0x00000361,0x00001D04,0xFFFFF651,0x00000361}, - {"0000001000010011111100001111111111101111011010000010100110100100",0x00002DD0,0xFFFFED40,0x0000049F,0x00001C8C,0xFFFFF6B3,0x00000353,0x00001C8C,0xFFFFF6B3,0x00000353}, - {"0000001000010011111010101001010011011110000111000000100011100100",0x000021ED,0xFFFFF530,0x00000380,0x00001643,0xFFFFFB1C,0x000002C3,0x00001643,0xFFFFFB1C,0x000002C3}, - {"0000001000010011111010101001010011011110001100100001100100000100",0x000028C7,0xFFFFF160,0x000003FD,0x00001990,0xFFFFF994,0x000002E2,0x00001990,0xFFFFF994,0x000002E2}, - {"0000001000010011111100001111111111101111011001100001000010100100",0x0000431C,0xFFFFDF9D,0x000006A3,0x000034A6,0xFFFFE6B0,0x000005C9,0x000034A6,0xFFFFE6B0,0x000005C9}, - {"0000001000010011111010101001010011011110001001100011000010100100",0x00004115,0xFFFFE0D6,0x00000667,0x000031AD,0xFFFFE850,0x00000585,0x000031AD,0xFFFFE850,0x00000585}, - {"0000001000010011111100001111111111101111011001000011100100100100",0x0000424A,0xFFFFDEEC,0x000006E1,0x0000346A,0xFFFFE5EA,0x00000602,0x0000346A,0xFFFFE5EA,0x00000602}, - {"0000001000010011111100001111111111101111011001100001100110000100",0x00004990,0xFFFFDAFA,0x00000771,0x00002A9C,0xFFFFED37,0x000004BC,0x00002A9C,0xFFFFED37,0x000004BC}, - {"0000001000010011111100001111111111101111011001000010100010100100",0x00003858,0xFFFFE568,0x000005D2,0x00003030,0xFFFFE8B0,0x0000058E,0x00003030,0xFFFFE8B0,0x0000058E}, - {"0000001000010011111100001111111111101111011010000100000101100100",0x00001EDC,0xFFFFF6CD,0x00000322,0x00001FCA,0xFFFFF4BD,0x0000039E,0x00001FCA,0xFFFFF4BD,0x0000039E}, - {"0000001000010011111100001111111111101111011001100010000100100100",0x00004C88,0xFFFFDBA3,0x0000071B,0x000030C4,0xFFFFEAFD,0x000004F7,0x000030C4,0xFFFFEAFD,0x000004F7}, - {"0000001000010011111100001111111111101111011010000000100100000100",0x00002B9A,0xFFFFEE41,0x0000047D,0x00002131,0xFFFFF344,0x000003E5,0x00002131,0xFFFFF344,0x000003E5}, - {"0000001000010011111100001111111111101111011000100011100110000100",0x00003E4B,0xFFFFE33C,0x000005FA,0x00003877,0xFFFFE437,0x0000062E,0x00003877,0xFFFFE437,0x0000062E}, - {"0000001000010011111010101001010011011110001100100010000001100100",0x00002376,0xFFFFF444,0x0000038A,0x000017ED,0xFFFFFA4C,0x000002C1,0x000017ED,0xFFFFFA4C,0x000002C1}, - {"0000001000010011111100001111111111101111011001100001000010000100",0x00004517,0xFFFFDDF4,0x000006F2,0x000030DC,0xFFFFE8EF,0x00000571,0x000030DC,0xFFFFE8EF,0x00000571}, - {"0000001000010011111100001111111111101111011010000001100101000100",0x0000270C,0xFFFFF1F3,0x000003DF,0x0000207B,0xFFFFF474,0x000003AD,0x0000207B,0xFFFFF474,0x000003AD}, - {"0000001000010011111100001111111111101111011001000101000101000100",0x00004086,0xFFFFDF39,0x000006E3,0x00002A24,0xFFFFEC2B,0x000004FF,0x00002A24,0xFFFFEC2B,0x000004FF}, - {"0000001000010011111100001111111111101111010111000011000100100100",0x00003BDE,0xFFFFE45E,0x000005EB,0x00002CD5,0xFFFFEC45,0x000004DD,0x00002CD5,0xFFFFEC45,0x000004DD}, - {"0000001000010011111100001111111111101111011100100011000011100100",0x00003803,0xFFFFE714,0x00000579,0x0000288A,0xFFFFEF21,0x0000046B,0x0000288A,0xFFFFEF21,0x0000046B}, - {"0000001000010011111100001111111111101111011000000001000100000100",0x00003F50,0xFFFFE002,0x000006CD,0x00001AD4,0xFFFFF72E,0x0000031F,0x00001AD4,0xFFFFF72E,0x0000031F}, - {"0000001000010011111100001111111111101111011010000010000011100100",0x00002968,0xFFFFF100,0x00000402,0x00001FB5,0xFFFFF57C,0x0000037F,0x00001FB5,0xFFFFF57C,0x0000037F}, - {"0000001000010011111100001111111111101111011001100010000100000100",0x00004283,0xFFFFE2A7,0x000005F5,0x00003165,0xFFFFEB0C,0x000004EC,0x00003165,0xFFFFEB0C,0x000004EC}, - {"0000001000010011111100001111111111101111011001000011000110100100",0x00004253,0xFFFFDDA8,0x00000732,0x00002E5C,0xFFFFE90A,0x00000593,0x00002E5C,0xFFFFE90A,0x00000593}, - {"0000001000010011111100001111111111101111010111000101000010100100",0x00003551,0xFFFFE756,0x0000058D,0x000029A7,0xFFFFED0C,0x000004DE,0x000029A7,0xFFFFED0C,0x000004DE}, - {"0000001000010011111100001111111111101111011001000010100011000100",0x00003728,0xFFFFE604,0x000005C4,0x00002832,0xFFFFEE64,0x00000493,0x00002832,0xFFFFEE64,0x00000493}, - {"0000001000010011111100001111111111101111011000100011100101100100",0x00004796,0xFFFFDCC8,0x00000715,0x000032AB,0xFFFFE848,0x0000057C,0x000032AB,0xFFFFE848,0x0000057C}, - {"0000001000010011111100001111111111101111011000100001000011000100",0x000049DF,0xFFFFDB24,0x0000075F,0x00003076,0xFFFFE967,0x0000055C,0x00003076,0xFFFFE967,0x0000055C}, - {"0000001000010011111100001111111111101111011100100001000100000100",0x00003F13,0xFFFFE099,0x000006A8,0x00002279,0xFFFFF226,0x000003F3,0x00002279,0xFFFFF226,0x000003F3}, - {"0000001000010011111100001111111111101111011001000011000010100100",0x00003E03,0xFFFFE19F,0x00000674,0x00002D66,0xFFFFEAA7,0x00000537,0x00002D66,0xFFFFEAA7,0x00000537}, - {"0000001000010011111100001111111111101111010111000100000100000100",0x000037DA,0xFFFFE63F,0x000005A7,0x00002543,0xFFFFF0A0,0x00000431,0x00002543,0xFFFFF0A0,0x00000431}, - {"0000001000010011111100001111111111101111011000100100100101000100",0x00003D82,0xFFFFE3F5,0x000005D9,0x0000332F,0xFFFFE834,0x00000577,0x0000332F,0xFFFFE834,0x00000577}, - {"0000001000010011111010101001010011011110000100100010100011000100",0x00002915,0xFFFFF1E0,0x000003D4,0x00002065,0xFFFFF57B,0x00000378,0x00002065,0xFFFFF57B,0x00000378}, - {"0000001000010011111100001111111111101111010111100100100100000100",0x000036FC,0xFFFFE72D,0x00000577,0x00002811,0xFFFFEF30,0x00000464,0x00002811,0xFFFFEF30,0x00000464}, - {"0000001000010011111100001111111111101111011000100011000110000100",0x00004767,0xFFFFDD30,0x000006FD,0x00003703,0xFFFFE564,0x000005F8,0x00003703,0xFFFFE564,0x000005F8}, - {"0000001000010011111100001111111111101111011000000011000110000100",0x00003094,0xFFFFEAA9,0x000004F5,0x000022E7,0xFFFFF200,0x000003FB,0x000022E7,0xFFFFF200,0x000003FB}, - {"0000001000010011111100001111111111101111011001000001000101000100",0x00003EF0,0xFFFFDF83,0x000006ED,0x00002A27,0xFFFFEB7C,0x00000537,0x00002A27,0xFFFFEB7C,0x00000537}, - {"0000001000010011111100001111111111101111011010000001000100100100",0x0000243C,0xFFFFF358,0x000003AC,0x00001DC4,0xFFFFF5E9,0x00000372,0x00001DC4,0xFFFFF5E9,0x00000372}, - {"0000001000010011111100001111111111101111011100100010000101000100",0x0000284B,0xFFFFF036,0x0000040F,0x00001FCD,0xFFFFF445,0x00000395,0x00001FCD,0xFFFFF445,0x00000395}, - {"0000001000010011111100001111111111101111011010000100000011000100",0x00002611,0xFFFFF285,0x000003C7,0x00001CFE,0xFFFFF6A0,0x00000355,0x00001CFE,0xFFFFF6A0,0x00000355}, - {"0000001000010011111010101001010011011110000111000011100110100100",0x00002292,0xFFFFF49F,0x00000393,0x000017F4,0xFFFFF9CD,0x000002F5,0x000017F4,0xFFFFF9CD,0x000002F5}, - {"0000001000010011111100001111111111101111010111100011100010100100",0x000037F3,0xFFFFE68D,0x00000590,0x00002443,0xFFFFF1AD,0x000003FA,0x00002443,0xFFFFF1AD,0x000003FA}, - {"0000001000010011111100001111111111101111011010000010000101000100",0x00002C01,0xFFFFEF3F,0x00000444,0x0000210A,0xFFFFF475,0x000003A7,0x0000210A,0xFFFFF475,0x000003A7}, - {"0000001000010011111010101001010011011110000100100001000011100100",0x00002C0E,0xFFFFEF0F,0x00000446,0x00001A82,0xFFFFF8F7,0x000002DE,0x00001A82,0xFFFFF8F7,0x000002DE}, - {"0000001000010011111100001111111111101111010111100010000011000100",0x00003FA6,0xFFFFE20A,0x0000063F,0x00002E29,0xFFFFEB21,0x00000510,0x00002E29,0xFFFFEB21,0x00000510}, - {"0000001000010011111100001111111111101111010111000010000101100100",0x00003BCD,0xFFFFE31B,0x0000063C,0x000019AF,0xFFFFF83D,0x000002F8,0x000019AF,0xFFFFF83D,0x000002F8}, - {"0000001000010011111100001111111111101111011001100100000101100100",0x000044C8,0xFFFFDF08,0x000006B0,0x00002E2E,0xFFFFEB62,0x000004FD,0x00002E2E,0xFFFFEB62,0x000004FD}, - {"0000001000010011111100001111111111101111010111000001100010000100",0x00003790,0xFFFFE571,0x000005E3,0x00002042,0xFFFFF35D,0x000003CF,0x00002042,0xFFFFF35D,0x000003CF}, - {"0000001000010011111100001111111111101111011000000101000011100100",0x000038AC,0xFFFFE46C,0x00000609,0x0000215E,0xFFFFF22D,0x00000403,0x0000215E,0xFFFFF22D,0x00000403}, - {"0000001000010011111100001111111111101111010111100010100110100100",0x00003A1E,0xFFFFE536,0x000005C9,0x000024F3,0xFFFFF11A,0x0000041B,0x000024F3,0xFFFFF11A,0x0000041B}, - {"0000001000010011111100001111111111101111011001100101000011100100",0x0000431A,0xFFFFDF1B,0x000006C5,0x00002F34,0xFFFFEA02,0x00000545,0x00002F34,0xFFFFEA02,0x00000545}, - {"0000001000010011111100001111111111101111011001000001100100000100",0x000042DC,0xFFFFDE28,0x0000070C,0x00003B53,0xFFFFE0EA,0x000006E2,0x00003B53,0xFFFFE0EA,0x000006E2}, - {"0000001000010011111100001111111111101111011010000011000101100100",0x0000264B,0xFFFFF29A,0x000003C4,0x000021D0,0xFFFFF3CE,0x000003C4,0x000021D0,0xFFFFF3CE,0x000003C4}, - {"0000001000010011111100001111111111101111010110100100000001100100",0x00004225,0xFFFFE0E8,0x00000665,0x00002B53,0xFFFFED89,0x0000049F,0x00002B53,0xFFFFED89,0x0000049F}, - {"0000001000010011111010101001010011011110001000000100100100100100",0x00001FCC,0xFFFFF63F,0x00000358,0x000019E8,0xFFFFF882,0x0000032A,0x000019E8,0xFFFFF882,0x0000032A}, - {"0000001000010011111100001111111111101111011000100100000010100100",0x000045E0,0xFFFFDDD0,0x000006ED,0x00003193,0xFFFFE8BD,0x00000572,0x00003193,0xFFFFE8BD,0x00000572}, - {"0000001000010011111100001111111111101111011010000011100100100100",0x000024FC,0xFFFFF366,0x000003A6,0x00001FE8,0xFFFFF509,0x00000394,0x00001FE8,0xFFFFF509,0x00000394}, - {"0000001000010011111100001111111111101111010111000100100010000100",0x0000378F,0xFFFFE54B,0x000005F1,0x00001C9B,0xFFFFF5C7,0x00000368,0x00001C9B,0xFFFFF5C7,0x00000368}, - {"0000001000010011111100001111111111101111011001000001100010100100",0x00003CF3,0xFFFFE15A,0x00000694,0x00002CDD,0xFFFFEA44,0x00000557,0x00002CDD,0xFFFFEA44,0x00000557}, - {"0000001000010011111010101001010011011110001000000000100100000100",0x000021EC,0xFFFFF4F4,0x0000038F,0x00001511,0xFFFFFBF5,0x0000029E,0x00001511,0xFFFFFBF5,0x0000029E}, - {"0000001000010011111100001111111111101111011000000001000010100100",0x00003C8A,0xFFFFE1C1,0x00000685,0x000019C7,0xFFFFF7E2,0x00000301,0x000019C7,0xFFFFF7E2,0x00000301}, - {"0000001000010011111100001111111111101111010111100010000001100100",0x00003908,0xFFFFE5C7,0x000005B3,0x00002793,0xFFFFEF46,0x00000465,0x00002793,0xFFFFEF46,0x00000465}, - {"0000001000010011111100001111111111101111011000000101000100000100",0x000040A3,0xFFFFDE61,0x00000725,0x00002077,0xFFFFF2CE,0x000003E8,0x00002077,0xFFFFF2CE,0x000003E8}, - {"0000001000010011111100001111111111101111011001100100000101000100",0x00003DCA,0xFFFFE34D,0x00000608,0x00002D66,0xFFFFEBDF,0x000004E8,0x00002D66,0xFFFFEBDF,0x000004E8}, - {"0000001000010011111100001111111111101111010111100101000011000100",0x00003085,0xFFFFEB70,0x000004C8,0x000029B1,0xFFFFEDD9,0x000004A5,0x000029B1,0xFFFFEDD9,0x000004A5}, - {"0000001000010011111010101001010011011110000010000011100010000100",0x00004C73,0xFFFFD676,0x0000086C,0x0000280A,0xFFFFED89,0x000004C2,0x0000280A,0xFFFFED89,0x000004C2}, - {"0000001000010011111010101001010011011110001001000010000101100100",0x00002CE5,0xFFFFEE8C,0x00000466,0x00001755,0xFFFFFAC2,0x000002AC,0x00001755,0xFFFFFAC2,0x000002AC}, - {"0000001000010011111100001111111111101111011000100001000100100100",0x0000489F,0xFFFFDBF1,0x0000073E,0x0000332D,0xFFFFE786,0x000005AD,0x0000332D,0xFFFFE786,0x000005AD}, - {"0000001000010011111100001111111111101111011000000010100001100100",0x00003D09,0xFFFFE193,0x00000689,0x00001E82,0xFFFFF4C0,0x00000386,0x00001E82,0xFFFFF4C0,0x00000386}, - {"0000001000010011111100001111111111101111011001000100000100000100",0x00003E4C,0xFFFFE131,0x00000689,0x00002F4E,0xFFFFE925,0x0000057B,0x00002F4E,0xFFFFE925,0x0000057B}, - {"0000001000010011111100001111111111101111010110100100000010000100",0x00003B31,0xFFFFE53F,0x000005B3,0x0000248A,0xFFFFF211,0x000003DF,0x0000248A,0xFFFFF211,0x000003DF}, - {"0000001000010011111100001111111111101111011001000100000100100100",0x000038DD,0xFFFFE54A,0x000005C9,0x00002B6D,0xFFFFEBDF,0x00000502,0x00002B6D,0xFFFFEBDF,0x00000502}, - {"0000001000010011111100001111111111101111011010000100000001100100",0x00002698,0xFFFFF1A8,0x000003F2,0x00002163,0xFFFFF34B,0x000003E3,0x00002163,0xFFFFF34B,0x000003E3}, - {"0000001000010011111010101001010011011110001000000001000001100100",0x000023A8,0xFFFFF4CD,0x00000386,0x00001944,0xFFFFF983,0x00000300,0x00001944,0xFFFFF983,0x00000300}, - {"0000001000010011111100001111111111101111011001000001100011000100",0x00003EAF,0xFFFFE0C3,0x000006A0,0x000030AB,0xFFFFE829,0x000005A6,0x000030AB,0xFFFFE829,0x000005A6}, - {"0000001000010011111100001111111111101111011010000100100101000100",0x00002E89,0xFFFFECA6,0x000004B6,0x00001FA0,0xFFFFF4A8,0x000003A3,0x00001FA0,0xFFFFF4A8,0x000003A3}, - {"0000001000010011111100001111111111101111011010000010100010100100",0x000028A4,0xFFFFF112,0x00000402,0x00001F7C,0xFFFFF545,0x0000038A,0x00001F7C,0xFFFFF545,0x0000038A}, - {"0000001000010011111100001111111111101111011001100101000010100100",0x00004135,0xFFFFDFA2,0x000006C5,0x0000324C,0xFFFFE7AA,0x000005AF,0x0000324C,0xFFFFE7AA,0x000005AF}, - {"0000001000010011111010101001010011011110001000000011100011000100",0x00002012,0xFFFFF693,0x00000352,0x0000171F,0xFFFFFABB,0x000002D9,0x0000171F,0xFFFFFABB,0x000002D9}, - {"0000001000010011111100001111111111101111011001000011000010000100",0x00003D7C,0xFFFFE1BC,0x00000671,0x00002A45,0xFFFFEC84,0x000004EC,0x00002A45,0xFFFFEC84,0x000004EC}, - {"0000001000010011111100001111111111101111011100100011000001100100",0x00004172,0xFFFFDF58,0x000006DA,0x00002504,0xFFFFF0A6,0x00000431,0x00002504,0xFFFFF0A6,0x00000431}, - {"0000001000010011111100001111111010011001001010000001100101000100",0x000029C7,0xFFFFF087,0x00000414,0x00001DCB,0xFFFFF675,0x0000035F,0x00001DCB,0xFFFFF675,0x0000035F}, - {"0000001000010011111100001111111010011001001010100010100110100100",0x000027F0,0xFFFFF05A,0x00000432,0x00001707,0xFFFFFA0E,0x000002D1,0x00001707,0xFFFFFA0E,0x000002D1}, - {"0000001000010011111100001111111010011001001000100010000101000100",0x00003279,0xFFFFE9F7,0x00000511,0x00001B5E,0xFFFFF787,0x00000317,0x00001B5E,0xFFFFF787,0x00000317}, - {"0000001000010011111100001111111010011001001100100010000110000100",0x000030A5,0xFFFFEABC,0x000004FF,0x000019D1,0xFFFFF83C,0x00000304,0x000019D1,0xFFFFF83C,0x00000304}, - {"0000001000010011111100001111111010011001001010000010100001000100",0x0000283B,0xFFFFF122,0x00000402,0x000019C2,0xFFFFF8E9,0x000002FB,0x000019C2,0xFFFFF8E9,0x000002FB}, - {"0000001000010011111100001111111010011001001011000010000010000100",0x00003376,0xFFFFE9E1,0x00000510,0x000021A7,0xFFFFF39F,0x000003BF,0x000021A7,0xFFFFF39F,0x000003BF}, - {"0000001000010011111100001111111010011001001100100001100011000100",0x000031D2,0xFFFFEA9C,0x000004FC,0x00001F66,0xFFFFF4E4,0x00000390,0x00001F66,0xFFFFF4E4,0x00000390}, - {"0000001000010011111100001111111010011001000110100011100001100100",0x00003006,0xFFFFEB18,0x000004F2,0x000019B3,0xFFFFF84E,0x00000301,0x000019B3,0xFFFFF84E,0x00000301}, - {"0000001000010011111100001111111010011001001100000011100110100100",0x0000364F,0xFFFFE81F,0x00000556,0x00002AC9,0xFFFFED87,0x000004BD,0x00002AC9,0xFFFFED87,0x000004BD}, - {"0000001000010011111100001111111010011001001011100011100001000100",0x00003043,0xFFFFEBAE,0x000004CD,0x00001B0C,0xFFFFF7ED,0x0000030C,0x00001B0C,0xFFFFF7ED,0x0000030C}, - {"0000001000010011111100001111111010011001001100000100100010100100",0x000037CE,0xFFFFE69E,0x00000596,0x0000276B,0xFFFFEF65,0x0000046E,0x0000276B,0xFFFFEF65,0x0000046E}, - {"0000001000010011111100001111111010011001001011000011000100000100",0x00003063,0xFFFFED5E,0x0000046F,0x000024AE,0xFFFFF2C4,0x000003D8,0x000024AE,0xFFFFF2C4,0x000003D8}, - {"0000001000010011111100001111111010011001001011100000100010100100",0x00002F5D,0xFFFFEBDC,0x000004D3,0x00001EDB,0xFFFFF50F,0x0000038E,0x00001EDB,0xFFFFF50F,0x0000038E}, - {"0000001000010011111100001111111010011001001011100100100010100100",0x00003148,0xFFFFEA9A,0x000004FB,0x0000192D,0xFFFFF8E9,0x000002DF,0x0000192D,0xFFFFF8E9,0x000002DF}, - {"0000001000010011111100001111111010011001001011000010000001100100",0x00003682,0xFFFFE7E4,0x0000055C,0x0000250E,0xFFFFF150,0x0000041A,0x0000250E,0xFFFFF150,0x0000041A}, - {"0000001000010011111100001111111010011001001010100010000010000100",0x0000284E,0xFFFFF15A,0x000003F8,0x00001CE2,0xFFFFF6F9,0x0000034F,0x00001CE2,0xFFFFF6F9,0x0000034F}, - {"0000001000010011111100001111111010011001001100000001100010100100",0x00003171,0xFFFFEAE9,0x000004ED,0x00001F40,0xFFFFF513,0x00000384,0x00001F40,0xFFFFF513,0x00000384}, - {"0000001000010011111100001111111010011001001100100011000001000100",0x000031BD,0xFFFFEA64,0x0000050A,0x00001EFD,0xFFFFF4F7,0x00000390,0x00001EFD,0xFFFFF4F7,0x00000390}, - {"0000001000010011111100001111111010011001001011100101000011100100",0x00003050,0xFFFFEB29,0x000004EA,0x000019B3,0xFFFFF878,0x000002F9,0x000019B3,0xFFFFF878,0x000002F9}, - {"0000001000010011111100001111111010011001001011000001100100000100",0x00003400,0xFFFFE9A0,0x0000051A,0x00002460,0xFFFFF1DA,0x00000409,0x00002460,0xFFFFF1DA,0x00000409}, - {"0000001000010011111100001111111010011001001011000100100010000100",0x000034A1,0xFFFFE86F,0x00000558,0x0000255D,0xFFFFF09E,0x00000443,0x0000255D,0xFFFFF09E,0x00000443}, - {"0000001000010011111100001111111010011001001011100100100011100100",0x00003103,0xFFFFEAD7,0x000004F0,0x00001896,0xFFFFF95A,0x000002CC,0x00001896,0xFFFFF95A,0x000002CC}, - {"0000001000010011111100001111111010011001001100000001100011100100",0x00003120,0xFFFFEB9E,0x000004CB,0x000021E8,0xFFFFF3A2,0x000003C1,0x000021E8,0xFFFFF3A2,0x000003C1}, - {"0000001000010011111100001111111010011001000111000101000011100100",0x00003558,0xFFFFE812,0x00000565,0x0000256E,0xFFFFF097,0x00000447,0x0000256E,0xFFFFF097,0x00000447}, - {"0000001000010011111100001111111010011001000110100010100001000100",0x00002DA8,0xFFFFECA8,0x000004B7,0x0000180B,0xFFFFF96D,0x000002D8,0x0000180B,0xFFFFF96D,0x000002D8}, - {"0000001000010011111100001111111010011001001011100011000001100100",0x00003232,0xFFFFEA66,0x000004FF,0x00001DDE,0xFFFFF5FE,0x0000035A,0x00001DDE,0xFFFFF5FE,0x0000035A}, - {"0000001000010011111100001111111010011001001100000101000011100100",0x000034D2,0xFFFFE89F,0x00000548,0x0000246C,0xFFFFF17F,0x00000418,0x0000246C,0xFFFFF17F,0x00000418}, - {"0000001000010011111100001111111010011001001100000100100100000100",0x000033EC,0xFFFFE954,0x0000052A,0x00002323,0xFFFFF279,0x000003EE,0x00002323,0xFFFFF279,0x000003EE}, - {"0000001000010011111100001111111010011001001100000011100010000100",0x000033AA,0xFFFFE955,0x0000052D,0x0000229F,0xFFFFF2B2,0x000003E7,0x0000229F,0xFFFFF2B2,0x000003E7}, - {"0000001000010011111100001111111010011001001100100100100101100100",0x00003258,0xFFFFE9AA,0x0000052A,0x00001D5F,0xFFFFF5D1,0x0000036B,0x00001D5F,0xFFFFF5D1,0x0000036B}, - {"0000001000010011111100001111111010011001001100000010100110100100",0x0000323A,0xFFFFEA5F,0x00000504,0x00002108,0xFFFFF3D5,0x000003BA,0x00002108,0xFFFFF3D5,0x000003BA}, - {"0000001000010011111100001111111010011001001011000010000110000100",0x00003216,0xFFFFEA6B,0x000004FF,0x00001D6E,0xFFFFF640,0x00000350,0x00001D6E,0xFFFFF640,0x00000350}, - {"0000001000010011111100001111111010011001001100100001000011100100",0x000030C5,0xFFFFEAC4,0x000004FC,0x00001924,0xFFFFF8C2,0x000002EE,0x00001924,0xFFFFF8C2,0x000002EE}, - {"0000001000010011111100001111111010011001001100000101000100000100",0x000032BB,0xFFFFE9F1,0x00000515,0x00002211,0xFFFFF31B,0x000003D5,0x00002211,0xFFFFF31B,0x000003D5}, - {"0000001000010011111100001111111010011001001100000100100011000100",0x0000352C,0xFFFFE85B,0x00000553,0x00002410,0xFFFFF1B4,0x0000040F,0x00002410,0xFFFFF1B4,0x0000040F}, - {"0000001000010011111100001111111010011001001000100011100011000100",0x000036A0,0xFFFFE7E8,0x0000055D,0x00002901,0xFFFFEEB8,0x00000489,0x00002901,0xFFFFEEB8,0x00000489}, - {"0000001000010011111100001111111010011001001011000011000001000100",0x00003340,0xFFFFE9D9,0x00000516,0x00002332,0xFFFFF27A,0x000003F0,0x00002332,0xFFFFF27A,0x000003F0}, - {"0000001000010011111100001111111010011001000110100011100010100100",0x00003564,0xFFFFE86D,0x0000054E,0x00002613,0xFFFFF07C,0x00000444,0x00002613,0xFFFFF07C,0x00000444}, - {"0000001000010011111100001111111010011001001010000000100100000100",0x00002AD1,0xFFFFEF0B,0x0000045C,0x00001DEA,0xFFFFF5C8,0x00000381,0x00001DEA,0xFFFFF5C8,0x00000381}, - {"0000001000010011111100001111111010011001001000100010000011100100",0x000035B0,0xFFFFE846,0x00000555,0x000027BE,0xFFFFEF5D,0x00000474,0x000027BE,0xFFFFEF5D,0x00000474}, - {"0000001000010011111100001111111010011001001000100011100010100100",0x000032C4,0xFFFFEA48,0x00000502,0x000022C6,0xFFFFF2DF,0x000003DE,0x000022C6,0xFFFFF2DF,0x000003DE}, - {"0000001000010011111100001111111010011001001100000000100011000100",0x00003036,0xFFFFEB0D,0x000004F9,0x00001FE8,0xFFFFF41A,0x000003BC,0x00001FE8,0xFFFFF41A,0x000003BC}, - {"0000001000010011111100001111111010011001000110100000100100000100",0x000030F8,0xFFFFEA13,0x00000524,0x00001B6A,0xFFFFF6C9,0x0000034A,0x00001B6A,0xFFFFF6C9,0x0000034A}, - {"0000001000010011111100001111111010011001001100000001000010100100",0x00002EE2,0xFFFFEC0C,0x000004CB,0x00001A39,0xFFFFF814,0x0000030F,0x00001A39,0xFFFFF814,0x0000030F}, - {"0000001000010011111100001111111010011001000111000011000110000100",0x00003457,0xFFFFE924,0x0000052A,0x00001E9D,0xFFFFF59C,0x00000363,0x00001E9D,0xFFFFF59C,0x00000363}, - {"0000001000010011111100001111111010011001001100100010100001000100",0x000030BF,0xFFFFEB18,0x000004ED,0x00001D37,0xFFFFF636,0x0000035C,0x00001D37,0xFFFFF636,0x0000035C}, - {"0000001000010011111100001111111010011001001011100100000010000100",0x000031AF,0xFFFFEA75,0x000004FE,0x000019F2,0xFFFFF87A,0x000002F0,0x000019F2,0xFFFFF87A,0x000002F0}, - {"0000001000010011111100001111111010011001001100000010100010000100",0x00003642,0xFFFFE85B,0x00000547,0x00002975,0xFFFFEE98,0x0000048B,0x00002975,0xFFFFEE98,0x0000048B}, - {"0000001000010011111100001111111010011001001011100010100010000100",0x00002E8B,0xFFFFED1E,0x0000048E,0x000019C1,0xFFFFF917,0x000002D6,0x000019C1,0xFFFFF917,0x000002D6}, - {"0000001000010011111100001111111010011001001100100100000110100100",0x000033D9,0xFFFFE8E1,0x00000548,0x0000224B,0xFFFFF298,0x000003F4,0x0000224B,0xFFFFF298,0x000003F4}, - {"0000001000010011111100001111111010011001001011100010100011000100",0x000032BC,0xFFFFEB0F,0x000004D6,0x00002488,0xFFFFF240,0x000003F2,0x00002488,0xFFFFF240,0x000003F2}, - {"0000001000010011111100001111111010011001001100000100100101000100",0x000035FD,0xFFFFE838,0x00000553,0x00002762,0xFFFFEFBC,0x00000460,0x00002762,0xFFFFEFBC,0x00000460}, - {"0000001000010011111100001111111010011001001010000001100010100100",0x0000268B,0xFFFFF263,0x000003D1,0x00001914,0xFFFFF977,0x000002E8,0x00001914,0xFFFFF977,0x000002E8}, - {"0000001000010011111100001111111010011001001011000011000110000100",0x0000330B,0xFFFFEA1E,0x00000505,0x000020B1,0xFFFFF44D,0x0000039E,0x000020B1,0xFFFFF44D,0x0000039E}, - {"0000001000010011111100001111111010011001001000100010000010000100",0x0000326E,0xFFFFEA26,0x00000508,0x00001C17,0xFFFFF722,0x00000328,0x00001C17,0xFFFFF722,0x00000328}, - {"0000001000010011111100001111111010011001001010100011000110100100",0x00002A3F,0xFFFFEEE8,0x0000046D,0x00001B2B,0xFFFFF737,0x0000034D,0x00001B2B,0xFFFFF737,0x0000034D}, - {"0000001000010011111100001111111010011001001011000100000001100100",0x00003732,0xFFFFE765,0x00000574,0x00002A6D,0xFFFFEDA8,0x000004B7,0x00002A6D,0xFFFFEDA8,0x000004B7}, - {"0000001000010011111100001111111010011001001100000000100100100100",0x000034D3,0xFFFFE827,0x00000569,0x000027AA,0xFFFFEEE7,0x00000492,0x000027AA,0xFFFFEEE7,0x00000492}, - {"0000001000010011111100001111111010011001001011100100000011000100",0x00003306,0xFFFFEA39,0x000004FC,0x00001DCC,0xFFFFF655,0x00000344,0x00001DCC,0xFFFFF655,0x00000344}, - {"0000001000010011111100001111111010011001001010000010000001000100",0x00002A48,0xFFFFEFCA,0x00000439,0x00001DED,0xFFFFF60D,0x00000375,0x00001DED,0xFFFFF60D,0x00000375}, - {"0000001000010011111100001111111010011001001100000011100011000100",0x000033A3,0xFFFFEA36,0x000004F9,0x0000247C,0xFFFFF21F,0x000003F4,0x0000247C,0xFFFFF21F,0x000003F4}, - {"0000001000010011111100001111111010011001001011000011000101100100",0x0000311B,0xFFFFEB76,0x000004D1,0x00001EB1,0xFFFFF5B6,0x00000366,0x00001EB1,0xFFFFF5B6,0x00000366}, - {"0000001000010011111100001111111010011001001100100100000101100100",0x00003307,0xFFFFE97F,0x0000052A,0x00001E76,0xFFFFF54D,0x0000037C,0x00001E76,0xFFFFF54D,0x0000037C}, - {"0000001000010011111100001111111010011001000111000010000101000100",0x0000344B,0xFFFFE9C5,0x00000509,0x000020D6,0xFFFFF486,0x0000038F,0x000020D6,0xFFFFF486,0x0000038F}, - {"0000001000010011111100001111111010011001001011000011000101000100",0x000034B9,0xFFFFEA0B,0x000004F7,0x000027B3,0xFFFFF057,0x0000043A,0x000027B3,0xFFFFF057,0x0000043A}, - {"0000001000010011111100001111111010011001001100000001100101100100",0x00003360,0xFFFFE984,0x00000527,0x00002238,0xFFFFF2EE,0x000003E0,0x00002238,0xFFFFF2EE,0x000003E0}, - {"0000001000010011111100001111111010011001001100000010000100100100",0x0000315C,0xFFFFEC05,0x000004B1,0x000023C8,0xFFFFF2CC,0x000003DE,0x000023C8,0xFFFFF2CC,0x000003DE}, - {"0000001000010011111100001111111010011001001011000010100001100100",0x0000389B,0xFFFFE6D5,0x00000582,0x00002C6C,0xFFFFEC92,0x000004DE,0x00002C6C,0xFFFFEC92,0x000004DE}, - {"0000001000010011111100001111111010011001001011100001000100100100",0x00003058,0xFFFFEB30,0x000004E6,0x000019B5,0xFFFFF88B,0x000002F1,0x000019B5,0xFFFFF88B,0x000002F1}, - {"0000001000010011111100001111111010011001001011100000100100000100",0x00002F69,0xFFFFEB4A,0x000004F1,0x00001B82,0xFFFFF6EC,0x00000341,0x00001B82,0xFFFFF6EC,0x00000341}, - {"0000001000010011111100001111111010011001000110100001100011100100",0x000031EB,0xFFFFEA64,0x00000508,0x00002059,0xFFFFF427,0x000003B0,0x00002059,0xFFFFF427,0x000003B0}, - {"0000001000010011111100001111111010011001001000100100000100100100",0x000033E2,0xFFFFE94D,0x0000052A,0x000020BF,0xFFFFF40B,0x000003AB,0x000020BF,0xFFFFF40B,0x000003AB}, - {"0000001000010011111100001111111010011001001010000011000110000100",0x00002AF9,0xFFFFEFE9,0x00000427,0x00001F72,0xFFFFF57A,0x00000383,0x00001F72,0xFFFFF57A,0x00000383}, - {"0000001000010011111100001111111010011001001011000010100000100100",0x00003282,0xFFFFEA88,0x000004FA,0x00002561,0xFFFFF126,0x0000042B,0x00002561,0xFFFFF126,0x0000042B}, - {"0000001000010011111100001111111010011001001100000001000011100100",0x0000308A,0xFFFFEB5D,0x000004E0,0x00001E83,0xFFFFF577,0x00000378,0x00001E83,0xFFFFF577,0x00000378}, - {"0000001000010011111100001111111010011001001100100100100010000100",0x0000336E,0xFFFFE8C8,0x00000553,0x0000217C,0xFFFFF2E1,0x000003EB,0x0000217C,0xFFFFF2E1,0x000003EB}, - {"0000001000010011111100001111111010011001000110100010000101100100",0x000034A9,0xFFFFE838,0x00000561,0x000020CE,0xFFFFF38A,0x000003C7,0x000020CE,0xFFFFF38A,0x000003C7}, - {"0000001000010011111100001111111010011001001000100010000110000100",0x00003152,0xFFFFE9EB,0x00000522,0x00001755,0xFFFFF9A9,0x000002C6,0x00001755,0xFFFFF9A9,0x000002C6}, - {"0000001000010011111100001111111010011001001010000001100010000100",0x0000286E,0xFFFFF136,0x000003FD,0x00001BAB,0xFFFFF7C3,0x0000032C,0x00001BAB,0xFFFFF7C3,0x0000032C}, - {"0000001000010011111100001111111010011001001100000000100101000100",0x0000316B,0xFFFFEA02,0x00000528,0x00002247,0xFFFFF24E,0x00000408,0x00002247,0xFFFFF24E,0x00000408}, - {"0000001000010011111100001111111010011001001011000000100011100100",0x000034CF,0xFFFFE83D,0x00000562,0x00002458,0xFFFFF130,0x00000430,0x00002458,0xFFFFF130,0x00000430}, - {"0000001000010011111100001111111010011001001011000010100110000100",0x00003352,0xFFFFE9D1,0x00000515,0x0000212A,0xFFFFF3DC,0x000003B4,0x0000212A,0xFFFFF3DC,0x000003B4}, - {"0000001000010011111100001111111010011001001010000100000010100100",0x00002946,0xFFFFF09B,0x00000415,0x00001DC9,0xFFFFF650,0x00000366,0x00001DC9,0xFFFFF650,0x00000366}, - {"0000001000010011111100001111111010011001001100000001000100100100",0x00003080,0xFFFFEB47,0x000004E1,0x00001BD5,0xFFFFF73B,0x00000329,0x00001BD5,0xFFFFF73B,0x00000329}, - {"0000001000010011111100001111111010011001000110100001100010000100",0x00002FBD,0xFFFFEB7B,0x000004DD,0x000017FC,0xFFFFF99E,0x000002C7,0x000017FC,0xFFFFF99E,0x000002C7}, - {"0000001000010011111100001111111010011001001010000001000100100100",0x00002A28,0xFFFFF032,0x0000041F,0x00001B19,0xFFFFF83A,0x00000312,0x00001B19,0xFFFFF83A,0x00000312}, - {"0000001000010011111100001111111010011001001000100100000011000100",0x00003420,0xFFFFE936,0x00000530,0x000023C2,0xFFFFF203,0x00000406,0x000023C2,0xFFFFF203,0x00000406}, - {"0000001000010011111100001111111010011001001100000001000101000100",0x00002F7C,0xFFFFEBBA,0x000004D1,0x0000185D,0xFFFFF975,0x000002CA,0x0000185D,0xFFFFF975,0x000002CA}, - {"0000001000010011111100001111111010011001001011100010000001000100",0x00002C51,0xFFFFEE3B,0x0000046F,0x000019AA,0xFFFFF8DD,0x000002ED,0x000019AA,0xFFFFF8DD,0x000002ED}, - {"0000001000010011111100001111111010011001000110100100000101000100",0x000033D6,0xFFFFE8F2,0x0000053D,0x00001D73,0xFFFFF5FB,0x0000035B,0x00001D73,0xFFFFF5FB,0x0000035B}, - {"0000001000010011111100001111111010011001001100100011000010000100",0x000031D9,0xFFFFEAF7,0x000004E4,0x00001EBD,0xFFFFF5A6,0x00000368,0x00001EBD,0xFFFFF5A6,0x00000368}, - {"0000001000010011111100001111111010011001000110100010000010100100",0x00003386,0xFFFFE9CE,0x00000515,0x00002422,0xFFFFF1F3,0x00000405,0x00002422,0xFFFFF1F3,0x00000405}, - {"0000001000010011111100001111111010011001001011000101000011100100",0x000032FB,0xFFFFE9BC,0x00000520,0x00002301,0xFFFFF267,0x000003F7,0x00002301,0xFFFFF267,0x000003F7}, - {"0000001000010011111100001111111010011001001100100010100100100100",0x000032C2,0xFFFFEAC0,0x000004EA,0x0000250F,0xFFFFF1A2,0x00000413,0x0000250F,0xFFFFF1A2,0x00000413}, - {"0000001000010011111100001111111010011001000111000010100101000100",0x00003722,0xFFFFE8A6,0x00000527,0x000026E4,0xFFFFF0F5,0x0000041C,0x000026E4,0xFFFFF0F5,0x0000041C}, - {"0000001000010011111100001111111010011001001011000100100011000100",0x000035A4,0xFFFFE822,0x00000558,0x000022F2,0xFFFFF288,0x000003E8,0x000022F2,0xFFFFF288,0x000003E8}, - {"0000001000010011111100001111111010011001001010000000100100100100",0x00002CD1,0xFFFFEDC6,0x0000048C,0x00001EAF,0xFFFFF53D,0x00000396,0x00001EAF,0xFFFFF53D,0x00000396}, - {"0000001000010011111100001111111010011001001100000001000101100100",0x00003156,0xFFFFEA60,0x0000050B,0x00001BBC,0xFFFFF704,0x00000335,0x00001BBC,0xFFFFF704,0x00000335}, - {"0000001000010011111100001111111010011001001011000101000100000100",0x000034A1,0xFFFFE8C0,0x00000544,0x00002528,0xFFFFF105,0x0000042C,0x00002528,0xFFFFF105,0x0000042C}, - {"0000001000010011111100001111111010011001001100100011000001100100",0x000032CE,0xFFFFE9D3,0x00000520,0x000021FF,0xFFFFF2FD,0x000003E4,0x000021FF,0xFFFFF2FD,0x000003E4}, - {"0000001000010011111100001111111010011001000110100101000010100100",0x000034A0,0xFFFFE823,0x0000056D,0x0000256F,0xFFFFF047,0x0000045A,0x0000256F,0xFFFFF047,0x0000045A}, - {"0000001000010011111100001111111010011001001100000011100101000100",0x00003109,0xFFFFEBD6,0x000004BF,0x000022D4,0xFFFFF32D,0x000003D0,0x000022D4,0xFFFFF32D,0x000003D0}, - {"0000001000010011111100001111111010011001001011000001000101100100",0x000030B7,0xFFFFEAF0,0x000004F3,0x00001AEC,0xFFFFF7A9,0x0000031B,0x00001AEC,0xFFFFF7A9,0x0000031B}, - {"0000001000010011111100001111111010011001001011000011100110100100",0x00003078,0xFFFFEBA4,0x000004CF,0x00001E7A,0xFFFFF5AF,0x0000036B,0x00001E7A,0xFFFFF5AF,0x0000036B}, - {"0000001000010011111100001111111010011001001100000100000100100100",0x00003442,0xFFFFE998,0x00000518,0x000025EA,0xFFFFF0F3,0x0000042B,0x000025EA,0xFFFFF0F3,0x0000042B}, - {"0000001000010011111100001111111010011001001100000010000110100100",0x000031CB,0xFFFFEA80,0x00000501,0x000020A3,0xFFFFF403,0x000003B2,0x000020A3,0xFFFFF403,0x000003B2}, - {"0000001000010011111100001111111010011001001010100010100110000100",0x00002947,0xFFFFF018,0x00000433,0x00001BA5,0xFFFFF75C,0x00000340,0x00001BA5,0xFFFFF75C,0x00000340}, - {"0000001000010011111100001111111010011001001011000011100110000100",0x000033F9,0xFFFFE99D,0x00000518,0x00002231,0xFFFFF358,0x000003C5,0x00002231,0xFFFFF358,0x000003C5}, - {"0000001000010011111100001111111010011001001100100001000100100100",0x00003131,0xFFFFEA45,0x00000513,0x00001973,0xFFFFF85E,0x00000301,0x00001973,0xFFFFF85E,0x00000301}, - {"0000001000010011111100001111111010011001000111000010100110100100",0x00003571,0xFFFFE8AC,0x00000539,0x00002049,0xFFFFF49C,0x0000038D,0x00002049,0xFFFFF49C,0x0000038D}, - {"0000001000010011111100001111111010011001001011100011100001100100",0x0000309E,0xFFFFEB1D,0x000004E8,0x000019ED,0xFFFFF86E,0x000002F8,0x000019ED,0xFFFFF86E,0x000002F8}, - {"0000001000010011111100001111111010011001001100000010100110000100",0x00003091,0xFFFFEB9B,0x000004CC,0x00001D2C,0xFFFFF6A2,0x0000033D,0x00001D2C,0xFFFFF6A2,0x0000033D}, - {"0000001000010011111100001111111010011001001100000000100011100100",0x00003069,0xFFFFEAFD,0x000004F8,0x00001E82,0xFFFFF51C,0x0000038D,0x00001E82,0xFFFFF51C,0x0000038D}, - {"0000001000010011111100001111111010011001001000100001000010100100",0x00003459,0xFFFFE7F2,0x00000572,0x00001DA7,0xFFFFF552,0x0000037F,0x00001DA7,0xFFFFF552,0x0000037F}, - {"0000001000010011111100001111111010011001001100100001000100000100",0x0000304B,0xFFFFEAFB,0x000004F4,0x0000191E,0xFFFFF8BD,0x000002EE,0x0000191E,0xFFFFF8BD,0x000002EE}, - {"0000001000010011111100001111111010011001001100000010000011000100",0x0000346E,0xFFFFEA07,0x000004FD,0x00002767,0xFFFFF058,0x00000440,0x00002767,0xFFFFF058,0x00000440}, - {"0000001000010011111100001111111010011001001011100011000010000100",0x000030B5,0xFFFFEBC1,0x000004C1,0x00001B3C,0xFFFFF818,0x000002FD,0x00001B3C,0xFFFFF818,0x000002FD}, - {"0000001000010011111100001111111010011001001100000000100100000100",0x0000321F,0xFFFFE9EA,0x00000524,0x00002380,0xFFFFF1C2,0x0000041A,0x00002380,0xFFFFF1C2,0x0000041A}, - {"0000001000010011111100001111111010011001001011100011000001000100",0x000030DF,0xFFFFEB37,0x000004E2,0x00001E3C,0xFFFFF5BB,0x00000369,0x00001E3C,0xFFFFF5BB,0x00000369}, - {"0000001000010011111100001111111010011001001010000100100010100100",0x000027E0,0xFFFFF0E2,0x00000416,0x00001A6A,0xFFFFF820,0x00000321,0x00001A6A,0xFFFFF820,0x00000321}, - {"0000001000010011111100001111111010011001000110100001000010000100",0x00002FA1,0xFFFFEB63,0x000004E7,0x0000196B,0xFFFFF880,0x000002FB,0x0000196B,0xFFFFF880,0x000002FB}, - {"0000001000010011111100001111111010011001000111000001000010000100",0x0000310C,0xFFFFEAAF,0x000004FC,0x000019EF,0xFFFFF850,0x000002FD,0x000019EF,0xFFFFF850,0x000002FD}, - {"0000001000010011111100001111111010011001001100100011100100000100",0x0000334A,0xFFFFEA07,0x0000050B,0x00002380,0xFFFFF26F,0x000003F0,0x00002380,0xFFFFF26F,0x000003F0}, - {"0000001000010011111100001111111010011001001100000010100101000100",0x00002FF9,0xFFFFECDC,0x00000492,0x00002297,0xFFFFF394,0x000003BF,0x00002297,0xFFFFF394,0x000003BF}, - {"0000001000010011111100001111111010011001001011000010000101100100",0x0000354B,0xFFFFE894,0x00000546,0x000024C4,0xFFFFF16C,0x0000041B,0x000024C4,0xFFFFF16C,0x0000041B}, - {"0000001000010011111100001111111010011001001000100000100100100100",0x00003245,0xFFFFE92F,0x00000544,0x00001829,0xFFFFF8F1,0x000002EA,0x00001829,0xFFFFF8F1,0x000002EA}, - {"0000001000010011111100001111111010011001001011100100100010000100",0x0000302F,0xFFFFEB51,0x000004E3,0x0000199F,0xFFFFF894,0x000002F4,0x0000199F,0xFFFFF894,0x000002F4}, - {"0000001000010011111100001111111010011001001011100001100011000100",0x00002F54,0xFFFFEC86,0x000004A6,0x00001A6F,0xFFFFF891,0x000002EC,0x00001A6F,0xFFFFF891,0x000002EC}, - {"0000001000010011111100001111111010011001001010000100000101100100",0x00002908,0xFFFFF0D8,0x0000040A,0x00001C9B,0xFFFFF729,0x00000342,0x00001C9B,0xFFFFF729,0x00000342}, - {"0000001000010011111100001111111010011001001100000010100101100100",0x000031D9,0xFFFFEB40,0x000004D7,0x000023F5,0xFFFFF259,0x000003F4,0x000023F5,0xFFFFF259,0x000003F4}, - {"0000001000010011111100001111111010011001001100000100100011100100",0x000034C8,0xFFFFE8C6,0x0000053F,0x00002313,0xFFFFF280,0x000003EC,0x00002313,0xFFFFF280,0x000003EC}, - {"0000001000010011111100001111111010011001001100000101000011000100",0x000037D1,0xFFFFE6A1,0x0000059C,0x00002C6A,0xFFFFEBFF,0x00000504,0x00002C6A,0xFFFFEBFF,0x00000504}, - {"0000001000010011111100001111111010011001001100100001100101100100",0x000030E9,0xFFFFEA6B,0x0000050F,0x00001A2D,0xFFFFF7DF,0x00000316,0x00001A2D,0xFFFFF7DF,0x00000316}, - {"0000001000010011111100001111111010011001001100000010000010000100",0x0000323D,0xFFFFEA95,0x000004F4,0x00001ED2,0xFFFFF584,0x0000036C,0x00001ED2,0xFFFFF584,0x0000036C}, - {"0000001000010011111100001111111010011001001011000011000000100100",0x000033D6,0xFFFFE9DB,0x00000510,0x000027A7,0xFFFFEFC7,0x0000045E,0x000027A7,0xFFFFEFC7,0x0000045E}, - {"0000001000010011111100001111111010011001000111000011000101100100",0x00003444,0xFFFFE98A,0x00000517,0x000020FD,0xFFFFF43F,0x0000039D,0x000020FD,0xFFFFF43F,0x0000039D}, - {"0000001000010011111100001111111010011001001010000000100011100100",0x00002987,0xFFFFEFA1,0x0000044B,0x00001B06,0xFFFFF788,0x0000033C,0x00001B06,0xFFFFF788,0x0000033C}, - {"0000001000010011111100001111111010011001001011000010100011100100",0x0000311D,0xFFFFED20,0x00000474,0x000025DA,0xFFFFF223,0x000003F0,0x000025DA,0xFFFFF223,0x000003F0}, - {"0000001000010011111100001111111010011001001011000001000100100100",0x000032A2,0xFFFFEA0A,0x0000050D,0x00001D48,0xFFFFF659,0x0000034A,0x00001D48,0xFFFFF659,0x0000034A}, - {"0000001000010011111100001111111010011001001000100000100011100100",0x00003110,0xFFFFE9EA,0x00000529,0x00001786,0xFFFFF958,0x000002DB,0x00001786,0xFFFFF958,0x000002DB}, - {"0000001000010011111100001111111010011001001010000010000110100100",0x000027F2,0xFFFFF174,0x000003F7,0x00001C7A,0xFFFFF72A,0x00000348,0x00001C7A,0xFFFFF72A,0x00000348}, - {"0000001000010011111100001111111010011001000111000001000011100100",0x000031DB,0xFFFFEA7D,0x000004FB,0x000019C4,0xFFFFF8B1,0x000002E6,0x000019C4,0xFFFFF8B1,0x000002E6}, - {"0000001000010011111100001111111010011001001011000001000100000100",0x00003158,0xFFFFEAAC,0x000004FA,0x00001BC1,0xFFFFF737,0x0000032B,0x00001BC1,0xFFFFF737,0x0000032B}, - {"0000001000010011111100001111111010011001001100000001000011000100",0x00002F36,0xFFFFEBF9,0x000004CA,0x00001A2A,0xFFFFF83F,0x00000303,0x00001A2A,0xFFFFF83F,0x00000303}, - {"0000001000010011111100001111111010011001001100100011100010100100",0x000032B4,0xFFFFEA72,0x000004FA,0x000021FF,0xFFFFF378,0x000003C5,0x000021FF,0xFFFFF378,0x000003C5}, - {"0000001000010011111100001111111010011001001100000011000101100100",0x00003262,0xFFFFEAFA,0x000004DF,0x00002441,0xFFFFF237,0x000003F6,0x00002441,0xFFFFF237,0x000003F6}, - {"0000001000010011111100001111111010011001001100000011100100100100",0x0000336A,0xFFFFEAFB,0x000004D1,0x00002746,0xFFFFF0B8,0x0000042B,0x00002746,0xFFFFF0B8,0x0000042B}, - {"0000001000010011111100001111111010011001000110100100000010000100",0x000032E5,0xFFFFE923,0x00000541,0x00001DF0,0xFFFFF552,0x00000380,0x00001DF0,0xFFFFF552,0x00000380}, - {"0000001000010011111100001111111010011001001100000100000001100100",0x000035D1,0xFFFFE80B,0x0000055F,0x00002780,0xFFFFEF74,0x0000046F,0x00002780,0xFFFFEF74,0x0000046F}, - {"0000001000010011111100001111111010011001001100000010100010100100",0x000033EC,0xFFFFEA48,0x000004F4,0x0000269F,0xFFFFF0D8,0x0000042A,0x0000269F,0xFFFFF0D8,0x0000042A}, - {"0000001000010011111100001111111010011001001100100011100010000100",0x000030C4,0xFFFFEB39,0x000004E2,0x00001B44,0xFFFFF7AA,0x00000318,0x00001B44,0xFFFFF7AA,0x00000318}, - {"0000001000010011111100001111111010011001001010000001000101000100",0x00002926,0xFFFFF0AF,0x0000040E,0x0000194E,0xFFFFF959,0x000002E2,0x0000194E,0xFFFFF959,0x000002E2}, - {"0000001000010011111100001111111010011001001011000001000011000100",0x00003141,0xFFFFEAAF,0x000004F6,0x00001864,0xFFFFF97C,0x000002C6,0x00001864,0xFFFFF97C,0x000002C6}, - {"0000001000010011111100001111111010011001001100000001000001100100",0x000030B2,0xFFFFEB7C,0x000004DB,0x000022CE,0xFFFFF2B5,0x000003F0,0x000022CE,0xFFFFF2B5,0x000003F0}, - {"0000001000010011111100001111111010011001001100000001100101000100",0x0000318C,0xFFFFEAC7,0x000004F6,0x00002113,0xFFFFF3CA,0x000003BD,0x00002113,0xFFFFF3CA,0x000003BD}, - {"0000001000010011111100001111111010011001001011100001000100000100",0x00002FD2,0xFFFFEB8F,0x000004D9,0x00001996,0xFFFFF89F,0x000002F1,0x00001996,0xFFFFF89F,0x000002F1}, - {"0000001000010011111100001111111010011001000110100010100010100100",0x0000310D,0xFFFFEB25,0x000004E7,0x00001F67,0xFFFFF4EF,0x0000038E,0x00001F67,0xFFFFF4EF,0x0000038E}, - {"0000001000010011111100001111111010011001001010100100100101100100",0x00002BBC,0xFFFFEE68,0x00000477,0x00002050,0xFFFFF41D,0x000003C8,0x00002050,0xFFFFF41D,0x000003C8}, - {"0000001000010011111100001111111010011001001100000010000100000100",0x00003096,0xFFFFECED,0x00000486,0x000024C9,0xFFFFF278,0x000003E7,0x000024C9,0xFFFFF278,0x000003E7}, - {"0000001000010011111100001111111010011001001011000001000010100100",0x00003401,0xFFFFE8F1,0x0000053C,0x00001E75,0xFFFFF55C,0x00000376,0x00001E75,0xFFFFF55C,0x00000376}, - {"0000001000010011111100001111111010011001001100000010100001000100",0x0000319E,0xFFFFEAB1,0x000004F8,0x00001EA3,0xFFFFF567,0x00000378,0x00001EA3,0xFFFFF567,0x00000378}, - {"0000001000010011111100001111111010011001001100100010100101100100",0x000030FD,0xFFFFEB4C,0x000004DB,0x00001CA6,0xFFFFF6E8,0x00000335,0x00001CA6,0xFFFFF6E8,0x00000335}, - {"0000001000010011111100001111111010011001001011100100000010100100",0x000030D6,0xFFFFEB1A,0x000004E4,0x00001A0D,0xFFFFF87D,0x000002EF,0x00001A0D,0xFFFFF87D,0x000002EF}, - {"0000001000010011111100001111111010011001001011000010000100100100",0x0000324B,0xFFFFEB17,0x000004D9,0x00002225,0xFFFFF3A8,0x000003BA,0x00002225,0xFFFFF3A8,0x000003BA}, - {"0000001000010011111100001111111010011001001010000100000010000100",0x00002A00,0xFFFFF02E,0x00000424,0x00001E21,0xFFFFF61D,0x0000036C,0x00001E21,0xFFFFF61D,0x0000036C}, - {"0000001000010011111100001111111010011001001010100100100010100100",0x000029CF,0xFFFFEF53,0x00000457,0x00001B11,0xFFFFF772,0x0000033D,0x00001B11,0xFFFFF772,0x0000033D}, - {"0000001000010011111100001111111010011001000110100011000010100100",0x000032A1,0xFFFFEA63,0x000004FB,0x00001F83,0xFFFFF516,0x0000037E,0x00001F83,0xFFFFF516,0x0000037E}, - {"0000001000010011111100001111111010011001001011100010000011000100",0x0000305C,0xFFFFEC14,0x000004B5,0x00001D0B,0xFFFFF6ED,0x00000332,0x00001D0B,0xFFFFF6ED,0x00000332}, - {"0000001000010011111100001111111010011001001011000001000001100100",0x00003467,0xFFFFE8D5,0x00000543,0x0000243F,0xFFFFF190,0x00000418,0x0000243F,0xFFFFF190,0x00000418}, - {"0000001000010011111100001111111010011001001010100010000001100100",0x00002796,0xFFFFF133,0x00000409,0x00001903,0xFFFFF91C,0x000002FC,0x00001903,0xFFFFF91C,0x000002FC}, - {"0000001000010011111100001111111010011001001100000010000101100100",0x000031F6,0xFFFFEAB7,0x000004F5,0x000022B9,0xFFFFF2D0,0x000003E6,0x000022B9,0xFFFFF2D0,0x000003E6}, - {"0000001000010011111100001111111010011001001011100101000100000100",0x00003196,0xFFFFEA76,0x00000503,0x00001CC5,0xFFFFF67D,0x0000034A,0x00001CC5,0xFFFFF67D,0x0000034A}, - {"0000001000010011111100001111111010011001001100100001000101000100",0x00002F9E,0xFFFFEAD9,0x00000505,0x000017C1,0xFFFFF93D,0x000002DF,0x000017C1,0xFFFFF93D,0x000002DF}, - {"0000001000010011111100001111111010011001001011100010000100100100",0x00002FBC,0xFFFFEC75,0x000004A8,0x00001D6D,0xFFFFF6AC,0x0000033D,0x00001D6D,0xFFFFF6AC,0x0000033D}, - {"0000001000010011111100001111111010011001001011000011100010100100",0x00003541,0xFFFFE921,0x00000524,0x00002662,0xFFFFF0CB,0x0000042B,0x00002662,0xFFFFF0CB,0x0000042B}, - {"0000001000010011111100001111111010011001001010100010000110100100",0x00002953,0xFFFFEF76,0x00000459,0x00001C05,0xFFFFF6A0,0x00000368,0x00001C05,0xFFFFF6A0,0x00000368}, - {"0000001000010011111100001111111010011001001011000100100100100100",0x000034BC,0xFFFFE8DD,0x00000536,0x0000210E,0xFFFFF3F4,0x000003A8,0x0000210E,0xFFFFF3F4,0x000003A8}, - {"0000001000010011111100001111111010011001001011000010100110100100",0x000034BE,0xFFFFE916,0x0000052F,0x000024A1,0xFFFFF1A6,0x00000410,0x000024A1,0xFFFFF1A6,0x00000410}, - {"0000001000010011111100001111111010011001001100000100100101100100",0x000037B5,0xFFFFE7A9,0x0000055B,0x000028A1,0xFFFFEF51,0x00000467,0x000028A1,0xFFFFEF51,0x00000467}, - {"0000001000010011111100001111111010011001001100000001000100000100",0x00002FC5,0xFFFFEBBE,0x000004D1,0x00001BA5,0xFFFFF757,0x00000328,0x00001BA5,0xFFFFF757,0x00000328}, - {"0000001000010011111100001111111010011001001100000100000010100100",0x000033CB,0xFFFFE944,0x0000052B,0x00001FBE,0xFFFFF4B1,0x0000038C,0x00001FBE,0xFFFFF4B1,0x0000038C}, - {"0000001000010011111100001111111010011001001100000001100001000100",0x000030AE,0xFFFFEBA0,0x000004D3,0x00002268,0xFFFFF316,0x000003DD,0x00002268,0xFFFFF316,0x000003DD}, - {"0000001000010011111100001111111010011001001011000010000010100100",0x00002F90,0xFFFFEC5A,0x000004B0,0x00001C3A,0xFFFFF752,0x00000323,0x00001C3A,0xFFFFF752,0x00000323}, - {"0000001000010011111100001111111010011001001011100011100011100100",0x00003113,0xFFFFEB91,0x000004C8,0x00001E3C,0xFFFFF623,0x0000034E,0x00001E3C,0xFFFFF623,0x0000034E}, - {"0000001000010011111100001111111010011001001100100011100110000100",0x0000330B,0xFFFFE94B,0x00000539,0x000020E7,0xFFFFF37E,0x000003CD,0x000020E7,0xFFFFF37E,0x000003CD}, - {"0000001000010011111100001111111010011001001011100010100001100100",0x000031D1,0xFFFFEACB,0x000004ED,0x00001E82,0xFFFFF5B2,0x00000365,0x00001E82,0xFFFFF5B2,0x00000365}, - {"0000001000010011111100001111111010011001001010100011100110000100",0x00002CD5,0xFFFFEDC1,0x0000048D,0x000020F8,0xFFFFF3C1,0x000003D1,0x000020F8,0xFFFFF3C1,0x000003D1}, - { NULL ,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000,0x000} +static const struct phm_fuses_default vega10_fuses_default[] = { + { 0x0213EA94DE0E4964, 0x00003C96, 0xFFFFE226, 0x00000656, 0x00002203, 0xFFFFF201, 0x000003FF, 0x00002203, 0xFFFFF201, 0x000003FF }, + { 0x0213EA94DE0A1884, 0x00003CC5, 0xFFFFE23A, 0x0000064E, 0x00002258, 0xFFFFF1F7, 0x000003FC, 0x00002258, 0xFFFFF1F7, 0x000003FC }, + { 0x0213EA94DE0E31A4, 0x00003CAF, 0xFFFFE36E, 0x00000602, 0x00001E98, 0xFFFFF569, 0x00000357, 0x00001E98, 0xFFFFF569, 0x00000357 }, + { 0x0213EA94DE2C1144, 0x0000391A, 0xFFFFE548, 0x000005C9, 0x00001B98, 0xFFFFF707, 0x00000324, 0x00001B98, 0xFFFFF707, 0x00000324 }, + { 0x0213EA94DE2C18C4, 0x00003821, 0xFFFFE674, 0x00000597, 0x00002196, 0xFFFFF361, 0x000003C0, 0x00002196, 0xFFFFF361, 0x000003C0 }, + { 0x0213EA94DE263884, 0x000044A2, 0xFFFFDCB7, 0x00000738, 0x0000325C, 0xFFFFE6A7, 0x000005E6, 0x0000325C, 0xFFFFE6A7, 0x000005E6 }, + { 0x0213EA94DE082924, 0x00004057, 0xFFFFE1CF, 0x0000063C, 0x00002E2E, 0xFFFFEB62, 0x000004FD, 0x00002E2E, 0xFFFFEB62, 0x000004FD }, + { 0x0213EA94DE284924, 0x00003FD0, 0xFFFFDF0F, 0x000006E5, 0x0000267C, 0xFFFFEE2D, 0x000004AB, 0x0000267C, 0xFFFFEE2D, 0x000004AB }, + { 0x0213EA94DE280904, 0x00003F13, 0xFFFFE010, 0x000006AD, 0x000020E7, 0xFFFFF266, 0x000003EC, 0x000020E7, 0xFFFFF266, 0x000003EC }, + { 0x0213EA94DE082044, 0x00004088, 0xFFFFDFAB, 0x000006B6, 0x0000252B, 0xFFFFEFDB, 0x00000458, 0x0000252B, 0xFFFFEFDB, 0x00000458 }, + { 0x0213EA94DE283884, 0x00003EF6, 0xFFFFE017, 0x000006AA, 0x00001F67, 0xFFFFF369, 0x000003BE, 0x00001F67, 0xFFFFF369, 0x000003BE }, + { 0x0213EA94DE2C2184, 0x00003CDD, 0xFFFFE2A7, 0x0000063C, 0x000026C6, 0xFFFFEF38, 0x00000478, 0x000026C6, 0xFFFFEF38, 0x00000478 }, + { 0x0213EA94DE105124, 0x00003FA8, 0xFFFFDF02, 0x000006F0, 0x000027FE, 0xFFFFECF6, 0x000004EA, 0x000027FE, 0xFFFFECF6, 0x000004EA }, + { 0x0213EA94DE2638C4, 0x00004670, 0xFFFFDC40, 0x00000742, 0x00003A7A, 0xFFFFE1A7, 0x000006B6, 0x00003A7A, 0xFFFFE1A7, 0x000006B6 }, + { 0x0213EA94DE2C3024, 0x00003CDC, 0xFFFFE18C, 0x00000683, 0x00002A69, 0xFFFFEBE7, 0x00000515, 0x00002A69, 0xFFFFEBE7, 0x00000515 }, + { 0x0213EA94DE0E38C4, 0x00003CEC, 0xFFFFE38E, 0x00000601, 0x00002752, 0xFFFFEFA7, 0x00000453, 0x00002752, 0xFFFFEFA7, 0x00000453 }, + { 0x0213EA94DE2C1124, 0x000037D0, 0xFFFFE634, 0x000005A7, 0x00001CD2, 0xFFFFF644, 0x00000348, 0x00001CD2, 0xFFFFF644, 0x00000348 }, + { 0x0213EA94DE283964, 0x00003DF5, 0xFFFFE0A5, 0x00000698, 0x00001FD5, 0xFFFFF30E, 0x000003D1, 0x00001FD5, 0xFFFFF30E, 0x000003D1 }, + { 0x0213EA94DE0828C4, 0x00004201, 0xFFFFE03E, 0x00000688, 0x00003206, 0xFFFFE852, 0x0000058A, 0x00003206, 0xFFFFE852, 0x0000058A }, + { 0x0213EA94DE2C1864, 0x00003BED, 0xFFFFE2F5, 0x00000638, 0x0000270D, 0xFFFFEED0, 0x0000048E, 0x0000270D, 0xFFFFEED0, 0x0000048E }, + { 0x0213EA94DE0A1904, 0x00003E82, 0xFFFFE1BE, 0x00000654, 0x000025FB, 0xFFFFEFFA, 0x00000448, 0x000025FB, 0xFFFFEFFA, 0x00000448 }, + { 0x0213EA94DE2C40C4, 0x00003962, 0xFFFFE4B9, 0x000005EF, 0x00002385, 0xFFFFF156, 0x00000423, 0x00002385, 0xFFFFF156, 0x00000423 }, + { 0x0213EA94DE2C0944, 0x00003D88, 0xFFFFE21A, 0x00000655, 0x0000295A, 0xFFFFED68, 0x000004C4, 0x0000295A, 0xFFFFED68, 0x000004C4 }, + { 0x0213EA94DE2C1104, 0x00003AA4, 0xFFFFE4A3, 0x000005E0, 0x000022EF, 0xFFFFF250, 0x000003EB, 0x000022EF, 0xFFFFF250, 0x000003EB }, + { 0x0213EA94DE0E29A4, 0x00003D97, 0xFFFFE30D, 0x0000060D, 0x0000205D, 0xFFFFF45D, 0x00000380, 0x0000205D, 0xFFFFF45D, 0x00000380 }, + { 0x0213EA94DE2C40A4, 0x000039B6, 0xFFFFE446, 0x00000605, 0x00002325, 0xFFFFF16C, 0x0000041F, 0x00002325, 0xFFFFF16C, 0x0000041F }, + { 0x0213EA94DE263904, 0x0000457E, 0xFFFFDCF6, 0x00000722, 0x00003972, 0xFFFFE27B, 0x0000068E, 0x00003972, 0xFFFFE27B, 0x0000068E }, + { 0x0213EA94DE0A1924, 0x00003FB8, 0xFFFFE101, 0x00000670, 0x00002787, 0xFFFFEEF5, 0x00000471, 0x00002787, 0xFFFFEEF5, 0x00000471 }, + { 0x0213EA94DE0E38A4, 0x00003BB2, 0xFFFFE430, 0x000005EA, 0x000024A5, 0xFFFFF162, 0x00000409, 0x000024A5, 0xFFFFF162, 0x00000409 }, + { 0x0213EA94DE082144, 0x00003EC5, 0xFFFFE1BD, 0x0000064F, 0x000022F0, 0xFFFFF227, 0x000003E8, 0x000022F0, 0xFFFFF227, 0x000003E8 }, + { 0x0213EA94DE2C3164, 0x000038A7, 0xFFFFE59F, 0x000005C1, 0x000021CC, 0xFFFFF2DF, 0x000003D9, 0x000021CC, 0xFFFFF2DF, 0x000003D9 }, + { 0x0213EA94DE324184, 0x00002995, 0xFFFFEF7A, 0x0000044C, 0x00001552, 0xFFFFFB5D, 0x00000292, 0x00001552, 0xFFFFFB5D, 0x00000292 }, + { 0x0213EA94DE2C4064, 0x00003B26, 0xFFFFE2D3, 0x00000649, 0x000023B4, 0xFFFFF09B, 0x00000449, 0x000023B4, 0xFFFFF09B, 0x00000449 }, + { 0x0213EA94DE081124, 0x000040D2, 0xFFFFE00A, 0x00000696, 0x000022DA, 0xFFFFF1E9, 0x000003F2, 0x000022DA, 0xFFFFF1E9, 0x000003F2 }, + { 0x0213EA94DE2C3924, 0x00003C98, 0xFFFFE365, 0x00000618, 0x00002D5D, 0xFFFFEB3A, 0x0000051D, 0x00002D5D, 0xFFFFEB3A, 0x0000051D }, + { 0x0213EA94DE2C10A4, 0x00003BBD, 0xFFFFE37E, 0x00000617, 0x0000252E, 0xFFFFF06E, 0x00000441, 0x0000252E, 0xFFFFF06E, 0x00000441 }, + { 0x0213EA94DE262924, 0x00004363, 0xFFFFDF7A, 0x000006A0, 0x000031F5, 0xFFFFE880, 0x0000057B, 0x000031F5, 0xFFFFE880, 0x0000057B }, + { 0x0213EA94DE0E3844, 0x00003CFC, 0xFFFFE2AF, 0x0000062E, 0x0000212A, 0xFFFFF335, 0x000003BF, 0x0000212A, 0xFFFFF335, 0x000003BF }, + { 0x0213EA94DE1C4924, 0x0000252D, 0xFFFFF31B, 0x000003C3, 0x00001A1A, 0xFFFFF882, 0x00000325, 0x00001A1A, 0xFFFFF882, 0x00000325 }, + { 0x0213EA94DE0A29A4, 0x00003FE2, 0xFFFFDFEF, 0x000006AC, 0x000025A2, 0xFFFFEF84, 0x00000462, 0x000025A2, 0xFFFFEF84, 0x00000462 }, + { 0x0213EA94DE0820E4, 0x000040A5, 0xFFFFE13B, 0x0000065B, 0x00002C13, 0xFFFFEC75, 0x000004D7, 0x00002C13, 0xFFFFEC75, 0x000004D7 }, + { 0x0213EA94DE0E48A4, 0x00003E42, 0xFFFFE1B3, 0x00000657, 0x0000221D, 0xFFFFF273, 0x000003DE, 0x0000221D, 0xFFFFF273, 0x000003DE }, + { 0x0213EA94DE0A20E4, 0x00003E7F, 0xFFFFE255, 0x00000638, 0x00002D30, 0xFFFFEB8A, 0x00000503, 0x00002D30, 0xFFFFEB8A, 0x00000503 }, + { 0x0213EA94DE2C29C4, 0x00003E56, 0xFFFFE16D, 0x00000670, 0x000028DC, 0xFFFFEDA0, 0x000004BA, 0x000028DC, 0xFFFFEDA0, 0x000004BA }, + { 0x0213EA94DE2630A4, 0x000044AD, 0xFFFFDE24, 0x000006DD, 0x000031AD, 0xFFFFE850, 0x00000585, 0x000031AD, 0xFFFFE850, 0x00000585 }, + { 0x0213EA94DE2C20E4, 0x00003AF3, 0xFFFFE5B0, 0x000005A6, 0x00002CF6, 0xFFFFEC75, 0x000004DD, 0x00002CF6, 0xFFFFEC75, 0x000004DD }, + { 0x0213EA94DE0A2084, 0x00003E66, 0xFFFFE19E, 0x0000065B, 0x00002332, 0xFFFFF1B9, 0x000003FD, 0x00002332, 0xFFFFF1B9, 0x000003FD }, + { 0x0213EA94DE082884, 0x00003FB4, 0xFFFFE0A5, 0x00000686, 0x0000253E, 0xFFFFF02E, 0x00000444, 0x0000253E, 0xFFFFF02E, 0x00000444 }, + { 0x0213EA94DE2818A4, 0x00003E28, 0xFFFFE14D, 0x0000066E, 0x00001FE2, 0xFFFFF39A, 0x000003B1, 0x00001FE2, 0xFFFFF39A, 0x000003B1 }, + { 0x0213EA94DE2C0904, 0x000039E6, 0xFFFFE44B, 0x000005FE, 0x0000210C, 0xFFFFF2F4, 0x000003DA, 0x0000210C, 0xFFFFF2F4, 0x000003DA }, + { 0x0213EA94DE2C5104, 0x00003A4D, 0xFFFFE252, 0x0000067A, 0x000027E2, 0xFFFFECED, 0x000004FA, 0x000027E2, 0xFFFFECED, 0x000004FA }, + { 0x0213EA94DE0A2964, 0x00004065, 0xFFFFE02F, 0x0000069B, 0x0000299D, 0xFFFFED38, 0x000004C2, 0x0000299D, 0xFFFFED38, 0x000004C2 }, + { 0x0213EA94DE0E20A4, 0x000039EE, 0xFFFFE603, 0x00000594, 0x0000214F, 0xFFFFF429, 0x0000038E, 0x0000214F, 0xFFFFF429, 0x0000038E }, + { 0x0213EA94DE0E48E4, 0x00003BD2, 0xFFFFE351, 0x00000618, 0x000020B8, 0xFFFFF377, 0x000003B4, 0x000020B8, 0xFFFFF377, 0x000003B4 }, + { 0x0213EA94DE0A3124, 0x00003FAA, 0xFFFFE183, 0x0000065E, 0x000032AE, 0xFFFFE7C2, 0x000005A6, 0x000032AE, 0xFFFFE7C2, 0x000005A6 }, + { 0x0213EA94DE2C2984, 0x00003AFB, 0xFFFFE3E4, 0x00000608, 0x00002293, 0xFFFFF21F, 0x000003FA, 0x00002293, 0xFFFFF21F, 0x000003FA }, + { 0x0213EA94DE262064, 0x0000448B, 0xFFFFDD5D, 0x0000070D, 0x00002E4E, 0xFFFFE9DF, 0x00000551, 0x00002E4E, 0xFFFFE9DF, 0x00000551 }, + { 0x0213EA94DE0E2184, 0x00003D46, 0xFFFFE39B, 0x000005F3, 0x0000218E, 0xFFFFF3CD, 0x00000398, 0x0000218E, 0xFFFFF3CD, 0x00000398 }, + { 0x0213EA94DE0848E4, 0x00003F01, 0xFFFFDFD9, 0x000006BF, 0x000023AF, 0xFFFFF04E, 0x0000044C, 0x000023AF, 0xFFFFF04E, 0x0000044C }, + { 0x0213EA94DE1029A4, 0x0000403D, 0xFFFFDF6B, 0x000006C9, 0x0000270D, 0xFFFFEE4B, 0x0000049E, 0x0000270D, 0xFFFFEE4B, 0x0000049E }, + { 0x0213EA94DE0E3964, 0x00003C11, 0xFFFFE35C, 0x00000613, 0x000020F9, 0xFFFFF365, 0x000003B9, 0x000020F9, 0xFFFFF365, 0x000003B9 }, + { 0x0213EA94DE2C3884, 0x00003B58, 0xFFFFE37D, 0x0000061F, 0x00002698, 0xFFFFEF46, 0x00000478, 0x00002698, 0xFFFFEF46, 0x00000478 }, + { 0x0213EA94DE2841A4, 0x00003EBC, 0xFFFFDF7A, 0x000006D6, 0x0000212B, 0xFFFFF195, 0x0000041B, 0x0000212B, 0xFFFFF195, 0x0000041B }, + { 0x0213EA94DE0848C4, 0x00004050, 0xFFFFDEB3, 0x000006FE, 0x00002D6C, 0xFFFFE961, 0x00000582, 0x00002D6C, 0xFFFFE961, 0x00000582 }, + { 0x0213EA94DE262044, 0x000043F0, 0xFFFFDD9C, 0x00000702, 0x00002B31, 0xFFFFEBEA, 0x000004F7, 0x00002B31, 0xFFFFEBEA, 0x000004F7 }, + { 0x0213EA94DE100924, 0x00003EFA, 0xFFFFE093, 0x00000696, 0x000026DB, 0xFFFFEEB3, 0x00000489, 0x000026DB, 0xFFFFEEB3, 0x00000489 }, + { 0x0213EA94DE082064, 0x0000425D, 0xFFFFDE8D, 0x000006E6, 0x00002CA4, 0xFFFFEAD2, 0x00000531, 0x00002CA4, 0xFFFFEAD2, 0x00000531 }, + { 0x0213EA94DE2639A4, 0x000043B0, 0xFFFFDD03, 0x00000728, 0x00002946, 0xFFFFECA6, 0x000004DE, 0x00002946, 0xFFFFECA6, 0x000004DE }, + { 0x0213EA94DE282864, 0x00003F6A, 0xFFFFE03A, 0x0000069D, 0x00002208, 0xFFFFF1F8, 0x000003F6, 0x00002208, 0xFFFFF1F8, 0x000003F6 }, + { 0x0213EA94DE2C2964, 0x00003A94, 0xFFFFE4A7, 0x000005E2, 0x000024D0, 0xFFFFF100, 0x00000426, 0x000024D0, 0xFFFFF100, 0x00000426 }, + { 0x0213EA94DE2810C4, 0x00003F2F, 0xFFFFE0A3, 0x00000688, 0x00002198, 0xFFFFF271, 0x000003E2, 0x00002198, 0xFFFFF271, 0x000003E2 }, + { 0x0213EA94DE1048E4, 0x00003EA5, 0xFFFFE032, 0x000006AE, 0x0000227C, 0xFFFFF130, 0x00000426, 0x0000227C, 0xFFFFF130, 0x00000426 }, + { 0x0213EA94DE264144, 0x0000442F, 0xFFFFDBC4, 0x0000078B, 0x00003CD6, 0xFFFFDE6C, 0x0000076C, 0x00003CD6, 0xFFFFDE6C, 0x0000076C }, + { 0x0213EA94DE282884, 0x00003DDE, 0xFFFFE174, 0x00000668, 0x00001FF4, 0xFFFFF38F, 0x000003B1, 0x00001FF4, 0xFFFFF38F, 0x000003B1 }, + { 0x0213EA94DE0A3144, 0x000040B0, 0xFFFFE016, 0x000006A0, 0x00002DBB, 0xFFFFEA7F, 0x00000537, 0x00002DBB, 0xFFFFEA7F, 0x00000537 }, + { 0x0213EA94DE2C3104, 0x00003429, 0xFFFFEA97, 0x000004DD, 0x000024D5, 0xFFFFF26F, 0x000003DF, 0x000024D5, 0xFFFFF26F, 0x000003DF }, + { 0x0213EA94DE0E1904, 0x00003AEB, 0xFFFFE590, 0x000005A3, 0x000022CB, 0xFFFFF347, 0x000003B2, 0x000022CB, 0xFFFFF347, 0x000003B2 }, + { 0x0213EA94DE283904, 0x00003B8E, 0xFFFFE2EF, 0x00000636, 0x00002351, 0xFFFFF143, 0x0000041C, 0x00002351, 0xFFFFF143, 0x0000041C }, + { 0x0213EA94DE3240C4, 0x00002926, 0xFFFFF0B0, 0x00000410, 0x0000194E, 0xFFFFF94E, 0x000002E9, 0x0000194E, 0xFFFFF94E, 0x000002E9 }, + { 0x0213EA94DE283184, 0x0000402B, 0xFFFFDF78, 0x000006C2, 0x00002273, 0xFFFFF16C, 0x00000414, 0x00002273, 0xFFFFF16C, 0x00000414 }, + { 0x0213EA94DE0A10A4, 0x00003D6A, 0xFFFFE1D3, 0x00000659, 0x00002006, 0xFFFFF394, 0x000003B1, 0x00002006, 0xFFFFF394, 0x000003B1 }, + { 0x0213EA94DE284064, 0x00004042, 0xFFFFDFD8, 0x000006A8, 0x00002135, 0xFFFFF29F, 0x000003D9, 0x00002135, 0xFFFFF29F, 0x000003D9 }, + { 0x0213EA94DE0820A4, 0x0000405B, 0xFFFFE093, 0x00000682, 0x0000288F, 0xFFFFEE3A, 0x00000491, 0x0000288F, 0xFFFFEE3A, 0x00000491 }, + { 0x0213EA94DE2C48A4, 0x00003A49, 0xFFFFE30C, 0x00000648, 0x000023F9, 0xFFFFF02D, 0x00000460, 0x000023F9, 0xFFFFF02D, 0x00000460 }, + { 0x0213EA94DE282964, 0x00003D59, 0xFFFFE1CC, 0x0000065B, 0x00002013, 0xFFFFF37D, 0x000003B6, 0x00002013, 0xFFFFF37D, 0x000003B6 }, + { 0x0213EA94DE2C3984, 0x000040C1, 0xFFFFDF8C, 0x000006CA, 0x00003271, 0xFFFFE6CA, 0x000005EA, 0x00003271, 0xFFFFE6CA, 0x000005EA }, + { 0x0213EA94DE2620E4, 0x000042E9, 0xFFFFDFDC, 0x0000068C, 0x00002ED9, 0xFFFFEAAF, 0x0000051B, 0x00002ED9, 0xFFFFEAAF, 0x0000051B }, + { 0x0213EA94DE083084, 0x000042ED, 0xFFFFDE50, 0x000006F0, 0x00002FCF, 0xFFFFE8BB, 0x0000058C, 0x00002FCF, 0xFFFFE8BB, 0x0000058C }, + { 0x0213EA94DE0A4104, 0x00003EBD, 0xFFFFE099, 0x00000698, 0x00002709, 0xFFFFEE7B, 0x00000495, 0x00002709, 0xFFFFEE7B, 0x00000495 }, + { 0x0213EA94DE284904, 0x00003F71, 0xFFFFDF82, 0x000006C9, 0x0000219B, 0xFFFFF1AD, 0x0000040F, 0x0000219B, 0xFFFFF1AD, 0x0000040F }, + { 0x0213EA94DE2808E4, 0x00003E73, 0xFFFFE080, 0x0000069B, 0x000020E7, 0xFFFFF273, 0x000003E9, 0x000020E7, 0xFFFFF273, 0x000003E9 }, + { 0x0213EA94DE0E3184, 0x00003E14, 0xFFFFE278, 0x0000062C, 0x00002275, 0xFFFFF2B3, 0x000003CE, 0x00002275, 0xFFFFF2B3, 0x000003CE }, + { 0x0213EA94DE2C21A4, 0x00003ABB, 0xFFFFE3B9, 0x00000615, 0x00002192, 0xFFFFF28F, 0x000003EB, 0x00002192, 0xFFFFF28F, 0x000003EB }, + { 0x0213EA94DE283124, 0x00003D53, 0xFFFFE255, 0x00000643, 0x0000275B, 0xFFFFEEED, 0x00000479, 0x0000275B, 0xFFFFEEED, 0x00000479 }, + { 0x0213EA94DE262864, 0x000043E3, 0xFFFFDDC3, 0x000006FB, 0x00002B6B, 0xFFFFEBD6, 0x000004FA, 0x00002B6B, 0xFFFFEBD6, 0x000004FA }, + { 0x0213EA94DE0E2144, 0x00003BDE, 0xFFFFE507, 0x000005B4, 0x000022CE, 0xFFFFF358, 0x000003AB, 0x000022CE, 0xFFFFF358, 0x000003AB }, + { 0x0213EA94DE323164, 0x00002460, 0xFFFFF3B5, 0x000003A2, 0x000014E7, 0xFFFFFC32, 0x0000027C, 0x000014E7, 0xFFFFFC32, 0x0000027C }, + { 0x0213EA94DE2820C4, 0x00003D20, 0xFFFFE298, 0x0000062F, 0x00002080, 0xFFFFF3AF, 0x000003A8, 0x00002080, 0xFFFFF3AF, 0x000003A8 }, + { 0x0213EA94DE081904, 0x00003E14, 0xFFFFE221, 0x00000641, 0x000021BB, 0xFFFFF2EA, 0x000003CA, 0x000021BB, 0xFFFFF2EA, 0x000003CA }, + { 0x0213EA94DE0A40C4, 0x00003DE1, 0xFFFFE14E, 0x00000677, 0x00002468, 0xFFFFF068, 0x00000440, 0x00002468, 0xFFFFF068, 0x00000440 }, + { 0x0213EA94DE261084, 0x00004372, 0xFFFFDDF8, 0x000006F5, 0x00002B3F, 0xFFFFEBE8, 0x000004F8, 0x00002B3F, 0xFFFFEBE8, 0x000004F8 }, + { 0x0213EA94DE0A28C4, 0x00003E4F, 0xFFFFE2A3, 0x0000062B, 0x00002F5A, 0xFFFFEA37, 0x0000053B, 0x00002F5A, 0xFFFFEA37, 0x0000053B }, + { 0x0213EA94DE2850E4, 0x00003E07, 0xFFFFE02F, 0x000006B6, 0x0000216B, 0xFFFFF1A3, 0x00000416, 0x0000216B, 0xFFFFF1A3, 0x00000416 }, + { 0x0213EA94DE2838A4, 0x00003DAB, 0xFFFFE128, 0x0000067F, 0x0000216F, 0xFFFFF236, 0x000003F3, 0x0000216F, 0xFFFFF236, 0x000003F3 }, + { 0x0213EA94DE2C2924, 0x0000364B, 0xFFFFE8CB, 0x0000052A, 0x00002568, 0xFFFFF1B2, 0x00000400, 0x00002568, 0xFFFFF1B2, 0x00000400 }, + { 0x0213EA94DE261064, 0x00004219, 0xFFFFDE87, 0x000006E8, 0x00002C59, 0xFFFFEAEE, 0x00000529, 0x00002C59, 0xFFFFEAEE, 0x00000529 }, + { 0x0213EA94DE0E1944, 0x000039A8, 0xFFFFE602, 0x00000594, 0x00001D06, 0xFFFFF6F0, 0x00000316, 0x00001D06, 0xFFFFF6F0, 0x00000316 }, + { 0x0213EA94DE2610E4, 0x00004052, 0xFFFFE01C, 0x00000698, 0x00002310, 0xFFFFF1A1, 0x000003FE, 0x00002310, 0xFFFFF1A1, 0x000003FE }, + { 0x0213EA94DE0E2824, 0x00003C1C, 0xFFFFE3EB, 0x000005F1, 0x00002289, 0xFFFFF2CF, 0x000003C9, 0x00002289, 0xFFFFF2CF, 0x000003C9 }, + { 0x0213EA94DE0E5124, 0x00003F19, 0xFFFFE085, 0x0000069E, 0x00002B94, 0xFFFFEB72, 0x0000051D, 0x00002B94, 0xFFFFEB72, 0x0000051D }, + { 0x0213EA94DE0E41A4, 0x00003C51, 0xFFFFE2AD, 0x00000638, 0x0000206B, 0xFFFFF361, 0x000003BE, 0x0000206B, 0xFFFFF361, 0x000003BE }, + { 0x0213EA94DE2610C4, 0x000040B9, 0xFFFFDFBB, 0x000006AB, 0x0000241F, 0xFFFFF0CC, 0x00000425, 0x0000241F, 0xFFFFF0CC, 0x00000425 }, + { 0x0213EA94DE0A2064, 0x00003E62, 0xFFFFE12C, 0x00000678, 0x00002445, 0xFFFFF09E, 0x00000435, 0x00002445, 0xFFFFF09E, 0x00000435 }, + { 0x0213EA94DE0E1984, 0x00003C97, 0xFFFFE399, 0x000005FB, 0x0000209D, 0xFFFFF41D, 0x0000038F, 0x0000209D, 0xFFFFF41D, 0x0000038F }, + { 0x0213EA94DE0E3144, 0x00003FF9, 0xFFFFE1E9, 0x0000063E, 0x00002E96, 0xFFFFEAF5, 0x00000516, 0x00002E96, 0xFFFFEAF5, 0x00000516 }, + { 0x0213EA94DE0A3084, 0x00003F04, 0xFFFFE109, 0x0000067A, 0x000026E1, 0xFFFFEF0B, 0x00000476, 0x000026E1, 0xFFFFEF0B, 0x00000476 }, + { 0x0213EA94DE101124, 0x00003E3E, 0xFFFFE187, 0x00000660, 0x00002049, 0xFFFFF38D, 0x000003B0, 0x00002049, 0xFFFFF38D, 0x000003B0 }, + { 0x0213EA94DE282944, 0x00003D58, 0xFFFFE253, 0x0000063D, 0x00002158, 0xFFFFF308, 0x000003C3, 0x00002158, 0xFFFFF308, 0x000003C3 }, + { 0x0213EA94DE0840C4, 0x00004074, 0xFFFFDF8D, 0x000006C0, 0x00002799, 0xFFFFEE19, 0x000004A5, 0x00002799, 0xFFFFEE19, 0x000004A5 }, + { 0x0213EA94DE281924, 0x00003DAF, 0xFFFFE1C9, 0x00000659, 0x000020E5, 0xFFFFF313, 0x000003C6, 0x000020E5, 0xFFFFF313, 0x000003C6 }, + { 0x0213EA94DE0A3964, 0x000041DD, 0xFFFFDDFA, 0x0000071B, 0x0000348D, 0xFFFFE4B4, 0x0000064C, 0x0000348D, 0xFFFFE4B4, 0x0000064C }, + { 0x0213EA94DE2C2884, 0x00003947, 0xFFFFE5AE, 0x000005B8, 0x000024A6, 0xFFFFF140, 0x0000041D, 0x000024A6, 0xFFFFF140, 0x0000041D }, + { 0x0213EA94DE101844, 0x00003D35, 0xFFFFE197, 0x0000066E, 0x00002248, 0xFFFFF1BC, 0x00000408, 0x00002248, 0xFFFFF1BC, 0x00000408 }, + { 0x0213EA94DE0A18E4, 0x00003F4F, 0xFFFFE13E, 0x0000066D, 0x00002AF0, 0xFFFFEC99, 0x000004DB, 0x00002AF0, 0xFFFFEC99, 0x000004DB }, + { 0x0213EA94DE263944, 0x0000430F, 0xFFFFDDFB, 0x000006FC, 0x00002D4D, 0xFFFFEA55, 0x00000540, 0x00002D4D, 0xFFFFEA55, 0x00000540 }, + { 0x0213EA94DE0E2944, 0x00003B22, 0xFFFFE543, 0x000005B1, 0x000022E1, 0xFFFFF31B, 0x000003B9, 0x000022E1, 0xFFFFF31B, 0x000003B9 }, + { 0x0213EA94DE0E2084, 0x00003978, 0xFFFFE611, 0x00000592, 0x00001C36, 0xFFFFF771, 0x00000302, 0x00001C36, 0xFFFFF771, 0x00000302 }, + { 0x0213EA94DE262164, 0x000044DF, 0xFFFFDDAB, 0x000006F2, 0x00002CEA, 0xFFFFEB47, 0x00000507, 0x00002CEA, 0xFFFFEB47, 0x00000507 }, + { 0x0213EA94DE0A38C4, 0x00003E9B, 0xFFFFE12C, 0x0000067C, 0x00002B79, 0xFFFFEBD9, 0x00000503, 0x00002B79, 0xFFFFEBD9, 0x00000503 }, + { 0x0213EA94DE263044, 0x00004464, 0xFFFFDCD3, 0x00000731, 0x00002D14, 0xFFFFEA2D, 0x0000054E, 0x00002D14, 0xFFFFEA2D, 0x0000054E }, + { 0x0213EA94DE281124, 0x00003FB3, 0xFFFFE052, 0x00000693, 0x000020AC, 0xFFFFF311, 0x000003C6, 0x000020AC, 0xFFFFF311, 0x000003C6 }, + { 0x0213EA94DE2C1084, 0x00003BDA, 0xFFFFE2FB, 0x00000636, 0x0000261E, 0xFFFFEF72, 0x00000471, 0x0000261E, 0xFFFFEF72, 0x00000471 }, + { 0x0213EA94DE2C1964, 0x00003D72, 0xFFFFE28A, 0x0000063E, 0x000029D8, 0xFFFFED54, 0x000004C7, 0x000029D8, 0xFFFFED54, 0x000004C7 }, + { 0x0213EA94DE2C2824, 0x00003E26, 0xFFFFE102, 0x00000694, 0x00002DD1, 0xFFFFE9CA, 0x0000056D, 0x00002DD1, 0xFFFFE9CA, 0x0000056D }, + { 0x0213EA94DE104124, 0x000041CD, 0xFFFFDE97, 0x000006ED, 0x00002DE5, 0xFFFFE9B9, 0x00000565, 0x00002DE5, 0xFFFFE9B9, 0x00000565 }, + { 0x0213EA94DE0A2984, 0x00003F30, 0xFFFFE06E, 0x00000698, 0x000024FF, 0xFFFFEFFC, 0x0000044F, 0x000024FF, 0xFFFFEFFC, 0x0000044F }, + { 0x0213EA94DE2C38C4, 0x0000378B, 0xFFFFE6B4, 0x00000594, 0x000023A7, 0xFFFFF1DC, 0x00000407, 0x000023A7, 0xFFFFF1DC, 0x00000407 }, + { 0x0213EA94DE0E4164, 0x00003CD7, 0xFFFFE28D, 0x00000636, 0x00002036, 0xFFFFF3B5, 0x000003AA, 0x00002036, 0xFFFFF3B5, 0x000003AA }, + { 0x0213EA94DE0A3884, 0x00003EF9, 0xFFFFE0AA, 0x0000068D, 0x000024D3, 0xFFFFF02F, 0x00000445, 0x000024D3, 0xFFFFF02F, 0x00000445 }, + { 0x0213EA94DE283944, 0x00003D08, 0xFFFFE1BB, 0x00000665, 0x00002159, 0xFFFFF26F, 0x000003E6, 0x00002159, 0xFFFFF26F, 0x000003E6 }, + { 0x0213EA94DE2C20C4, 0x000038A9, 0xFFFFE6CA, 0x00000580, 0x000025D3, 0xFFFFF101, 0x00000421, 0x000025D3, 0xFFFFF101, 0x00000421 }, + { 0x0213EA94DE0A20A4, 0x00003E45, 0xFFFFE1F8, 0x0000064D, 0x000027E3, 0xFFFFEEBB, 0x0000047F, 0x000027E3, 0xFFFFEEBB, 0x0000047F }, + { 0x0213EA94DE0E3864, 0x00003F76, 0xFFFFE128, 0x0000066E, 0x0000286B, 0xFFFFEE4C, 0x00000493, 0x0000286B, 0xFFFFEE4C, 0x00000493 }, + { 0x0213EA94DE264104, 0x0000440D, 0xFFFFDCA2, 0x0000074F, 0x00003817, 0xFFFFE256, 0x000006AF, 0x00003817, 0xFFFFE256, 0x000006AF }, + { 0x0213EA94DE105104, 0x00003EE1, 0xFFFFDFA7, 0x000006D4, 0x000027EA, 0xFFFFED2B, 0x000004DE, 0x000027EA, 0xFFFFED2B, 0x000004DE }, + { 0x0213EA94DE2C3864, 0x00003C62, 0xFFFFE285, 0x0000064A, 0x00002520, 0xFFFFF001, 0x0000045C, 0x00002520, 0xFFFFF001, 0x0000045C }, + { 0x0213EA94DE323964, 0x0000272E, 0xFFFFF17A, 0x000003FA, 0x0000150B, 0xFFFFFBD5, 0x00000284, 0x0000150B, 0xFFFFFBD5, 0x00000284 }, + { 0x0213EA94DE261924, 0x00004275, 0xFFFFDF69, 0x000006A5, 0x000025AA, 0xFFFFF05C, 0x0000042B, 0x000025AA, 0xFFFFF05C, 0x0000042B }, + { 0x0213EA94DE0E40E4, 0x00003CAA, 0xFFFFE392, 0x000005FF, 0x000023A8, 0xFFFFF20E, 0x000003E9, 0x000023A8, 0xFFFFF20E, 0x000003E9 }, + { 0x0213EA94DE2C50C4, 0x00003CF8, 0xFFFFE0FB, 0x000006A6, 0x00002CA7, 0xFFFFE9FF, 0x0000056E, 0x00002CA7, 0xFFFFE9FF, 0x0000056E }, + { 0x0213EA94DE282124, 0x00003D00, 0xFFFFE296, 0x00000633, 0x000021C1, 0xFFFFF2C8, 0x000003CF, 0x000021C1, 0xFFFFF2C8, 0x000003CF }, + { 0x0213EA94DE2838E4, 0x00003B46, 0xFFFFE301, 0x00000632, 0x0000204C, 0xFFFFF33B, 0x000003C8, 0x0000204C, 0xFFFFF33B, 0x000003C8 }, + { 0x0213EA94DE204164, 0x00002026, 0xFFFFF5CE, 0x00000368, 0x00001598, 0xFFFFFB29, 0x000002C3, 0x00001598, 0xFFFFFB29, 0x000002C3 }, + { 0x0213EA94DE283164, 0x00003DCA, 0xFFFFE178, 0x00000668, 0x00001FDB, 0xFFFFF39D, 0x000003AF, 0x00001FDB, 0xFFFFF39D, 0x000003AF }, + { 0x0213EA94DE2C48C4, 0x00003A59, 0xFFFFE327, 0x00000642, 0x000024B9, 0xFFFFEFC4, 0x00000471, 0x000024B9, 0xFFFFEFC4, 0x00000471 }, + { 0x0213EA94DE2C2944, 0x00003C26, 0xFFFFE440, 0x000005EB, 0x00002C0F, 0xFFFFEC88, 0x000004E0, 0x00002C0F, 0xFFFFEC88, 0x000004E0 }, + { 0x0213EA94DE083884, 0x00004149, 0xFFFFDEB8, 0x000006E7, 0x0000280A, 0xFFFFED89, 0x000004C2, 0x0000280A, 0xFFFFED89, 0x000004C2 }, + { 0x0213EA94DE0E4124, 0x00003EB4, 0xFFFFE1E5, 0x0000064D, 0x0000299F, 0xFFFFEDB3, 0x000004A9, 0x0000299F, 0xFFFFEDB3, 0x000004A9 }, + { 0x0213EA94DE2C39A4, 0x00003BBF, 0xFFFFE268, 0x0000065A, 0x00002504, 0xFFFFEFB0, 0x00000470, 0x00002504, 0xFFFFEFB0, 0x00000470 }, + { 0x0213EA94DE084904, 0x00004203, 0xFFFFDDC6, 0x00000720, 0x0000303B, 0xFFFFE78F, 0x000005D0, 0x0000303B, 0xFFFFE78F, 0x000005D0 }, + { 0x0213EA94DE0E3984, 0x00003DA3, 0xFFFFE244, 0x0000063E, 0x000021B4, 0xFFFFF2DA, 0x000003CD, 0x000021B4, 0xFFFFF2DA, 0x000003CD }, + { 0x0213EA94DE0A38E4, 0x00004035, 0xFFFFE065, 0x0000069B, 0x00003323, 0xFFFFE6D6, 0x000005D8, 0x00003323, 0xFFFFE6D6, 0x000005D8 }, + { 0x0213EA94DE2C1164, 0x00003944, 0xFFFFE4E5, 0x000005E2, 0x00001F3C, 0xFFFFF456, 0x0000039D, 0x00001F3C, 0xFFFFF456, 0x0000039D }, + { 0x0213EA94DE061904, 0x000032D8, 0xFFFFEAE8, 0x000004E6, 0x00001812, 0xFFFFFA1C, 0x000002BC, 0x00001812, 0xFFFFFA1C, 0x000002BC }, + { 0x0213F0FD42D22944, 0x000041F6, 0xFFFFE025, 0x0000069A, 0x0000241E, 0xFFFFF1B4, 0x00000402, 0x0000241E, 0xFFFFF1B4, 0x00000402 }, + { 0x0213F0FE990C30A4, 0x00003300, 0xFFFFEB60, 0x000004C1, 0x00001E15, 0xFFFFF6A6, 0x0000033B, 0x00001E15, 0xFFFFF6A6, 0x0000033B }, + { 0x0213EA94DE0408A4, 0x000037F0, 0xFFFFE68F, 0x0000059B, 0x00001F8A, 0xFFFFF467, 0x000003A3, 0x00001F8A, 0xFFFFF467, 0x000003A3 }, + { 0x0213F0FE99182984, 0x000025D8, 0xFFFFF2AA, 0x000003C3, 0x000018A8, 0xFFFFF9BE, 0x000002D2, 0x000018A8, 0xFFFFF9BE, 0x000002D2 }, + { 0x0213F0FE990620C4, 0x0000364F, 0xFFFFE988, 0x000004FC, 0x00001E51, 0xFFFFF633, 0x0000034F, 0x00001E51, 0xFFFFF633, 0x0000034F }, + { 0x0213EA94DE061144, 0x00002288, 0xFFFFF483, 0x0000036C, 0x0000280F, 0xFFFFEF39, 0x0000047B, 0x0000280F, 0xFFFFEF39, 0x0000047B }, + { 0x0213F0FE99082084, 0x00003322, 0xFFFFEA7E, 0x000004ED, 0x00001DAD, 0xFFFFF62B, 0x00000355, 0x00001DAD, 0xFFFFF62B, 0x00000355 }, + { 0x0213EA94DE0250E4, 0x00002B7B, 0xFFFFEE4F, 0x0000045B, 0x00001AA2, 0xFFFFF710, 0x0000033E, 0x00001AA2, 0xFFFFF710, 0x0000033E }, + { 0x0213F0FE990420C4, 0x000034CC, 0xFFFFEA79, 0x000004E4, 0x00001B05, 0xFFFFF8B3, 0x000002EC, 0x00001B05, 0xFFFFF8B3, 0x000002EC }, + { 0x0213F0FD42DC2864, 0x00003837, 0xFFFFE5ED, 0x000005C3, 0x00001ACB, 0xFFFFF7B2, 0x00000314, 0x00001ACB, 0xFFFFF7B2, 0x00000314 }, + { 0x0213F0FE99044164, 0x0000352D, 0xFFFFE88F, 0x00000548, 0x000021E6, 0xFFFFF3B5, 0x000003AA, 0x000021E6, 0xFFFFF3B5, 0x000003AA }, + { 0x0213F0FE990A4884, 0x00003300, 0xFFFFE835, 0x0000057B, 0x00001A85, 0xFFFFF715, 0x00000336, 0x00001A85, 0xFFFFF715, 0x00000336 }, + { 0x0213EA94DE0448A4, 0x000033FA, 0xFFFFE851, 0x00000565, 0x00001A8E, 0xFFFFF727, 0x0000033B, 0x00001A8E, 0xFFFFF727, 0x0000033B }, + { 0x0213F0FD42DA3924, 0x000039D3, 0xFFFFE5D3, 0x000005B0, 0x00001888, 0xFFFFF978, 0x000002C8, 0x00001888, 0xFFFFF978, 0x000002C8 }, + { 0x0213F0FE990E4864, 0x00002F6B, 0xFFFFEC53, 0x000004B9, 0x00001C15, 0xFFFFF71B, 0x00000337, 0x00001C15, 0xFFFFF71B, 0x00000337 }, + { 0x0213F0FE99064144, 0x0000384D, 0xFFFFE737, 0x00000569, 0x00001D2D, 0xFFFFF673, 0x00000343, 0x00001D2D, 0xFFFFF673, 0x00000343 }, + { 0x0213F0FE990620A4, 0x00003A49, 0xFFFFE70B, 0x0000055F, 0x00001A63, 0xFFFFF8CD, 0x000002E2, 0x00001A63, 0xFFFFF8CD, 0x000002E2 }, + { 0x0213F0FE99042984, 0x0000311E, 0xFFFFEB97, 0x000004C6, 0x00001EAE, 0xFFFFF5A9, 0x00000367, 0x00001EAE, 0xFFFFF5A9, 0x00000367 }, + { 0x0213F0FE990E1124, 0x000027D3, 0xFFFFF075, 0x00000417, 0x00002001, 0xFFFFF44A, 0x000003A2, 0x00002001, 0xFFFFF44A, 0x000003A2 }, + { 0x0213F0FE99064904, 0x00003B72, 0xFFFFE4BD, 0x000005DC, 0x00001D76, 0xFFFFF606, 0x0000035A, 0x00001D76, 0xFFFFF606, 0x0000035A }, + { 0x0213F0FE99101124, 0x00002E0F, 0xFFFFECA7, 0x000004AE, 0x00001DC6, 0xFFFFF5BF, 0x0000036A, 0x00001DC6, 0xFFFFF5BF, 0x0000036A }, + { 0x0213F0FE990238A4, 0x000032C7, 0xFFFFEA7A, 0x000004F0, 0x00001A7B, 0xFFFFF827, 0x00000301, 0x00001A7B, 0xFFFFF827, 0x00000301 }, + { 0x0213EA94DE044884, 0x0000312D, 0xFFFFEA39, 0x00000515, 0x00001948, 0xFFFFF800, 0x00000318, 0x00001948, 0xFFFFF800, 0x00000318 }, + { 0x0213EA94DE062084, 0x00003611, 0xFFFFE8D7, 0x00000533, 0x00001929, 0xFFFFF965, 0x000002D2, 0x00001929, 0xFFFFF965, 0x000002D2 }, + { 0x0213F0FE992C30E4, 0x00002FE2, 0xFFFFED89, 0x00000470, 0x00001A3C, 0xFFFFF955, 0x000002D5, 0x00001A3C, 0xFFFFF955, 0x000002D5 }, + { 0x0213EA94DE0208A4, 0x000035FF, 0xFFFFE884, 0x00000548, 0x0000182A, 0xFFFFF9AB, 0x000002CF, 0x0000182A, 0xFFFFF9AB, 0x000002CF }, + { 0x0213F0FE990220E4, 0x00003597, 0xFFFFE904, 0x00000528, 0x00001A94, 0xFFFFF840, 0x00000300, 0x00001A94, 0xFFFFF840, 0x00000300 }, + { 0x0213F0FE99181944, 0x000026CB, 0xFFFFF1FB, 0x000003E4, 0x000017CC, 0xFFFFFA25, 0x000002C8, 0x000017CC, 0xFFFFFA25, 0x000002C8 }, + { 0x0213EA94DE0608C4, 0x00003274, 0xFFFFEA39, 0x0000050C, 0x00001B20, 0xFFFFF7C1, 0x00000314, 0x00001B20, 0xFFFFF7C1, 0x00000314 }, + { 0x0213F0FD42D82924, 0x0000280B, 0xFFFFF283, 0x000003B5, 0x000018D0, 0xFFFFF992, 0x000002EC, 0x000018D0, 0xFFFFF992, 0x000002EC }, + { 0x0213F0FE99062104, 0x000033AB, 0xFFFFEB1B, 0x000004C4, 0x00001FEE, 0xFFFFF53A, 0x00000378, 0x00001FEE, 0xFFFFF53A, 0x00000378 }, + { 0x0213F0FE990A3964, 0x00002F79, 0xFFFFEB0C, 0x000004FA, 0x00001E57, 0xFFFFF4BF, 0x0000039B, 0x00001E57, 0xFFFFF4BF, 0x0000039B }, + { 0x0213F0FE990448E4, 0x00003487, 0xFFFFE8F2, 0x00000539, 0x0000185B, 0xFFFFF9AE, 0x000002BA, 0x0000185B, 0xFFFFF9AE, 0x000002BA }, + { 0x0213F0FE990A18A4, 0x00003500, 0xFFFFE793, 0x0000058A, 0x00001AA2, 0xFFFFF792, 0x0000031D, 0x00001AA2, 0xFFFFF792, 0x0000031D }, + { 0x0213F0FE99081164, 0x00003943, 0xFFFFE54D, 0x000005D9, 0x00001BC8, 0xFFFFF6E0, 0x00000339, 0x00001BC8, 0xFFFFF6E0, 0x00000339 }, + { 0x0213EA94DE0430A4, 0x0000306D, 0xFFFFEC5E, 0x000004A5, 0x00001A3A, 0xFFFFF85F, 0x00000304, 0x00001A3A, 0xFFFFF85F, 0x00000304 }, + { 0x0213F0FD42D83084, 0x00002BA4, 0xFFFFEE8D, 0x0000046A, 0x0000198C, 0xFFFFF88E, 0x00000307, 0x0000198C, 0xFFFFF88E, 0x00000307 }, + { 0x0213F0FD42D218E4, 0x00003D30, 0xFFFFE2F6, 0x0000062A, 0x000025DC, 0xFFFFF074, 0x00000435, 0x000025DC, 0xFFFFF074, 0x00000435 }, + { 0x0213F0FD42D83964, 0x00002CD6, 0xFFFFED79, 0x0000049B, 0x000016D0, 0xFFFFFA53, 0x000002BB, 0x000016D0, 0xFFFFFA53, 0x000002BB }, + { 0x0213F0FE99163164, 0x00002484, 0xFFFFF3BD, 0x000003A0, 0x000015B8, 0xFFFFFB6B, 0x000002A4, 0x000015B8, 0xFFFFFB6B, 0x000002A4 }, + { 0x0213F0FE990E3944, 0x000038AE, 0xFFFFE6D1, 0x00000587, 0x00001A2A, 0xFFFFF8F1, 0x000002D4, 0x00001A2A, 0xFFFFF8F1, 0x000002D4 }, + { 0x0213F0FE99044944, 0x000036FD, 0xFFFFE76C, 0x00000576, 0x00001EE4, 0xFFFFF58D, 0x00000361, 0x00001EE4, 0xFFFFF58D, 0x00000361 }, + { 0x0213F0FD42D830A4, 0x00002BCF, 0xFFFFEF28, 0x00000448, 0x00001B93, 0xFFFFF7BA, 0x00000327, 0x00001B93, 0xFFFFF7BA, 0x00000327 }, + { 0x0213F0FE99062884, 0x00003834, 0xFFFFE818, 0x0000053B, 0x00001AFE, 0xFFFFF85C, 0x000002F3, 0x00001AFE, 0xFFFFF85C, 0x000002F3 }, + { 0x0213F0FE993231A4, 0x00002EF7, 0xFFFFEBFC, 0x000004CE, 0x00001897, 0xFFFFF8EF, 0x000002EC, 0x00001897, 0xFFFFF8EF, 0x000002EC }, + { 0x0213F0FE992C18C4, 0x000035BD, 0xFFFFE8BB, 0x0000053B, 0x00001F22, 0xFFFFF561, 0x00000373, 0x00001F22, 0xFFFFF561, 0x00000373 }, + { 0x0213F0FE99183984, 0x00002D42, 0xFFFFEE1D, 0x00000478, 0x000016F0, 0xFFFFFAAE, 0x000002B3, 0x000016F0, 0xFFFFFAAE, 0x000002B3 }, + { 0x0213EA94DE045124, 0x00002F98, 0xFFFFEB3C, 0x000004F0, 0x00001903, 0xFFFFF818, 0x00000319, 0x00001903, 0xFFFFF818, 0x00000319 }, + { 0x0213F0FD42D42144, 0x00004081, 0xFFFFDF13, 0x000006F3, 0x00002A6D, 0xFFFFEC1B, 0x00000509, 0x00002A6D, 0xFFFFEC1B, 0x00000509 }, + { 0x0213EA94DE040904, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001FF6, 0xFFFFF427, 0x000003B0, 0x00001FF6, 0xFFFFF427, 0x000003B0 }, + { 0x0213F0FE99023884, 0x00003243, 0xFFFFEA5C, 0x000004FD, 0x000020FB, 0xFFFFF39E, 0x000003C0, 0x000020FB, 0xFFFFF39E, 0x000003C0 }, + { 0x0213F0FD42D848A4, 0x00002F20, 0xFFFFEC19, 0x000004C6, 0x00001748, 0xFFFFF99F, 0x000002DA, 0x00001748, 0xFFFFF99F, 0x000002DA }, + { 0x0213F0FE99103984, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001A43, 0xFFFFF843, 0x000002F9, 0x00001A43, 0xFFFFF843, 0x000002F9 }, + { 0x0213F0FE990220A4, 0x0000396E, 0xFFFFE616, 0x000005A9, 0x00001A51, 0xFFFFF850, 0x000002FA, 0x00001A51, 0xFFFFF850, 0x000002FA }, + { 0x0213F0FE99043144, 0x0000305C, 0xFFFFED4B, 0x0000046C, 0x00001CF9, 0xFFFFF7BA, 0x00000304, 0x00001CF9, 0xFFFFF7BA, 0x00000304 }, + { 0x0213F0FD42DA4164, 0x0000343C, 0xFFFFE869, 0x00000559, 0x00001CE2, 0xFFFFF614, 0x00000359, 0x00001CE2, 0xFFFFF614, 0x00000359 }, + { 0x0213F0FE99183964, 0x00002782, 0xFFFFF1FE, 0x000003D9, 0x000015DC, 0xFFFFFB8B, 0x00000290, 0x000015DC, 0xFFFFFB8B, 0x00000290 }, + { 0x0213F0FE991818C4, 0x00002B9C, 0xFFFFEF63, 0x00000443, 0x00001369, 0xFFFFFD51, 0x00000244, 0x00001369, 0xFFFFFD51, 0x00000244 }, + { 0x0213F0FE990A2084, 0x000035F8, 0xFFFFE743, 0x00000592, 0x000018D8, 0xFFFFF8EE, 0x000002E4, 0x000018D8, 0xFFFFF8EE, 0x000002E4 }, + { 0x0213EA94DE062844, 0x00002B72, 0xFFFFEF1E, 0x0000043C, 0x00002647, 0xFFFFF092, 0x0000043E, 0x00002647, 0xFFFFF092, 0x0000043E }, + { 0x0213F0FE99102184, 0x00002EC9, 0xFFFFEC5F, 0x000004B8, 0x000018B6, 0xFFFFF936, 0x000002D8, 0x000018B6, 0xFFFFF936, 0x000002D8 }, + { 0x0213F0FE99064084, 0x000038A7, 0xFFFFE6AC, 0x00000589, 0x00001C42, 0xFFFFF70B, 0x00000329, 0x00001C42, 0xFFFFF70B, 0x00000329 }, + { 0x0213F0FE993008A4, 0x00002F6B, 0xFFFFEBF6, 0x000004CF, 0x000018AE, 0xFFFFF928, 0x000002E3, 0x000018AE, 0xFFFFF928, 0x000002E3 }, + { 0x0213F0FD42DA5104, 0x000029CD, 0xFFFFEEE1, 0x00000459, 0x00001AB5, 0xFFFFF76F, 0x00000324, 0x00001AB5, 0xFFFFF76F, 0x00000324 }, + { 0x0213EA94DE0638C4, 0x00003921, 0xFFFFE71D, 0x00000577, 0x00001646, 0xFFFFFB24, 0x00000293, 0x00001646, 0xFFFFFB24, 0x00000293 }, + { 0x0213EA94DE044164, 0x00003940, 0xFFFFE521, 0x000005E8, 0x00001947, 0xFFFFF839, 0x0000030D, 0x00001947, 0xFFFFF839, 0x0000030D }, + { 0x0213F0FD42D24164, 0x00003DCA, 0xFFFFE211, 0x00000659, 0x0000250E, 0xFFFFF072, 0x00000443, 0x0000250E, 0xFFFFF072, 0x00000443 }, + { 0x0213F0FE990C0904, 0x00002E95, 0xFFFFEC20, 0x000004C9, 0x000015B4, 0xFFFFFAD3, 0x0000029D, 0x000015B4, 0xFFFFFAD3, 0x0000029D }, + { 0x0213F0FE99041084, 0x00002C11, 0xFFFFEE6E, 0x00000468, 0x00001901, 0xFFFFF924, 0x000002E7, 0x00001901, 0xFFFFF924, 0x000002E7 }, + { 0x0213EA94DE062104, 0x0000293F, 0xFFFFF158, 0x000003E6, 0x0000183F, 0xFFFFF9F6, 0x000002D2, 0x0000183F, 0xFFFFF9F6, 0x000002D2 }, + { 0x0213F0FE990E1104, 0x00002A67, 0xFFFFEF34, 0x0000043E, 0x00001C6F, 0xFFFFF6F1, 0x0000032B, 0x00001C6F, 0xFFFFF6F1, 0x0000032B }, + { 0x0213EA94DE065124, 0x00002F8D, 0xFFFFEB77, 0x000004DA, 0x00001C0D, 0xFFFFF627, 0x00000365, 0x00001C0D, 0xFFFFF627, 0x00000365 }, + { 0x0213F0FE990C38C4, 0x00003476, 0xFFFFEA5B, 0x000004E7, 0x00001DBF, 0xFFFFF6C7, 0x00000333, 0x00001DBF, 0xFFFFF6C7, 0x00000333 }, + { 0x0213F0FE990E0944, 0x00003336, 0xFFFFE92F, 0x00000546, 0x00001614, 0xFFFFFAE0, 0x00000296, 0x00001614, 0xFFFFFAE0, 0x00000296 }, + { 0x0213F0FE99162164, 0x00002513, 0xFFFFF323, 0x000003BC, 0x000016DB, 0xFFFFFA79, 0x000002CD, 0x000016DB, 0xFFFFFA79, 0x000002CD }, + { 0x0213F0FE990A2944, 0x000035A7, 0xFFFFE78E, 0x00000584, 0x00001B0D, 0xFFFFF77D, 0x0000031F, 0x00001B0D, 0xFFFFF77D, 0x0000031F }, + { 0x0213F0FE993238E4, 0x00003171, 0xFFFFEB98, 0x000004C6, 0x00001C76, 0xFFFFF71F, 0x0000032F, 0x00001C76, 0xFFFFF71F, 0x0000032F }, + { 0x0213F0FD42DA1084, 0x00002C52, 0xFFFFED2E, 0x000004A7, 0x00002182, 0xFFFFF2F4, 0x000003E4, 0x00002182, 0xFFFFF2F4, 0x000003E4 }, + { 0x0213F0FE99102924, 0x000032E1, 0xFFFFEB39, 0x000004D0, 0x00001B55, 0xFFFFF859, 0x000002FA, 0x00001B55, 0xFFFFF859, 0x000002FA }, + { 0x0213F0FE991848A4, 0x000029B6, 0xFFFFEFF7, 0x00000430, 0x0000151B, 0xFFFFFBC6, 0x0000027F, 0x0000151B, 0xFFFFFBC6, 0x0000027F }, + { 0x0213F0FD42DA1964, 0x00002FF7, 0xFFFFEB67, 0x000004DA, 0x000020E9, 0xFFFFF363, 0x000003CE, 0x000020E9, 0xFFFFF363, 0x000003CE }, + { 0x0213F0FD42DA5124, 0x00003CDD, 0xFFFFE2B2, 0x00000649, 0x00001B18, 0xFFFFF739, 0x00000329, 0x00001B18, 0xFFFFF739, 0x00000329 }, + { 0x0213F0FE990628A4, 0x00003C82, 0xFFFFE5C6, 0x0000058E, 0x00001F3F, 0xFFFFF5AD, 0x00000361, 0x00001F3F, 0xFFFFF5AD, 0x00000361 }, + { 0x0213F0FD42DC4084, 0x0000319B, 0xFFFFEA15, 0x0000051B, 0x00001CC9, 0xFFFFF62E, 0x00000358, 0x00001CC9, 0xFFFFF62E, 0x00000358 }, + { 0x0213EA94DE0638E4, 0x000032B6, 0xFFFFEB2B, 0x000004D6, 0x000018E0, 0xFFFFF966, 0x000002DE, 0x000018E0, 0xFFFFF966, 0x000002DE }, + { 0x0213EA94DE023984, 0x0000300A, 0xFFFFEBA6, 0x000004D1, 0x00001CFD, 0xFFFFF5F6, 0x0000036D, 0x00001CFD, 0xFFFFF5F6, 0x0000036D }, + { 0x0213F0FD42D82984, 0x000026A9, 0xFFFFF15D, 0x00000400, 0x00001561, 0xFFFFFB1F, 0x000002A0, 0x00001561, 0xFFFFFB1F, 0x000002A0 }, + { 0x0213F0FE990E5124, 0x00003123, 0xFFFFEAD2, 0x000004FA, 0x000018CB, 0xFFFFF8F5, 0x000002EC, 0x000018CB, 0xFFFFF8F5, 0x000002EC }, + { 0x0213F0FE991840C4, 0x00003577, 0xFFFFE935, 0x00000533, 0x000016CD, 0xFFFFFB44, 0x00000289, 0x000016CD, 0xFFFFFB44, 0x00000289 }, + { 0x0213F0FE99282184, 0x00002875, 0xFFFFF170, 0x000003F3, 0x00001567, 0xFFFFFBD5, 0x00000289, 0x00001567, 0xFFFFFBD5, 0x00000289 }, + { 0x0213F0FE99084084, 0x00003AE2, 0xFFFFE538, 0x000005C1, 0x00001CB4, 0xFFFFF6A3, 0x0000033C, 0x00001CB4, 0xFFFFF6A3, 0x0000033C }, + { 0x0213F0FE990C38E4, 0x000031DF, 0xFFFFEC2A, 0x000004A3, 0x00001EF0, 0xFFFFF626, 0x00000352, 0x00001EF0, 0xFFFFF626, 0x00000352 }, + { 0x0213F0FD42D25144, 0x00004A6A, 0xFFFFDB15, 0x00000758, 0x000027F3, 0xFFFFEEEE, 0x00000479, 0x000027F3, 0xFFFFEEEE, 0x00000479 }, + { 0x0213EA94DE063904, 0x00002BB9, 0xFFFFEF5D, 0x00000433, 0x00001589, 0xFFFFFB57, 0x00000295, 0x00001589, 0xFFFFFB57, 0x00000295 }, + { 0x0213F0FE99042164, 0x000033A0, 0xFFFFE98F, 0x00000528, 0x00001CB4, 0xFFFFF706, 0x0000032D, 0x00001CB4, 0xFFFFF706, 0x0000032D }, + { 0x0213F0FE99163064, 0x0000248E, 0xFFFFF380, 0x000003AC, 0x000016EA, 0xFFFFFA6C, 0x000002CE, 0x000016EA, 0xFFFFFA6C, 0x000002CE }, + { 0x0213F0FE990221A4, 0x00002FE2, 0xFFFFEB2F, 0x000004E9, 0x00001D4E, 0xFFFFF56B, 0x00000380, 0x00001D4E, 0xFFFFF56B, 0x00000380 }, + { 0x0213F0FE990A2884, 0x00003283, 0xFFFFE9E7, 0x0000051D, 0x00000694, 0xFFFFFD32, 0x000003C3, 0x00000694, 0xFFFFFD32, 0x000003C3 }, + { 0x0213F0FD42D850C4, 0x00002EE4, 0xFFFFEBFD, 0x000004D3, 0x0000151A, 0xFFFFFAF6, 0x000002A4, 0x0000151A, 0xFFFFFAF6, 0x000002A4 }, + { 0x0213F0FD42DC18E4, 0x0000302D, 0xFFFFEB7F, 0x000004DA, 0x00001E6D, 0xFFFFF54B, 0x00000380, 0x00001E6D, 0xFFFFF54B, 0x00000380 }, + { 0x0213F0FD42DA50C4, 0x000033DA, 0xFFFFE7FB, 0x0000057F, 0x00001DED, 0xFFFFF50E, 0x0000038D, 0x00001DED, 0xFFFFF50E, 0x0000038D }, + { 0x0213F0FE992C4084, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001C3F, 0xFFFFF726, 0x0000032A, 0x00001C3F, 0xFFFFF726, 0x0000032A }, + { 0x0213F0FE990831C4, 0x00003BBD, 0xFFFFE55C, 0x000005B8, 0x000019DB, 0xFFFFF8BB, 0x000002EF, 0x000019DB, 0xFFFFF8BB, 0x000002EF }, + { 0x0213F0FE990E3884, 0x00002964, 0xFFFFF051, 0x0000040E, 0x000025CD, 0xFFFFF11B, 0x0000041F, 0x000025CD, 0xFFFFF11B, 0x0000041F }, + { 0x0213F0FD42DC4884, 0x000033F5, 0xFFFFE863, 0x00000560, 0x00001BCE, 0xFFFFF689, 0x0000034B, 0x00001BCE, 0xFFFFF689, 0x0000034B }, + { 0x0213F0FE990A2864, 0x00003294, 0xFFFFE924, 0x00000548, 0x00001D41, 0xFFFFF580, 0x0000037D, 0x00001D41, 0xFFFFF580, 0x0000037D }, + { 0x0213F0FD42DC39A4, 0x000034FB, 0xFFFFE7FE, 0x0000056D, 0x00001CB1, 0xFFFFF635, 0x00000357, 0x00001CB1, 0xFFFFF635, 0x00000357 }, + { 0x0213F0FE990A10A4, 0x00002E28, 0xFFFFEBB9, 0x000004E0, 0x00001B20, 0xFFFFF6E3, 0x0000033C, 0x00001B20, 0xFFFFF6E3, 0x0000033C }, + { 0x0213F0FD42DA1904, 0x00002799, 0xFFFFF0F4, 0x000003FC, 0x00001C9D, 0xFFFFF6A1, 0x00000345, 0x00001C9D, 0xFFFFF6A1, 0x00000345 }, + { 0x0213F0FE99064104, 0x00003AEA, 0xFFFFE5DB, 0x0000059D, 0x00001B61, 0xFFFFF7F0, 0x00000301, 0x00001B61, 0xFFFFF7F0, 0x00000301 }, + { 0x0213EA94DE041984, 0x000031F6, 0xFFFFEAB8, 0x000004F3, 0x00001D90, 0xFFFFF622, 0x00000359, 0x00001D90, 0xFFFFF622, 0x00000359 }, + { 0x0213F0FE990C4064, 0x000031B8, 0xFFFFEA61, 0x0000050F, 0x0000199D, 0xFFFFF87C, 0x000002FD, 0x0000199D, 0xFFFFF87C, 0x000002FD }, + { 0x0213F0FD42D23144, 0x00004514, 0xFFFFDDFF, 0x000006F6, 0x000022CD, 0xFFFFF29F, 0x000003D9, 0x000022CD, 0xFFFFF29F, 0x000003D9 }, + { 0x0213EA94DE043164, 0x00002F30, 0xFFFFECB8, 0x000004A0, 0x00001B07, 0xFFFFF7E2, 0x00000313, 0x00001B07, 0xFFFFF7E2, 0x00000313 }, + { 0x0213F0FD42DC30A4, 0x0000383B, 0xFFFFE702, 0x00000581, 0x00001A08, 0xFFFFF8CA, 0x000002E2, 0x00001A08, 0xFFFFF8CA, 0x000002E2 }, + { 0x0213F0FE99022164, 0x00002CC5, 0xFFFFEDF8, 0x00000465, 0x00001F47, 0xFFFFF4B2, 0x00000393, 0x00001F47, 0xFFFFF4B2, 0x00000393 }, + { 0x0213F0FE991621C4, 0x00002304, 0xFFFFF453, 0x00000384, 0x0000170A, 0xFFFFFA3F, 0x000002CE, 0x0000170A, 0xFFFFFA3F, 0x000002CE }, + { 0x0213F0FE990A5124, 0x0000337E, 0xFFFFE850, 0x0000056E, 0x00001BDD, 0xFFFFF668, 0x00000353, 0x00001BDD, 0xFFFFF668, 0x00000353 }, + { 0x0213F0FE990E4924, 0x00002E2F, 0xFFFFEC9B, 0x000004AE, 0x00001C4D, 0xFFFFF6D3, 0x00000338, 0x00001C4D, 0xFFFFF6D3, 0x00000338 }, + { 0x0213EA94DE061124, 0x00002DDD, 0xFFFFEDA4, 0x00000477, 0x00002010, 0xFFFFF4BB, 0x00000390, 0x00002010, 0xFFFFF4BB, 0x00000390 }, + { 0x0213F0FD42DA48E4, 0x0000290C, 0xFFFFEF61, 0x00000445, 0x00002133, 0xFFFFF324, 0x000003D8, 0x00002133, 0xFFFFF324, 0x000003D8 }, + { 0x0213F0FE99062924, 0x0000371E, 0xFFFFE8D5, 0x00000524, 0x00001C3A, 0xFFFFF7AE, 0x00000314, 0x00001C3A, 0xFFFFF7AE, 0x00000314 }, + { 0x0213F0FD42D838E4, 0x00002A58, 0xFFFFF007, 0x00000429, 0x000018A6, 0xFFFFF98F, 0x000002E1, 0x000018A6, 0xFFFFF98F, 0x000002E1 }, + { 0x0213F0FE99023084, 0x00002FED, 0xFFFFEC48, 0x000004AA, 0x00001E9D, 0xFFFFF584, 0x00000370, 0x00001E9D, 0xFFFFF584, 0x00000370 }, + { 0x0213F0FE99181884, 0x00002829, 0xFFFFF15F, 0x000003F7, 0x0000157E, 0xFFFFFBD4, 0x00000282, 0x0000157E, 0xFFFFFBD4, 0x00000282 }, + { 0x0213F0FE99101924, 0x000030CF, 0xFFFFEB8D, 0x000004CE, 0x00001A4C, 0xFFFFF868, 0x000002F7, 0x00001A4C, 0xFFFFF868, 0x000002F7 }, + { 0x0213F0FD42DA2084, 0x00002C8F, 0xFFFFEDD2, 0x0000047D, 0x00001CCE, 0xFFFFF6A1, 0x00000343, 0x00001CCE, 0xFFFFF6A1, 0x00000343 }, + { 0x0213F0FE99182164, 0x00002A84, 0xFFFFEFBA, 0x0000043E, 0x000015EF, 0xFFFFFB4B, 0x0000029E, 0x000015EF, 0xFFFFFB4B, 0x0000029E }, + { 0x0213F0FE990C28A4, 0x000034CA, 0xFFFFEA08, 0x000004FF, 0x00001C19, 0xFFFFF7ED, 0x00000309, 0x00001C19, 0xFFFFF7ED, 0x00000309 }, + { 0x0213F0FE991639A4, 0x00002187, 0xFFFFF4B0, 0x0000037E, 0x0000154A, 0xFFFFFB0C, 0x000002AE, 0x0000154A, 0xFFFFFB0C, 0x000002AE }, + { 0x0213F0FD42DA3844, 0x00002F4F, 0xFFFFEB3C, 0x000004F8, 0x0000181F, 0xFFFFF92D, 0x000002DF, 0x0000181F, 0xFFFFF92D, 0x000002DF }, + { 0x0213F0FE990410E4, 0x0000290C, 0xFFFFF0B1, 0x000003FC, 0x00001DB0, 0xFFFFF636, 0x00000355, 0x00001DB0, 0xFFFFF636, 0x00000355 }, + { 0x0213F0FE990A1064, 0x000034C1, 0xFFFFE888, 0x0000055A, 0x000019BF, 0xFFFFF881, 0x000002FB, 0x000019BF, 0xFFFFF881, 0x000002FB }, + { 0x0213F0FD42DC18C4, 0x00003139, 0xFFFFEA98, 0x00000504, 0x000019F2, 0xFFFFF820, 0x0000030B, 0x000019F2, 0xFFFFF820, 0x0000030B }, + { 0x0213F0FD42D83144, 0x00002CAC, 0xFFFFEEB2, 0x00000458, 0x0000152C, 0xFFFFFBEF, 0x0000027B, 0x0000152C, 0xFFFFFBEF, 0x0000027B }, + { 0x0213F0FE992C38E4, 0x00003577, 0xFFFFE99C, 0x0000050D, 0x00001E64, 0xFFFFF679, 0x0000033F, 0x00001E64, 0xFFFFF679, 0x0000033F }, + { 0x0213F0FD42DA4104, 0x0000263A, 0xFFFFF1E4, 0x000003D4, 0x00001F68, 0xFFFFF4ED, 0x00000386, 0x00001F68, 0xFFFFF4ED, 0x00000386 }, + { 0x0213F0FD42D81984, 0x00002CE9, 0xFFFFED63, 0x00000497, 0x00001810, 0xFFFFF94D, 0x000002E3, 0x00001810, 0xFFFFF94D, 0x000002E3 }, + { 0x0213EA94DE044104, 0x0000318A, 0xFFFFEAC8, 0x000004F5, 0x0000195C, 0xFFFFF896, 0x000002FB, 0x0000195C, 0xFFFFF896, 0x000002FB }, + { 0x0213F0FD42D83904, 0x00002C41, 0xFFFFEEC6, 0x0000045D, 0x000017DD, 0xFFFFFA16, 0x000002CB, 0x000017DD, 0xFFFFFA16, 0x000002CB }, + { 0x0213F0FE990231A4, 0x00002DD4, 0xFFFFEC98, 0x000004AD, 0x00001BD7, 0xFFFFF69F, 0x00000347, 0x00001BD7, 0xFFFFF69F, 0x00000347 }, + { 0x0213F0FD42DA3944, 0x00003351, 0xFFFFE9B2, 0x0000051A, 0x00001CA1, 0xFFFFF6A4, 0x00000341, 0x00001CA1, 0xFFFFF6A4, 0x00000341 }, + { 0x0213F0FE99021104, 0x0000322D, 0xFFFFE9BE, 0x00000527, 0x00001CF9, 0xFFFFF5EB, 0x00000366, 0x00001CF9, 0xFFFFF5EB, 0x00000366 }, + { 0x0213F0FE990C28C4, 0x00003678, 0xFFFFE9A8, 0x00000503, 0x00001AD4, 0xFFFFF8F6, 0x000002E3, 0x00001AD4, 0xFFFFF8F6, 0x000002E3 }, + { 0x0213F0FE99161924, 0x0000260E, 0xFFFFF2C1, 0x000003CA, 0x00001139, 0xFFFFFE48, 0x00000236, 0x00001139, 0xFFFFFE48, 0x00000236 }, + { 0x0213F0FE990A2164, 0x000033D3, 0xFFFFE872, 0x00000565, 0x00001B72, 0xFFFFF713, 0x00000332, 0x00001B72, 0xFFFFF713, 0x00000332 }, + { 0x0213F0FE99323844, 0x0000309B, 0xFFFFEB42, 0x000004E4, 0x00001918, 0xFFFFF8C8, 0x000002F2, 0x00001918, 0xFFFFF8C8, 0x000002F2 }, + { 0x0213F0FE99182864, 0x000028B8, 0xFFFFF105, 0x00000402, 0x000018BB, 0xFFFFF9BC, 0x000002D3, 0x000018BB, 0xFFFFF9BC, 0x000002D3 }, + { 0x0213F0FE990A1884, 0x00003123, 0xFFFFE9D1, 0x00000534, 0x00001B19, 0xFFFFF6FE, 0x0000033C, 0x00001B19, 0xFFFFF6FE, 0x0000033C }, + { 0x0213F0FE99022144, 0x00003216, 0xFFFFEA8E, 0x000004F6, 0x00001F72, 0xFFFFF4CE, 0x0000038B, 0x00001F72, 0xFFFFF4CE, 0x0000038B }, + { 0x0213F0FE99162964, 0x00002564, 0xFFFFF32D, 0x000003B6, 0x00001685, 0xFFFFFADB, 0x000002BB, 0x00001685, 0xFFFFFADB, 0x000002BB }, + { 0x0213F0FD42DA2924, 0x00002E60, 0xFFFFED13, 0x00000497, 0x00001CA5, 0xFFFFF6B9, 0x00000346, 0x00001CA5, 0xFFFFF6B9, 0x00000346 }, + { 0x0213F0FE990E39A4, 0x0000336D, 0xFFFFE934, 0x0000053B, 0x00001B3E, 0xFFFFF763, 0x00000327, 0x00001B3E, 0xFFFFF763, 0x00000327 }, + { 0x0213F0FE99101084, 0x0000274A, 0xFFFFF119, 0x000003FA, 0x00001D75, 0xFFFFF5CD, 0x0000036F, 0x00001D75, 0xFFFFF5CD, 0x0000036F }, + { 0x0213F0FD42DA2164, 0x0000366B, 0xFFFFE70A, 0x0000059A, 0x00001ED8, 0xFFFFF501, 0x00000389, 0x00001ED8, 0xFFFFF501, 0x00000389 }, + { 0x0213F0FE99223964, 0x00003164, 0xFFFFEAB4, 0x000004FA, 0x00001C52, 0xFFFFF6E0, 0x00000336, 0x00001C52, 0xFFFFF6E0, 0x00000336 }, + { 0x0213F0FD42D23064, 0x00004224, 0xFFFFDF7F, 0x000006C1, 0x00002A52, 0xFFFFED5E, 0x000004BB, 0x00002A52, 0xFFFFED5E, 0x000004BB }, + { 0x0213F0FE99102864, 0x000030E3, 0xFFFFEB07, 0x000004ED, 0x00001FD3, 0xFFFFF46D, 0x000003A1, 0x00001FD3, 0xFFFFF46D, 0x000003A1 }, + { 0x0213F0FD42D82884, 0x00002AEB, 0xFFFFEF1B, 0x00000454, 0x00001829, 0xFFFFF995, 0x000002DD, 0x00001829, 0xFFFFF995, 0x000002DD }, + { 0x0213F0FD42DC50E4, 0x0000346B, 0xFFFFE7A2, 0x0000058B, 0x000020C5, 0xFFFFF2E8, 0x000003EC, 0x000020C5, 0xFFFFF2E8, 0x000003EC }, + { 0x0213F0FD42DC4164, 0x000039CF, 0xFFFFE5D7, 0x000005A9, 0x00001D66, 0xFFFFF5D6, 0x00000366, 0x00001D66, 0xFFFFF5D6, 0x00000366 }, + { 0x0213F0FE990418E4, 0x000034AC, 0xFFFFE9AE, 0x00000515, 0x00001A28, 0xFFFFF904, 0x000002DC, 0x00001A28, 0xFFFFF904, 0x000002DC }, + { 0x0213F0FD42DC2084, 0x00002D68, 0xFFFFED21, 0x00000498, 0x00001C6F, 0xFFFFF686, 0x0000034C, 0x00001C6F, 0xFFFFF686, 0x0000034C }, + { 0x0213F0FE990820C4, 0x0000328B, 0xFFFFEBA1, 0x000004B4, 0x00001DA3, 0xFFFFF683, 0x00000349, 0x00001DA3, 0xFFFFF683, 0x00000349 }, + { 0x0213F0FE991828C4, 0x000027DC, 0xFFFFF295, 0x000003BF, 0x000019C1, 0xFFFFF98E, 0x000002E8, 0x000019C1, 0xFFFFF98E, 0x000002E8 }, + { 0x0213F0FE99184084, 0x00002756, 0xFFFFF1D7, 0x000003DF, 0x000015D9, 0xFFFFFB51, 0x00000298, 0x000015D9, 0xFFFFFB51, 0x00000298 }, + { 0x0213F0FE99083884, 0x00003526, 0xFFFFE907, 0x00000526, 0x000017AB, 0xFFFFFA12, 0x000002AB, 0x000017AB, 0xFFFFFA12, 0x000002AB }, + { 0x0213F0FD42DA18E4, 0x0000351B, 0xFFFFE8B7, 0x00000540, 0x00001A86, 0xFFFFF821, 0x00000303, 0x00001A86, 0xFFFFF821, 0x00000303 }, + { 0x0213F0FE99164144, 0x000024B2, 0xFFFFF34E, 0x000003B1, 0x000018E2, 0xFFFFF926, 0x000002FC, 0x000018E2, 0xFFFFF926, 0x000002FC }, + { 0x0213F0FD42D828A4, 0x00002F36, 0xFFFFED5D, 0x00000486, 0x0000157A, 0xFFFFFB85, 0x00000293, 0x0000157A, 0xFFFFFB85, 0x00000293 }, + { 0x0213F0FD42DC50C4, 0x00003A6E, 0xFFFFE456, 0x000005FD, 0x00001F68, 0xFFFFF3D1, 0x000003C3, 0x00001F68, 0xFFFFF3D1, 0x000003C3 }, + { 0x0213F0FE990A31A4, 0x00002BC3, 0xFFFFED2D, 0x000004A7, 0x00001C3F, 0xFFFFF609, 0x00000364, 0x00001C3F, 0xFFFFF609, 0x00000364 }, + { 0x0213F0FE990E2084, 0x000032E1, 0xFFFFEA83, 0x000004F6, 0x00001B37, 0xFFFFF842, 0x000002F5, 0x00001B37, 0xFFFFF842, 0x000002F5 }, + { 0x0213F0FD42D83184, 0x000028E3, 0xFFFFF07F, 0x00000412, 0x00001676, 0xFFFFFA68, 0x000002BE, 0x00001676, 0xFFFFFA68, 0x000002BE }, + { 0x0213F0FD42D21104, 0x0000444C, 0xFFFFDDAD, 0x00000712, 0x00002634, 0xFFFFEF89, 0x0000046C, 0x00002634, 0xFFFFEF89, 0x0000046C }, + { 0x0213F0FE990418C4, 0x00003121, 0xFFFFEBBB, 0x000004C6, 0x00001C98, 0xFFFFF72B, 0x0000032D, 0x00001C98, 0xFFFFF72B, 0x0000032D }, + { 0x0213F0FD42D840A4, 0x00002C31, 0xFFFFEDC4, 0x00000490, 0x0000162D, 0xFFFFFA8E, 0x000002B4, 0x0000162D, 0xFFFFFA8E, 0x000002B4 }, + { 0x0213F0FD42DA18C4, 0x00002749, 0xFFFFF112, 0x000003FC, 0x00001C85, 0xFFFFF6B8, 0x00000342, 0x00001C85, 0xFFFFF6B8, 0x00000342 }, + { 0x0213F0FE99044104, 0x00003159, 0xFFFFEB99, 0x000004C2, 0x00001BD0, 0xFFFFF7CA, 0x00000307, 0x00001BD0, 0xFFFFF7CA, 0x00000307 }, + { 0x0213F0FE99164164, 0x00002610, 0xFFFFF1FD, 0x000003EC, 0x000016BE, 0xFFFFFA53, 0x000002CB, 0x000016BE, 0xFFFFFA53, 0x000002CB }, + { 0x0213F0FE99023184, 0x000037B5, 0xFFFFE63D, 0x000005B5, 0x00002285, 0xFFFFF25D, 0x000003F7, 0x00002285, 0xFFFFF25D, 0x000003F7 }, + { 0x0213F0FE990A28A4, 0x00002FEE, 0xFFFFEB47, 0x000004EF, 0x00001CBE, 0xFFFFF64E, 0x00000358, 0x00001CBE, 0xFFFFF64E, 0x00000358 }, + { 0x0213F0FE99105104, 0x00002E90, 0xFFFFEC48, 0x000004C0, 0x00001A47, 0xFFFFF7D1, 0x0000031A, 0x00001A47, 0xFFFFF7D1, 0x0000031A }, + { 0x0213F0FD42DA4084, 0x000034AB, 0xFFFFE84A, 0x00000559, 0x00001A72, 0xFFFFF79A, 0x0000031C, 0x00001A72, 0xFFFFF79A, 0x0000031C }, + { 0x0213F0FE99183884, 0x00002F7B, 0xFFFFECFC, 0x0000049C, 0x00001814, 0xFFFFFA22, 0x000002C2, 0x00001814, 0xFFFFFA22, 0x000002C2 }, + { 0x0213F0FE99021964, 0x00003618, 0xFFFFE709, 0x00000596, 0x00001EBF, 0xFFFFF482, 0x000003A5, 0x00001EBF, 0xFFFFF482, 0x000003A5 }, + { 0x0213EA94DE024904, 0x0000341B, 0xFFFFE8B2, 0x0000054F, 0x00001D26, 0xFFFFF578, 0x00000388, 0x00001D26, 0xFFFFF578, 0x00000388 }, + { 0x0213F0FE99102144, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x000019C0, 0xFFFFF8CC, 0x000002E6, 0x000019C0, 0xFFFFF8CC, 0x000002E6 }, + { 0x0213F0FE992841A4, 0x00002B76, 0xFFFFEF6C, 0x00000444, 0x00001563, 0xFFFFFBBE, 0x0000028D, 0x00001563, 0xFFFFFBBE, 0x0000028D }, + { 0x0213F0FD42D81864, 0x00002BA2, 0xFFFFEE31, 0x0000047F, 0x00001A3D, 0xFFFFF7F3, 0x00000320, 0x00001A3D, 0xFFFFF7F3, 0x00000320 }, + { 0x0213F0FE992C48E4, 0x00003545, 0xFFFFE87A, 0x0000054A, 0x00001B5A, 0xFFFFF7B0, 0x0000030C, 0x00001B5A, 0xFFFFF7B0, 0x0000030C }, + { 0x0213EA94DE042944, 0x00003879, 0xFFFFE73F, 0x00000578, 0x00001649, 0xFFFFFB57, 0x00000283, 0x00001649, 0xFFFFFB57, 0x00000283 }, + { 0x0213F0FD42D840C4, 0x00002772, 0xFFFFF0F1, 0x00000410, 0x0000142F, 0xFFFFFBCF, 0x00000287, 0x0000142F, 0xFFFFFBCF, 0x00000287 }, + { 0x0213F0FD42DA3184, 0x00003228, 0xFFFFE98E, 0x00000535, 0x00001F48, 0xFFFFF495, 0x00000399, 0x00001F48, 0xFFFFF495, 0x00000399 }, + { 0x0213F0FE990E40E4, 0x00002887, 0xFFFFF119, 0x000003E8, 0x000021AA, 0xFFFFF3F5, 0x000003A5, 0x000021AA, 0xFFFFF3F5, 0x000003A5 }, + { 0x0213F0FD42DA28A4, 0x0000301F, 0xFFFFEBB2, 0x000004D2, 0x00001C02, 0xFFFFF736, 0x0000032B, 0x00001C02, 0xFFFFF736, 0x0000032B }, + { 0x0213F0FE991820A4, 0x00002E13, 0xFFFFEE3F, 0x00000468, 0x000016AC, 0xFFFFFB32, 0x0000029E, 0x000016AC, 0xFFFFFB32, 0x0000029E }, + { 0x0213F0FE99044924, 0x00003478, 0xFFFFE8F9, 0x00000538, 0x00001DAB, 0xFFFFF645, 0x00000345, 0x00001DAB, 0xFFFFF645, 0x00000345 }, + { 0x0213F0FE990608C4, 0x000030C6, 0xFFFFEB6C, 0x000004D4, 0x0000184A, 0xFFFFF934, 0x000002E1, 0x0000184A, 0xFFFFF934, 0x000002E1 }, + { 0x0213F0FE990A2044, 0x00002F1B, 0xFFFFEBD3, 0x000004D3, 0x000019E7, 0xFFFFF813, 0x0000030D, 0x000019E7, 0xFFFFF813, 0x0000030D }, + { 0x0213F0FE99023904, 0x00003214, 0xFFFFEAE9, 0x000004E0, 0x0000178F, 0xFFFFFA1C, 0x000002B1, 0x0000178F, 0xFFFFFA1C, 0x000002B1 }, + { 0x0213F0FD42DC3144, 0x0000399C, 0xFFFFE738, 0x0000055E, 0x00001EA1, 0xFFFFF5E7, 0x0000035A, 0x00001EA1, 0xFFFFF5E7, 0x0000035A }, + { 0x0213F0FE990650C4, 0x00003A01, 0xFFFFE5B2, 0x000005B6, 0x00001D95, 0xFFFFF5D2, 0x0000036A, 0x00001D95, 0xFFFFF5D2, 0x0000036A }, + { 0x0213F0FE99043884, 0x0000310D, 0xFFFFEB78, 0x000004D0, 0x00001C06, 0xFFFFF76E, 0x0000031A, 0x00001C06, 0xFFFFF76E, 0x0000031A }, + { 0x0213F0FE99063864, 0x00003CD1, 0xFFFFE42F, 0x000005EB, 0x00001933, 0xFFFFF91F, 0x000002D4, 0x00001933, 0xFFFFF91F, 0x000002D4 }, + { 0x0213F0FD42DA3164, 0x00003119, 0xFFFFEB1B, 0x000004E1, 0x00001FC7, 0xFFFFF46A, 0x000003A2, 0x00001FC7, 0xFFFFF46A, 0x000003A2 }, + { 0x0213EA94DE0648A4, 0x0000390D, 0xFFFFE566, 0x000005D8, 0x00001EC6, 0xFFFFF4DC, 0x00000391, 0x00001EC6, 0xFFFFF4DC, 0x00000391 }, + { 0x0213F0FD42DA10C4, 0x00003446, 0xFFFFE858, 0x00000561, 0x00001FDB, 0xFFFFF3FF, 0x000003B9, 0x00001FDB, 0xFFFFF3FF, 0x000003B9 }, + { 0x0213F0FE99044904, 0x000032BA, 0xFFFFEA07, 0x00000511, 0x00001B25, 0xFFFFF7C9, 0x0000030D, 0x00001B25, 0xFFFFF7C9, 0x0000030D }, + { 0x0213F0FE990E1864, 0x00002CCF, 0xFFFFEDE5, 0x00000478, 0x00001BC8, 0xFFFFF761, 0x00000326, 0x00001BC8, 0xFFFFF761, 0x00000326 }, + { 0x0213F0FE99062984, 0x0000400E, 0xFFFFE1CB, 0x00000652, 0x00001AF8, 0xFFFFF7B9, 0x00000312, 0x00001AF8, 0xFFFFF7B9, 0x00000312 }, + { 0x0213F0FE990408E4, 0x00002F24, 0xFFFFEC2A, 0x000004C7, 0x00001B94, 0xFFFFF748, 0x00000333, 0x00001B94, 0xFFFFF748, 0x00000333 }, + { 0x0213F0FD42D21924, 0x00003FDA, 0xFFFFE1C1, 0x0000064B, 0x00002427, 0xFFFFF180, 0x0000040C, 0x00002427, 0xFFFFF180, 0x0000040C }, + { 0x0213F0FE990A18C4, 0x00002F6B, 0xFFFFEBA7, 0x000004DD, 0x00001C25, 0xFFFFF6C1, 0x00000344, 0x00001C25, 0xFFFFF6C1, 0x00000344 }, + { 0x0213F0FE99182104, 0x00002A53, 0xFFFFF0EE, 0x00000402, 0x000017C6, 0xFFFFFAA0, 0x000002BF, 0x000017C6, 0xFFFFFAA0, 0x000002BF }, + { 0x0213F0FE99105144, 0x000031F4, 0xFFFFEA34, 0x00000517, 0x000016FF, 0xFFFFFA4E, 0x000002AC, 0x000016FF, 0xFFFFFA4E, 0x000002AC }, + { 0x0213F0FE99322144, 0x00002E24, 0xFFFFED46, 0x00000489, 0x00001712, 0xFFFFFA5D, 0x000002AC, 0x00001712, 0xFFFFFA5D, 0x000002AC }, + { 0x0213F0FE99182824, 0x000028CD, 0xFFFFF0E3, 0x0000040E, 0x00001606, 0xFFFFFB37, 0x000002A4, 0x00001606, 0xFFFFFB37, 0x000002A4 }, + { 0x0213F0FE990220C4, 0x00003184, 0xFFFFEB88, 0x000004C3, 0x000018DA, 0xFFFFF939, 0x000002DB, 0x000018DA, 0xFFFFF939, 0x000002DB }, + { 0x0213F0FE99162124, 0x0000239B, 0xFFFFF470, 0x00000386, 0x00001714, 0xFFFFFA9F, 0x000002C8, 0x00001714, 0xFFFFFA9F, 0x000002C8 }, + { 0x0213F0FD42DC38E4, 0x00003641, 0xFFFFE92B, 0x00000515, 0x00001BE2, 0xFFFFF795, 0x0000031B, 0x00001BE2, 0xFFFFF795, 0x0000031B }, + { 0x0213F0FE992C1144, 0x00003278, 0xFFFFEA17, 0x00000510, 0x00001B71, 0xFFFFF778, 0x0000031D, 0x00001B71, 0xFFFFF778, 0x0000031D }, + { 0x0213F0FE99062844, 0x000035B9, 0xFFFFE8DA, 0x0000052D, 0x00001A6A, 0xFFFFF83B, 0x000002FF, 0x00001A6A, 0xFFFFF83B, 0x000002FF }, + { 0x0213F0FE990E18C4, 0x00002E5E, 0xFFFFED32, 0x0000048B, 0x00001E7D, 0xFFFFF60E, 0x0000034E, 0x00001E7D, 0xFFFFF60E, 0x0000034E }, + { 0x0213F0FE991019A4, 0x00003178, 0xFFFFEA52, 0x00000513, 0x00001AD0, 0xFFFFF793, 0x0000031F, 0x00001AD0, 0xFFFFF793, 0x0000031F }, + { 0x0213F0FD42D44104, 0x00003A2C, 0xFFFFE346, 0x00000641, 0x000023D0, 0xFFFFF0CE, 0x00000433, 0x000023D0, 0xFFFFF0CE, 0x00000433 }, + { 0x0213F0FD42D818C4, 0x000028FD, 0xFFFFF02A, 0x0000042B, 0x0000152B, 0xFFFFFB90, 0x00000289, 0x0000152B, 0xFFFFFB90, 0x00000289 }, + { 0x0213F0FE990E3084, 0x000030DE, 0xFFFFEBDF, 0x000004BE, 0x00001CDC, 0xFFFFF747, 0x0000031C, 0x00001CDC, 0xFFFFF747, 0x0000031C }, + { 0x0213F0FE99021944, 0x000036CB, 0xFFFFE6EE, 0x00000596, 0x00002096, 0xFFFFF3C2, 0x000003BB, 0x00002096, 0xFFFFF3C2, 0x000003BB }, + { 0x0213F0FE990C48C4, 0x00003172, 0xFFFFEAC1, 0x000004F4, 0x00001C87, 0xFFFFF6CD, 0x00000337, 0x00001C87, 0xFFFFF6CD, 0x00000337 }, + { 0x0213F0FD42D24864, 0x00004A18, 0xFFFFDB34, 0x00000758, 0x0000213C, 0xFFFFF3A2, 0x000003AC, 0x0000213C, 0xFFFFF3A2, 0x000003AC }, + { 0x0213F0FE99022104, 0x000031F3, 0xFFFFEB73, 0x000004C6, 0x00001B23, 0xFFFFF7CB, 0x0000031A, 0x00001B23, 0xFFFFF7CB, 0x0000031A }, + { 0x0213F0FE990A2924, 0x000031C0, 0xFFFFEABA, 0x000004F7, 0x00001A5A, 0xFFFFF845, 0x000002FF, 0x00001A5A, 0xFFFFF845, 0x000002FF }, + { 0x0213F0FE99104944, 0x00003B77, 0xFFFFE3B3, 0x00000623, 0x00001BCA, 0xFFFFF6F8, 0x00000333, 0x00001BCA, 0xFFFFF6F8, 0x00000333 }, + { 0x0213F0FE990A3944, 0x000035AF, 0xFFFFE76D, 0x00000588, 0x00001C16, 0xFFFFF6AB, 0x00000341, 0x00001C16, 0xFFFFF6AB, 0x00000341 }, + { 0x0213EA94DE0438C4, 0x000032AD, 0xFFFFEA8E, 0x000004F8, 0x00001A3A, 0xFFFFF832, 0x0000030E, 0x00001A3A, 0xFFFFF832, 0x0000030E }, + { 0x0213F0FE99104884, 0x00002E92, 0xFFFFEBD2, 0x000004DA, 0x00001E04, 0xFFFFF51E, 0x0000038A, 0x00001E04, 0xFFFFF51E, 0x0000038A }, + { 0x0213F0FD42D440A4, 0x00003E57, 0xFFFFE0F7, 0x0000068F, 0x000021F1, 0xFFFFF1C6, 0x00000411, 0x000021F1, 0xFFFFF1C6, 0x00000411 }, + { 0x0213F0FE990821A4, 0x00003598, 0xFFFFE8BB, 0x00000535, 0x00001B62, 0xFFFFF764, 0x00000326, 0x00001B62, 0xFFFFF764, 0x00000326 }, + { 0x0213F0FE990A3884, 0x00002B15, 0xFFFFEDEC, 0x00000487, 0x00001E8B, 0xFFFFF4AB, 0x0000039F, 0x00001E8B, 0xFFFFF4AB, 0x0000039F }, + { 0x0213EA94DE060904, 0x0000267E, 0xFFFFF1A7, 0x000003E1, 0x000021C1, 0xFFFFF2E9, 0x000003EA, 0x000021C1, 0xFFFFF2E9, 0x000003EA }, + { 0x0213EA94DE0239A4, 0x00002ED7, 0xFFFFEC88, 0x000004A6, 0x00001DEC, 0xFFFFF57C, 0x00000378, 0x00001DEC, 0xFFFFF57C, 0x00000378 }, + { 0x0213EA94DE0441A4, 0x00003365, 0xFFFFE946, 0x00000536, 0x000019E9, 0xFFFFF7E0, 0x0000031D, 0x000019E9, 0xFFFFF7E0, 0x0000031D }, + { 0x0213F0FE991818E4, 0x000029A4, 0xFFFFF0FD, 0x000003FE, 0x0000163F, 0xFFFFFB68, 0x00000299, 0x0000163F, 0xFFFFFB68, 0x00000299 }, + { 0x0213EA94DE021904, 0x0000348D, 0xFFFFE9F7, 0x00000509, 0x000017A0, 0xFFFFFA59, 0x000002B6, 0x000017A0, 0xFFFFFA59, 0x000002B6 }, + { 0x0213F0FE990610C4, 0x00003144, 0xFFFFEB23, 0x000004D9, 0x00001C9B, 0xFFFFF664, 0x00000351, 0x00001C9B, 0xFFFFF664, 0x00000351 }, + { 0x0213EA94DE0620E4, 0x00002E95, 0xFFFFEE1A, 0x00000463, 0x00001707, 0xFFFFFAB7, 0x000002B3, 0x00001707, 0xFFFFFAB7, 0x000002B3 }, + { 0x0213F0FD42D41864, 0x0000489C, 0xFFFFDA43, 0x000007AC, 0x00002866, 0xFFFFED6B, 0x000004D0, 0x00002866, 0xFFFFED6B, 0x000004D0 }, + { 0x0213F0FE99161844, 0x00002895, 0xFFFFF10A, 0x0000040A, 0x000013E9, 0xFFFFFC9F, 0x0000026E, 0x000013E9, 0xFFFFFC9F, 0x0000026E }, + { 0x0213F0FE99061964, 0x000033A0, 0xFFFFE9B1, 0x00000510, 0x00001D96, 0xFFFFF5AE, 0x0000036F, 0x00001D96, 0xFFFFF5AE, 0x0000036F }, + { 0x0213F0FE99083984, 0x0000327C, 0xFFFFEAEA, 0x000004DD, 0x00001D45, 0xFFFFF649, 0x00000356, 0x00001D45, 0xFFFFF649, 0x00000356 }, + { 0x0213EA94DE0248A4, 0x000031DF, 0xFFFFE9AB, 0x0000052F, 0x000019C8, 0xFFFFF7B7, 0x00000321, 0x000019C8, 0xFFFFF7B7, 0x00000321 }, + { 0x0213F0FE991640A4, 0x00002BCC, 0xFFFFEEF4, 0x0000045C, 0x000015CD, 0xFFFFFB58, 0x0000029E, 0x000015CD, 0xFFFFFB58, 0x0000029E }, + { 0x0213F0FE990638E4, 0x00003534, 0xFFFFEA10, 0x000004EB, 0x00001BB6, 0xFFFFF7B9, 0x00000314, 0x00001BB6, 0xFFFFF7B9, 0x00000314 }, + { 0x0213F0FE99041984, 0x00002F4F, 0xFFFFEC35, 0x000004B9, 0x0000205D, 0xFFFFF47F, 0x00000392, 0x0000205D, 0xFFFFF47F, 0x00000392 }, + { 0x0213F0FE990C20A4, 0x00003295, 0xFFFFEB1C, 0x000004D6, 0x000019C1, 0xFFFFF931, 0x000002D5, 0x000019C1, 0xFFFFF931, 0x000002D5 }, + { 0x0213F0FE99024144, 0x00003557, 0xFFFFE7F7, 0x00000568, 0x00002342, 0xFFFFF1F9, 0x00000405, 0x00002342, 0xFFFFF1F9, 0x00000405 }, + { 0x0213F0FE990450C4, 0x00003487, 0xFFFFE872, 0x0000055D, 0x000019D7, 0xFFFFF823, 0x0000030C, 0x000019D7, 0xFFFFF823, 0x0000030C }, + { 0x0213F0FE992C3944, 0x0000378F, 0xFFFFE7A6, 0x00000566, 0x00001875, 0xFFFFFA04, 0x000002AF, 0x00001875, 0xFFFFFA04, 0x000002AF }, + { 0x0213EA94DE0230E4, 0x00002A67, 0xFFFFF157, 0x000003DD, 0x000017BD, 0xFFFFFA53, 0x000002D1, 0x000017BD, 0xFFFFFA53, 0x000002D1 }, + { 0x0213F0FD42D220E4, 0x000030B5, 0xFFFFEB32, 0x000004D9, 0x00002129, 0xFFFFF38A, 0x000003BB, 0x00002129, 0xFFFFF38A, 0x000003BB }, + { 0x0213F0FE990610A4, 0x00003786, 0xFFFFE703, 0x00000584, 0x00001D63, 0xFFFFF5DC, 0x00000367, 0x00001D63, 0xFFFFF5DC, 0x00000367 }, + { 0x0213F0FD42DA20C4, 0x0000346A, 0xFFFFE93E, 0x0000052C, 0x00001B27, 0xFFFFF79D, 0x0000031F, 0x00001B27, 0xFFFFF79D, 0x0000031F }, + { 0x0213F0FE990E3024, 0x0000294E, 0xFFFFF0A5, 0x00000409, 0x00001928, 0xFFFFF93B, 0x000002E6, 0x00001928, 0xFFFFF93B, 0x000002E6 }, + { 0x0213F0FD42D410C4, 0x00003E09, 0xFFFFE0FF, 0x00000694, 0x000025A0, 0xFFFFEF0F, 0x0000048F, 0x000025A0, 0xFFFFEF0F, 0x0000048F }, + { 0x0213F0FE990A2964, 0x00003197, 0xFFFFEA06, 0x00000520, 0x00001B42, 0xFFFFF73B, 0x0000032A, 0x00001B42, 0xFFFFF73B, 0x0000032A }, + { 0x0213F0FE99161864, 0x000022CB, 0xFFFFF3FC, 0x000003A3, 0x00001449, 0xFFFFFBD0, 0x00000297, 0x00001449, 0xFFFFFBD0, 0x00000297 }, + { 0x0213F0FD42D82944, 0x00002A79, 0xFFFFEFD2, 0x00000433, 0x00001585, 0xFFFFFB92, 0x0000028E, 0x00001585, 0xFFFFFB92, 0x0000028E }, + { 0x0213F0FE990C4184, 0x00003249, 0xFFFFEA92, 0x000004F4, 0x000019CB, 0xFFFFF8CF, 0x000002E1, 0x000019CB, 0xFFFFF8CF, 0x000002E1 }, + { 0x0213EA94DE0218A4, 0x00002CEA, 0xFFFFEE46, 0x00000463, 0x00001A5E, 0xFFFFF83C, 0x0000030D, 0x00001A5E, 0xFFFFF83C, 0x0000030D }, + { 0x0213F0FD42DC5144, 0x00003AE2, 0xFFFFE422, 0x00000600, 0x00001C65, 0xFFFFF62F, 0x0000034B, 0x00001C65, 0xFFFFF62F, 0x0000034B }, + { 0x0213F0FE99181184, 0x000026A0, 0xFFFFF1C2, 0x000003F8, 0x000010E5, 0xFFFFFE56, 0x0000022A, 0x000010E5, 0xFFFFFE56, 0x0000022A }, + { 0x0213F0FE992829A4, 0x00002A7B, 0xFFFFF063, 0x00000417, 0x000016FC, 0xFFFFFAD7, 0x000002B1, 0x000016FC, 0xFFFFFAD7, 0x000002B1 }, + { 0x0213F0FE993210C4, 0x00003092, 0xFFFFEAB9, 0x00000507, 0x00001AE3, 0xFFFFF783, 0x00000323, 0x00001AE3, 0xFFFFF783, 0x00000323 }, + { 0x0213F0FE990438E4, 0x00003265, 0xFFFFEBE8, 0x000004AA, 0x00001D65, 0xFFFFF73F, 0x00000321, 0x00001D65, 0xFFFFF73F, 0x00000321 }, + { 0x0213EA94DE023084, 0x00002F14, 0xFFFFECC2, 0x000004A4, 0x00001A8D, 0xFFFFF7F3, 0x0000031D, 0x00001A8D, 0xFFFFF7F3, 0x0000031D }, + { 0x0213F0FD42DC10E4, 0x000035FB, 0xFFFFE6D3, 0x000005AC, 0x00001B19, 0xFFFFF712, 0x00000338, 0x00001B19, 0xFFFFF712, 0x00000338 }, + { 0x0213F0FD42DA2124, 0x00003519, 0xFFFFE8CC, 0x0000053A, 0x00001A0F, 0xFFFFF86E, 0x000002F5, 0x00001A0F, 0xFFFFF86E, 0x000002F5 }, + { 0x0213F0FE992C2144, 0x0000364C, 0xFFFFE879, 0x00000541, 0x00001A42, 0xFFFFF8BA, 0x000002E2, 0x00001A42, 0xFFFFF8BA, 0x000002E2 }, + { 0x0213EA94DE0218C4, 0x000029BA, 0xFFFFF09A, 0x00000408, 0x00001986, 0xFFFFF8D9, 0x000002FE, 0x00001986, 0xFFFFF8D9, 0x000002FE }, + { 0x0213F0FD42DA38E4, 0x00003507, 0xFFFFE961, 0x00000518, 0x00001B79, 0xFFFFF775, 0x00000325, 0x00001B79, 0xFFFFF775, 0x00000325 }, + { 0x0213F0FD42DC3184, 0x00003AD5, 0xFFFFE415, 0x00000613, 0x00001CB4, 0xFFFFF66D, 0x00000348, 0x00001CB4, 0xFFFFF66D, 0x00000348 }, + { 0x0213F0FE991640E4, 0x000023D1, 0xFFFFF42B, 0x0000038F, 0x00001546, 0xFFFFFBA0, 0x0000029F, 0x00001546, 0xFFFFFBA0, 0x0000029F }, + { 0x0213F0FE990A1924, 0x0000399E, 0xFFFFE518, 0x000005E7, 0x00001990, 0xFFFFF871, 0x000002FB, 0x00001990, 0xFFFFF871, 0x000002FB }, + { 0x0213F0FD42D82964, 0x00002EDE, 0xFFFFEC93, 0x000004B8, 0x0000152C, 0xFFFFFBB3, 0x0000027E, 0x0000152C, 0xFFFFFBB3, 0x0000027E }, + { 0x0213EA94DE042964, 0x00003140, 0xFFFFEBC9, 0x000004BB, 0x000016BE, 0xFFFFFB0A, 0x00000288, 0x000016BE, 0xFFFFFB0A, 0x00000288 }, + { 0x0213F0FE99064064, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x0000185D, 0xFFFFF95A, 0x000002D9, 0x0000185D, 0xFFFFF95A, 0x000002D9 }, + { 0x0213F0FE99023844, 0x0000389C, 0xFFFFE65A, 0x000005A2, 0x0000195D, 0xFFFFF8C8, 0x000002E8, 0x0000195D, 0xFFFFF8C8, 0x000002E8 }, + { 0x0213F0FE99042104, 0x0000362B, 0xFFFFE9EC, 0x000004F6, 0x00001605, 0xFFFFFC1C, 0x00000263, 0x00001605, 0xFFFFFC1C, 0x00000263 }, + { 0x0213F0FE992A1964, 0x00002946, 0xFFFFF04F, 0x00000426, 0x000015BA, 0xFFFFFB2F, 0x000002A3, 0x000015BA, 0xFFFFFB2F, 0x000002A3 }, + { 0x0213F0FE99082184, 0x0000368E, 0xFFFFE837, 0x0000054A, 0x000017D7, 0xFFFFF9EB, 0x000002BA, 0x000017D7, 0xFFFFF9EB, 0x000002BA }, + { 0x0213F0FD42DA2844, 0x00002E74, 0xFFFFEBE8, 0x000004DA, 0x00001DD6, 0xFFFFF57E, 0x00000379, 0x00001DD6, 0xFFFFF57E, 0x00000379 }, + { 0x0213F0FE99041944, 0x0000322D, 0xFFFFEAA8, 0x000004F5, 0x00001B55, 0xFFFFF7DD, 0x0000030B, 0x00001B55, 0xFFFFF7DD, 0x0000030B }, + { 0x0213F0FE99181904, 0x00002A29, 0xFFFFF07B, 0x00000416, 0x00001671, 0xFFFFFB3E, 0x0000029F, 0x00001671, 0xFFFFFB3E, 0x0000029F }, + { 0x0213F0FD42DA2104, 0x000030F6, 0xFFFFEB89, 0x000004CD, 0x00001815, 0xFFFFF9AE, 0x000002C9, 0x00001815, 0xFFFFF9AE, 0x000002C9 }, + { 0x0213F0FE990E10E4, 0x0000265F, 0xFFFFF1CB, 0x000003D5, 0x00001ED2, 0xFFFFF539, 0x0000037A, 0x00001ED2, 0xFFFFF539, 0x0000037A }, + { 0x0213F0FE99162184, 0x000027A8, 0xFFFFF10D, 0x00000413, 0x000014B5, 0xFFFFFBA1, 0x00000299, 0x000014B5, 0xFFFFFBA1, 0x00000299 }, + { 0x0213F0FE99043064, 0x00002CEE, 0xFFFFEDF6, 0x00000476, 0x00001A99, 0xFFFFF83E, 0x00000305, 0x00001A99, 0xFFFFF83E, 0x00000305 }, + { 0x0213F0FE990640C4, 0x0000346C, 0xFFFFEA17, 0x000004EF, 0x00001D38, 0xFFFFF69F, 0x0000033D, 0x00001D38, 0xFFFFF69F, 0x0000033D }, + { 0x0213F0FD42DA2944, 0x00002DBB, 0xFFFFED35, 0x00000490, 0x000018C1, 0xFFFFF930, 0x000002DA, 0x000018C1, 0xFFFFF930, 0x000002DA }, + { 0x0213F0FE99042924, 0x000038DF, 0xFFFFE8A7, 0x0000051E, 0x00001B59, 0xFFFFF915, 0x000002D3, 0x00001B59, 0xFFFFF915, 0x000002D3 }, + { 0x0213F0FE99080944, 0x00003384, 0xFFFFE979, 0x00000524, 0x00001AF3, 0xFFFFF74C, 0x0000032F, 0x00001AF3, 0xFFFFF74C, 0x0000032F }, + { 0x0213F0FE99181864, 0x0000258B, 0xFFFFF2AE, 0x000003CB, 0x0000190C, 0xFFFFF93E, 0x000002EF, 0x0000190C, 0xFFFFF93E, 0x000002EF }, + { 0x0213F0FE99103884, 0x000034F1, 0xFFFFE84B, 0x0000055E, 0x00001CB8, 0xFFFFF670, 0x0000034A, 0x00001CB8, 0xFFFFF670, 0x0000034A }, + { 0x0213F0FE990C2104, 0x000030FB, 0xFFFFECD2, 0x00000488, 0x00001BF4, 0xFFFFF821, 0x00000302, 0x00001BF4, 0xFFFFF821, 0x00000302 }, + { 0x0213F0FE99063044, 0x000036A6, 0xFFFFE815, 0x00000556, 0x000018FD, 0xFFFFF925, 0x000002DF, 0x000018FD, 0xFFFFF925, 0x000002DF }, + { 0x0213EA94DE023044, 0x0000302A, 0xFFFFEB79, 0x000004E0, 0x00001C11, 0xFFFFF694, 0x00000358, 0x00001C11, 0xFFFFF694, 0x00000358 }, + { 0x0213F0FE99181124, 0x00002555, 0xFFFFF2C4, 0x000003CB, 0x000017E3, 0xFFFFFA1F, 0x000002CB, 0x000017E3, 0xFFFFFA1F, 0x000002CB }, + { 0x0213F0FE990A3164, 0x000032A3, 0xFFFFE933, 0x00000544, 0x000019D3, 0xFFFFF81A, 0x00000306, 0x000019D3, 0xFFFFF81A, 0x00000306 }, + { 0x0213F0FD42D85104, 0x00002B91, 0xFFFFED81, 0x000004A9, 0x0000158B, 0xFFFFFAB9, 0x000002AC, 0x0000158B, 0xFFFFFAB9, 0x000002AC }, + { 0x0213F0FE990E20C4, 0x00003537, 0xFFFFE912, 0x0000052C, 0x00001C8A, 0xFFFFF754, 0x0000031B, 0x00001C8A, 0xFFFFF754, 0x0000031B }, + { 0x0213EA94DE063184, 0x000032E1, 0xFFFFEA5A, 0x000004F9, 0x000017B4, 0xFFFFF9D9, 0x000002C2, 0x000017B4, 0xFFFFF9D9, 0x000002C2 }, + { 0x0213F0FD42D210C4, 0x00003B76, 0xFFFFE330, 0x00000636, 0x000026FB, 0xFFFFEF06, 0x00000481, 0x000026FB, 0xFFFFEF06, 0x00000481 }, + { 0x0213F0FE99042144, 0x0000320C, 0xFFFFEB84, 0x000004C3, 0x00001A3A, 0xFFFFF8E9, 0x000002DF, 0x00001A3A, 0xFFFFF8E9, 0x000002DF }, + { 0x0213F0FE99023984, 0x0000317D, 0xFFFFEA1F, 0x00000515, 0x00002100, 0xFFFFF31B, 0x000003DD, 0x00002100, 0xFFFFF31B, 0x000003DD }, + { 0x0213F0FD42D43164, 0x00003DCB, 0xFFFFE0B4, 0x000006B4, 0x00002160, 0xFFFFF269, 0x000003F0, 0x00002160, 0xFFFFF269, 0x000003F0 }, + { 0x0213F0FE991618C4, 0x00002737, 0xFFFFF218, 0x000003E1, 0x000015B5, 0xFFFFFB8F, 0x0000029C, 0x000015B5, 0xFFFFFB8F, 0x0000029C }, + { 0x0213EA94DE023184, 0x0000318F, 0xFFFFEB3F, 0x000004D8, 0x00001938, 0xFFFFF8E9, 0x000002EB, 0x00001938, 0xFFFFF8E9, 0x000002EB }, + { 0x0213F0FE991048C4, 0x000031BD, 0xFFFFE9DE, 0x00000527, 0x000018A7, 0xFFFFF8CA, 0x000002ED, 0x000018A7, 0xFFFFF8CA, 0x000002ED }, + { 0x0213F0FD42DA3884, 0x00002F77, 0xFFFFEC2F, 0x000004B4, 0x00001D25, 0xFFFFF61B, 0x0000035D, 0x00001D25, 0xFFFFF61B, 0x0000035D }, + { 0x0213F0FE990E4904, 0x00002CCA, 0xFFFFEDB3, 0x0000047C, 0x00001FBD, 0xFFFFF4A7, 0x00000391, 0x00001FBD, 0xFFFFF4A7, 0x00000391 }, + { 0x0213F0FD42D438A4, 0x00003FF6, 0xFFFFE058, 0x000006A2, 0x000024CD, 0xFFFFF026, 0x00000452, 0x000024CD, 0xFFFFF026, 0x00000452 }, + { 0x0213F0FE990A38E4, 0x00003161, 0xFFFFEAC8, 0x000004F3, 0x00001BB6, 0xFFFFF72A, 0x0000032B, 0x00001BB6, 0xFFFFF72A, 0x0000032B }, + { 0x0213F0FD42D838A4, 0x00002EA0, 0xFFFFECA6, 0x000004B7, 0x000018C2, 0xFFFFF94E, 0x000002E1, 0x000018C2, 0xFFFFF94E, 0x000002E1 }, + { 0x0213F0FE99182184, 0x00002F62, 0xFFFFEC9E, 0x000004B8, 0x00001531, 0xFFFFFBCD, 0x00000285, 0x00001531, 0xFFFFFBCD, 0x00000285 }, + { 0x0213F0FE990440A4, 0x00003013, 0xFFFFEBD6, 0x000004C2, 0x00001B01, 0xFFFFF802, 0x000002FF, 0x00001B01, 0xFFFFF802, 0x000002FF }, + { 0x0213F0FE99183064, 0x00002972, 0xFFFFF08D, 0x00000417, 0x00001A32, 0xFFFFF8A4, 0x00000305, 0x00001A32, 0xFFFFF8A4, 0x00000305 }, + { 0x0213F0FD42D820E4, 0x00002E95, 0xFFFFED94, 0x00000487, 0x00001529, 0xFFFFFC26, 0x00000271, 0x00001529, 0xFFFFFC26, 0x00000271 }, + { 0x0213F0FE990A1084, 0x00002D6A, 0xFFFFEC79, 0x000004C1, 0x00001AE2, 0xFFFFF725, 0x00000337, 0x00001AE2, 0xFFFFF725, 0x00000337 }, + { 0x0213F0FE99021884, 0x000036B4, 0xFFFFE704, 0x00000591, 0x00001E7E, 0xFFFFF51C, 0x00000383, 0x00001E7E, 0xFFFFF51C, 0x00000383 }, + { 0x0213F0FE99041844, 0x00002A6F, 0xFFFFEF70, 0x00000443, 0x00001BAA, 0xFFFFF752, 0x00000336, 0x00001BAA, 0xFFFFF752, 0x00000336 }, + { 0x0213F0FE99183944, 0x00002C66, 0xFFFFEF5F, 0x0000043A, 0x000019F7, 0xFFFFF931, 0x000002EC, 0x000019F7, 0xFFFFF931, 0x000002EC }, + { 0x0213EA94DE0631C4, 0x00003852, 0xFFFFE6AB, 0x00000590, 0x000019C1, 0xFFFFF8B1, 0x000002E5, 0x000019C1, 0xFFFFF8B1, 0x000002E5 }, + { 0x0213F0FD42DA3124, 0x00003521, 0xFFFFE932, 0x00000523, 0x000018A9, 0xFFFFF96B, 0x000002D0, 0x000018A9, 0xFFFFF96B, 0x000002D0 }, + { 0x0213F0FE99062164, 0x000031B9, 0xFFFFEB36, 0x000004D0, 0x00001D65, 0xFFFFF612, 0x0000035D, 0x00001D65, 0xFFFFF612, 0x0000035D }, + { 0x0213F0FD42D41064, 0x00003ED0, 0xFFFFE135, 0x00000679, 0x00002351, 0xFFFFF0FE, 0x00000433, 0x00002351, 0xFFFFF0FE, 0x00000433 }, + { 0x0213F0FE990A20E4, 0x000033ED, 0xFFFFE91A, 0x00000541, 0x00001C93, 0xFFFFF6A0, 0x0000034A, 0x00001C93, 0xFFFFF6A0, 0x0000034A }, + { 0x0213EA94DE021844, 0x0000356F, 0xFFFFE8F7, 0x00000530, 0x000016BF, 0xFFFFFA85, 0x000002AB, 0x000016BF, 0xFFFFFA85, 0x000002AB }, + { 0x0213F0FE991840E4, 0x00002304, 0xFFFFF4F3, 0x00000364, 0x000017CC, 0xFFFFFA41, 0x000002CA, 0x000017CC, 0xFFFFFA41, 0x000002CA }, + { 0x0213F0FE99161164, 0x00002887, 0xFFFFEFD7, 0x00000450, 0x00001474, 0xFFFFFB94, 0x00000299, 0x00001474, 0xFFFFFB94, 0x00000299 }, + { 0x0213F0FE99063064, 0x00003D0B, 0xFFFFE416, 0x000005EF, 0x00001C7E, 0xFFFFF71D, 0x00000325, 0x00001C7E, 0xFFFFF71D, 0x00000325 }, + { 0x0213F0FE990810E4, 0x00003185, 0xFFFFEAFA, 0x000004E4, 0x00001A12, 0xFFFFF83C, 0x00000303, 0x00001A12, 0xFFFFF83C, 0x00000303 }, + { 0x0213F0FE990A1944, 0x00003032, 0xFFFFEAE6, 0x000004FC, 0x00001B2A, 0xFFFFF73F, 0x0000032B, 0x00001B2A, 0xFFFFF73F, 0x0000032B }, + { 0x0213F0FD42D838C4, 0x00002691, 0xFFFFF22D, 0x000003D6, 0x00001700, 0xFFFFFA6E, 0x000002C0, 0x00001700, 0xFFFFFA6E, 0x000002C0 }, + { 0x0213F0FE990218A4, 0x00002B2F, 0xFFFFEEC4, 0x0000044B, 0x0000215F, 0xFFFFF33F, 0x000003D2, 0x0000215F, 0xFFFFF33F, 0x000003D2 }, + { 0x0213F0FE990A4184, 0x000034AA, 0xFFFFE706, 0x000005B1, 0x00001B28, 0xFFFFF6B5, 0x00000349, 0x00001B28, 0xFFFFF6B5, 0x00000349 }, + { 0x0213F0FD42DA2964, 0x0000307E, 0xFFFFEB38, 0x000004E6, 0x00001A22, 0xFFFFF83F, 0x00000300, 0x00001A22, 0xFFFFF83F, 0x00000300 }, + { 0x0213F0FE990618A4, 0x000038D6, 0xFFFFE6D8, 0x0000057C, 0x00001B24, 0xFFFFF7E4, 0x00000307, 0x00001B24, 0xFFFFF7E4, 0x00000307 }, + { 0x0213F0FE99183044, 0x00002757, 0xFFFFF1E8, 0x000003DD, 0x000017F5, 0xFFFFFA15, 0x000002C8, 0x000017F5, 0xFFFFFA15, 0x000002C8 }, + { 0x0213F0FE99083184, 0x000031FC, 0xFFFFEB3E, 0x000004CE, 0x00001B4C, 0xFFFFF7AD, 0x00000319, 0x00001B4C, 0xFFFFF7AD, 0x00000319 }, + { 0x0213F0FE99301864, 0x00002933, 0xFFFFF073, 0x0000040E, 0x00001C3C, 0xFFFFF701, 0x0000033C, 0x00001C3C, 0xFFFFF701, 0x0000033C }, + { 0x0213F0FD42D218A4, 0x000040BB, 0xFFFFE066, 0x0000069A, 0x0000257F, 0xFFFFF08A, 0x00000435, 0x0000257F, 0xFFFFF08A, 0x00000435 }, + { 0x0213F0FE991010A4, 0x0000305B, 0xFFFFEB9B, 0x000004CB, 0x00001996, 0xFFFFF846, 0x00000308, 0x00001996, 0xFFFFF846, 0x00000308 }, + { 0x0213F0FE99064884, 0x000039C0, 0xFFFFE5D3, 0x000005B0, 0x00001A8D, 0xFFFFF7DA, 0x00000313, 0x00001A8D, 0xFFFFF7DA, 0x00000313 }, + { 0x0213EA94DE0210A4, 0x00002E23, 0xFFFFED3F, 0x0000048F, 0x0000189D, 0xFFFFF94C, 0x000002DE, 0x0000189D, 0xFFFFF94C, 0x000002DE }, + { 0x0213EA94DE021984, 0x0000332B, 0xFFFFE9F1, 0x00000516, 0x000018E6, 0xFFFFF8FE, 0x000002EC, 0x000018E6, 0xFFFFF8FE, 0x000002EC }, + { 0x0213F0FE990838C4, 0x000034A0, 0xFFFFEA44, 0x000004E4, 0x00001ECD, 0xFFFFF5B4, 0x00000364, 0x00001ECD, 0xFFFFF5B4, 0x00000364 }, + { 0x0213F0FD42D24104, 0x0000448C, 0xFFFFDF34, 0x000006A8, 0x0000231C, 0xFFFFF286, 0x000003D9, 0x0000231C, 0xFFFFF286, 0x000003D9 }, + { 0x0213EA94DE062144, 0x00002D8C, 0xFFFFEE65, 0x00000456, 0x000018B1, 0xFFFFF9C8, 0x000002C8, 0x000018B1, 0xFFFFF9C8, 0x000002C8 }, + { 0x0213F0FE99061904, 0x00003527, 0xFFFFE9BF, 0x000004FD, 0x00001D23, 0xFFFFF69F, 0x00000342, 0x00001D23, 0xFFFFF69F, 0x00000342 }, + { 0x0213F0FD42DC38A4, 0x00002C51, 0xFFFFEDC3, 0x00000483, 0x00001BE0, 0xFFFFF720, 0x0000032D, 0x00001BE0, 0xFFFFF720, 0x0000032D }, + { 0x0213F0FE990A3044, 0x00002C6C, 0xFFFFECEB, 0x000004B7, 0x00001C86, 0xFFFFF5E7, 0x00000371, 0x00001C86, 0xFFFFF5E7, 0x00000371 }, + { 0x0213F0FE99045144, 0x000037CF, 0xFFFFE6BE, 0x00000599, 0x000018CD, 0xFFFFF967, 0x000002C7, 0x000018CD, 0xFFFFF967, 0x000002C7 }, + { 0x0213F0FE99103164, 0x00002E6F, 0xFFFFED1D, 0x0000048E, 0x00001ADC, 0xFFFFF7F4, 0x0000030E, 0x00001ADC, 0xFFFFF7F4, 0x0000030E }, + { 0x0213F0FD42D42984, 0x00003FF3, 0xFFFFDF13, 0x000006F9, 0x000025BF, 0xFFFFEEEE, 0x00000497, 0x000025BF, 0xFFFFEEEE, 0x00000497 }, + { 0x0213F0FD42DC5104, 0x00004135, 0xFFFFDF97, 0x000006CC, 0x00001D52, 0xFFFFF541, 0x00000383, 0x00001D52, 0xFFFFF541, 0x00000383 }, + { 0x0213F0FD42DC20E4, 0x00002EA9, 0xFFFFEDDB, 0x0000045F, 0x0000197C, 0xFFFFF8E1, 0x000002F0, 0x0000197C, 0xFFFFF8E1, 0x000002F0 }, + { 0x0213EA94DE043084, 0x0000345C, 0xFFFFE922, 0x00000532, 0x00001922, 0xFFFFF8C7, 0x000002F1, 0x00001922, 0xFFFFF8C7, 0x000002F1 }, + { 0x0213F0FE99064124, 0x000035C4, 0xFFFFE8FE, 0x00000521, 0x00001C87, 0xFFFFF6F3, 0x00000330, 0x00001C87, 0xFFFFF6F3, 0x00000330 }, + { 0x0213F0FD42D83164, 0x00002888, 0xFFFFF08A, 0x0000041E, 0x0000150F, 0xFFFFFB87, 0x00000291, 0x0000150F, 0xFFFFFB87, 0x00000291 }, + { 0x0213F0FE990A1124, 0x000035E9, 0xFFFFE657, 0x000005CC, 0x00001BD6, 0xFFFFF664, 0x00000355, 0x00001BD6, 0xFFFFF664, 0x00000355 }, + { 0x0213F0FE991648E4, 0x00002F94, 0xFFFFEBD0, 0x000004E5, 0x00001333, 0xFFFFFCA7, 0x00000266, 0x00001333, 0xFFFFFCA7, 0x00000266 }, + { 0x0213F0FE99181964, 0x000029E7, 0xFFFFF009, 0x00000433, 0x0000144A, 0xFFFFFC37, 0x0000027D, 0x0000144A, 0xFFFFFC37, 0x0000027D }, + { 0x0213F0FE992C1944, 0x00003418, 0xFFFFE979, 0x00000521, 0x00001D33, 0xFFFFF66B, 0x0000034A, 0x00001D33, 0xFFFFF66B, 0x0000034A }, + { 0x0213EA94DE0440E4, 0x00003656, 0xFFFFE79D, 0x0000057A, 0x000017C2, 0xFFFFF992, 0x000002D4, 0x000017C2, 0xFFFFF992, 0x000002D4 }, + { 0x0213F0FE990C40C4, 0x00002EB2, 0xFFFFECFE, 0x00000493, 0x00001F2A, 0xFFFFF543, 0x0000037B, 0x00001F2A, 0xFFFFF543, 0x0000037B }, + { 0x0213F0FE99021124, 0x00002FC1, 0xFFFFEB3F, 0x000004E8, 0x00001CD0, 0xFFFFF5F7, 0x00000364, 0x00001CD0, 0xFFFFF5F7, 0x00000364 }, + { 0x0213F0FE990C1124, 0x0000307B, 0xFFFFEB66, 0x000004DE, 0x00001953, 0xFFFFF8ED, 0x000002E4, 0x00001953, 0xFFFFF8ED, 0x000002E4 }, + { 0x0213F0FD42DA1884, 0x00002CAA, 0xFFFFED07, 0x000004AC, 0x0000251C, 0xFFFFF086, 0x0000044D, 0x0000251C, 0xFFFFF086, 0x0000044D }, + { 0x0213EA94DE043944, 0x00002C94, 0xFFFFEE5F, 0x0000045B, 0x000018D7, 0xFFFFF900, 0x000002EB, 0x000018D7, 0xFFFFF900, 0x000002EB }, + { 0x0213F0FE99021864, 0x000031F1, 0xFFFFE9BE, 0x0000052E, 0x00001DDF, 0xFFFFF558, 0x00000380, 0x00001DDF, 0xFFFFF558, 0x00000380 }, + { 0x0213F0FE990E50C4, 0x00002603, 0xFFFFF1E9, 0x000003DA, 0x00001B37, 0xFFFFF75A, 0x0000032F, 0x00001B37, 0xFFFFF75A, 0x0000032F }, + { 0x0213F0FD42DA3044, 0x00003992, 0xFFFFE4F9, 0x000005EB, 0x00001775, 0xFFFFF9B8, 0x000002C2, 0x00001775, 0xFFFFF9B8, 0x000002C2 }, + { 0x0213F0FE99184964, 0x000029DA, 0xFFFFF052, 0x0000041F, 0x000016E2, 0xFFFFFA99, 0x000002BB, 0x000016E2, 0xFFFFFA99, 0x000002BB }, + { 0x0213F0FE99101064, 0x00002FF2, 0xFFFFEB8F, 0x000004DF, 0x00001AF6, 0xFFFFF7A1, 0x00000321, 0x00001AF6, 0xFFFFF7A1, 0x00000321 }, + { 0x0213F0FE991608E4, 0x00002590, 0xFFFFF222, 0x000003EE, 0x0000130B, 0xFFFFFCC9, 0x00000268, 0x0000130B, 0xFFFFFCC9, 0x00000268 }, + { 0x0213F0FE99024064, 0x000038A2, 0xFFFFE65F, 0x000005A2, 0x000018B1, 0xFFFFF917, 0x000002E1, 0x000018B1, 0xFFFFF917, 0x000002E1 }, + { 0x0213F0FD42DC48E4, 0x000035FD, 0xFFFFE73C, 0x0000058D, 0x00001BB3, 0xFFFFF6E1, 0x00000337, 0x00001BB3, 0xFFFFF6E1, 0x00000337 }, + { 0x0213F0FE991038C4, 0x00002AB7, 0xFFFFEF98, 0x00000429, 0x00001F35, 0xFFFFF539, 0x0000037C, 0x00001F35, 0xFFFFF539, 0x0000037C }, + { 0x0213F0FE990A0944, 0x000034BA, 0xFFFFE73D, 0x000005A6, 0x000018A6, 0xFFFFF888, 0x000002FB, 0x000018A6, 0xFFFFF888, 0x000002FB }, + { 0x0213F0FE99063844, 0x000032EA, 0xFFFFEA78, 0x000004F4, 0x00001AB6, 0xFFFFF812, 0x00000308, 0x00001AB6, 0xFFFFF812, 0x00000308 }, + { 0x0213F0FE990C3044, 0x00002BE9, 0xFFFFEE9A, 0x00000457, 0x00001942, 0xFFFFF8D2, 0x000002F2, 0x00001942, 0xFFFFF8D2, 0x000002F2 }, + { 0x0213F0FE99105124, 0x00002FAB, 0xFFFFEB76, 0x000004E1, 0x00001DCA, 0xFFFFF57D, 0x00000378, 0x00001DCA, 0xFFFFF57D, 0x00000378 }, + { 0x0213F0FE992E2844, 0x0000330A, 0xFFFFE9E1, 0x0000051B, 0x00001CC4, 0xFFFFF6DF, 0x00000335, 0x00001CC4, 0xFFFFF6DF, 0x00000335 }, + { 0x0213F0FE991828A4, 0x000027D8, 0xFFFFF276, 0x000003BF, 0x0000178A, 0xFFFFFABF, 0x000002B5, 0x0000178A, 0xFFFFFABF, 0x000002B5 }, + { 0x0213F0FD42DC3864, 0x0000340A, 0xFFFFE86D, 0x00000562, 0x00001B85, 0xFFFFF719, 0x0000032F, 0x00001B85, 0xFFFFF719, 0x0000032F }, + { 0x0213EA94DE063084, 0x00003879, 0xFFFFE73F, 0x00000578, 0x0000161C, 0xFFFFFB6B, 0x00000281, 0x0000161C, 0xFFFFFB6B, 0x00000281 }, + { 0x0213F0FE99184064, 0x00002879, 0xFFFFF0F8, 0x0000040A, 0x00001749, 0xFFFFFA37, 0x000002CC, 0x00001749, 0xFFFFFA37, 0x000002CC }, + { 0x0213F0FE99043964, 0x00002C3A, 0xFFFFEEA0, 0x0000044F, 0x00001D57, 0xFFFFF6C2, 0x00000332, 0x00001D57, 0xFFFFF6C2, 0x00000332 }, + { 0x0213EA94DE021964, 0x000035BB, 0xFFFFE90D, 0x0000052A, 0x000017D9, 0xFFFFF9F5, 0x000002C3, 0x000017D9, 0xFFFFF9F5, 0x000002C3 }, + { 0x0213EA94DE041124, 0x000031F1, 0xFFFFEAD4, 0x000004ED, 0x00001F10, 0xFFFFF539, 0x0000037D, 0x00001F10, 0xFFFFF539, 0x0000037D }, + { 0x0213F0FE99102824, 0x00002A1A, 0xFFFFEFAD, 0x00000430, 0x00001D47, 0xFFFFF62F, 0x0000035E, 0x00001D47, 0xFFFFF62F, 0x0000035E }, + { 0x0213F0FE99164924, 0x00002AF0, 0xFFFFEEDC, 0x00000465, 0x0000145F, 0xFFFFFBEB, 0x00000281, 0x0000145F, 0xFFFFFBEB, 0x00000281 }, + { 0x0213F0FE99183164, 0x00002657, 0xFFFFF2E0, 0x000003B6, 0x00001664, 0xFFFFFB37, 0x000002A2, 0x00001664, 0xFFFFFB37, 0x000002A2 }, + { 0x0213F0FD42D03864, 0x00003183, 0xFFFFE9F1, 0x0000052B, 0x00002020, 0xFFFFF3CE, 0x000003C1, 0x00002020, 0xFFFFF3CE, 0x000003C1 }, + { 0x0213F0FD42C628E4, 0x00003240, 0xFFFFEB65, 0x000004C7, 0x00002425, 0xFFFFF245, 0x000003F3, 0x00002425, 0xFFFFF245, 0x000003F3 }, + { 0x0213EA94DE321104, 0x000023D0, 0xFFFFF400, 0x00000397, 0x00001345, 0xFFFFFD6B, 0x00000241, 0x00001345, 0xFFFFFD6B, 0x00000241 }, + { 0x0213F0FD42CE38A4, 0x00003440, 0xFFFFE872, 0x0000055B, 0x00002247, 0xFFFFF296, 0x000003E8, 0x00002247, 0xFFFFF296, 0x000003E8 }, + { 0x0213F0FD42D04904, 0x00003275, 0xFFFFE970, 0x00000538, 0x00001F94, 0xFFFFF429, 0x000003AD, 0x00001F94, 0xFFFFF429, 0x000003AD }, + { 0x0213F0FD42C640A4, 0x00003918, 0xFFFFE5DA, 0x000005B6, 0x000024FC, 0xFFFFF106, 0x00000426, 0x000024FC, 0xFFFFF106, 0x00000426 }, + { 0x0213EA94DE062044, 0x0000334B, 0xFFFFEA39, 0x000004FD, 0x00001983, 0xFFFFF8F6, 0x000002E2, 0x00001983, 0xFFFFF8F6, 0x000002E2 }, + { 0x0213F0FD42C64984, 0x00003B59, 0xFFFFE4D0, 0x000005DA, 0x00002605, 0xFFFFF090, 0x00000439, 0x00002605, 0xFFFFF090, 0x00000439 }, + { 0x0213F0FD42D03124, 0x00003251, 0xFFFFEA46, 0x00000511, 0x00002781, 0xFFFFEF84, 0x00000470, 0x00002781, 0xFFFFEF84, 0x00000470 }, + { 0x0213F0FD42CA3164, 0x00003304, 0xFFFFE926, 0x00000542, 0x00001EE9, 0xFFFFF4E4, 0x0000038B, 0x00001EE9, 0xFFFFF4E4, 0x0000038B }, + { 0x0213F0FD42CC38C4, 0x00002F4C, 0xFFFFEC0C, 0x000004C4, 0x00001E49, 0xFFFFF578, 0x00000374, 0x00001E49, 0xFFFFF578, 0x00000374 }, + { 0x0213EA94DE1C2164, 0x00002034, 0xFFFFF692, 0x0000034C, 0x000014B8, 0xFFFFFC5B, 0x00000294, 0x000014B8, 0xFFFFFC5B, 0x00000294 }, + { 0x0213F0FD42CE4924, 0x0000385F, 0xFFFFE513, 0x000005F3, 0x000024E7, 0xFFFFF053, 0x00000450, 0x000024E7, 0xFFFFF053, 0x00000450 }, + { 0x0213EA94DE1C40E4, 0x00001D70, 0xFFFFF821, 0x0000030F, 0x00001541, 0xFFFFFBB4, 0x000002B0, 0x00001541, 0xFFFFFBB4, 0x000002B0 }, + { 0x0213F0FD42D02084, 0x000034EB, 0xFFFFE7FF, 0x00000575, 0x000019B4, 0xFFFFF836, 0x00000308, 0x000019B4, 0xFFFFF836, 0x00000308 }, + { 0x0213F0FD42D050E4, 0x000037C9, 0xFFFFE5D4, 0x000005CD, 0x000026A1, 0xFFFFEF0C, 0x00000491, 0x000026A1, 0xFFFFEF0C, 0x00000491 }, + { 0x0213EA94DE121944, 0x00002918, 0xFFFFF148, 0x000003E9, 0x00001A49, 0xFFFFF94C, 0x000002CF, 0x00001A49, 0xFFFFF94C, 0x000002CF }, + { 0x0213F0FD42CA4064, 0x00002F90, 0xFFFFEAB5, 0x00000514, 0x00001707, 0xFFFFF9C7, 0x000002C4, 0x00001707, 0xFFFFF9C7, 0x000002C4 }, + { 0x0213EA94DE062064, 0x0000327E, 0xFFFFEA99, 0x000004F4, 0x0000194F, 0xFFFFF929, 0x000002DC, 0x0000194F, 0xFFFFF929, 0x000002DC }, + { 0x0213F0FD42C64084, 0x0000326F, 0xFFFFE9CF, 0x00000519, 0x00002240, 0xFFFFF299, 0x000003E7, 0x00002240, 0xFFFFF299, 0x000003E7 }, + { 0x0213EA94DE321124, 0x000022FB, 0xFFFFF4C6, 0x00000371, 0x00001506, 0xFFFFFC73, 0x00000265, 0x00001506, 0xFFFFFC73, 0x00000265 }, + { 0x0213F0FD42CA3924, 0x00003AD6, 0xFFFFE470, 0x000005FE, 0x00001F03, 0xFFFFF4F3, 0x00000387, 0x00001F03, 0xFFFFF4F3, 0x00000387 }, + { 0x0213EA94DE201124, 0x00001F11, 0xFFFFF756, 0x00000332, 0x00001666, 0xFFFFFB8A, 0x000002B2, 0x00001666, 0xFFFFFB8A, 0x000002B2 }, + { 0x0213EA94DE0238A4, 0x00002A5F, 0xFFFFEFA7, 0x00000430, 0x00001943, 0xFFFFF8C6, 0x000002F7, 0x00001943, 0xFFFFF8C6, 0x000002F7 }, + { 0x0213EA94DE1650E4, 0x0000235E, 0xFFFFF3B4, 0x000003B3, 0x00001489, 0xFFFFFBCF, 0x0000029B, 0x00001489, 0xFFFFFBCF, 0x0000029B }, + { 0x0213F0FD42CC38A4, 0x00003570, 0xFFFFE780, 0x0000058D, 0x00001B1D, 0xFFFFF767, 0x00000325, 0x00001B1D, 0xFFFFF767, 0x00000325 }, + { 0x0213EA94DE042064, 0x00003678, 0xFFFFE7C3, 0x00000569, 0x00001831, 0xFFFFF98E, 0x000002C8, 0x00001831, 0xFFFFF98E, 0x000002C8 }, + { 0x0213EA94DE201864, 0x000020B9, 0xFFFFF625, 0x0000035A, 0x000015C5, 0xFFFFFB8A, 0x000002B5, 0x000015C5, 0xFFFFFB8A, 0x000002B5 }, + { 0x0213F0FD42C63184, 0x00003985, 0xFFFFE529, 0x000005DD, 0x00002165, 0xFFFFF351, 0x000003C5, 0x00002165, 0xFFFFF351, 0x000003C5 }, + { 0x0213F0FD42D02064, 0x0000322A, 0xFFFFE99D, 0x00000535, 0x000019A1, 0xFFFFF844, 0x00000305, 0x000019A1, 0xFFFFF844, 0x00000305 }, + { 0x0213F0FD42D05104, 0x000033ED, 0xFFFFE834, 0x00000571, 0x00002094, 0xFFFFF33A, 0x000003DB, 0x00002094, 0xFFFFF33A, 0x000003DB }, + { 0x0213EA94DE2040C4, 0x00001D10, 0xFFFFF84D, 0x0000030B, 0x00001659, 0xFFFFFB0A, 0x000002CB, 0x00001659, 0xFFFFFB0A, 0x000002CB }, + { 0x0213EA94DE1C1124, 0x0000210F, 0xFFFFF644, 0x00000355, 0x00001A4A, 0xFFFFF90F, 0x00000310, 0x00001A4A, 0xFFFFF90F, 0x00000310 }, + { 0x0213EA94DE164164, 0x00001CA8, 0xFFFFF813, 0x00000316, 0x00001440, 0xFFFFFC1C, 0x0000029D, 0x00001440, 0xFFFFFC1C, 0x0000029D }, + { 0x0213EA94DE3210C4, 0x00002864, 0xFFFFF15A, 0x000003FA, 0x0000137F, 0xFFFFFD43, 0x00000248, 0x0000137F, 0xFFFFFD43, 0x00000248 }, + { 0x0213F0FD42D04184, 0x00002CDB, 0xFFFFECFD, 0x000004A7, 0x00002472, 0xFFFFF0E1, 0x00000437, 0x00002472, 0xFFFFF0E1, 0x00000437 }, + { 0x0213F0FD42CC5104, 0x00003348, 0xFFFFE8CA, 0x00000554, 0x00001E91, 0xFFFFF4D4, 0x00000392, 0x00001E91, 0xFFFFF4D4, 0x00000392 }, + { 0x0213F0FD42C64944, 0x00003989, 0xFFFFE4BB, 0x000005F8, 0x00001ACB, 0xFFFFF780, 0x00000319, 0x00001ACB, 0xFFFFF780, 0x00000319 }, + { 0x0213F0FD42CA2104, 0x00003238, 0xFFFFEA09, 0x0000051E, 0x00001F08, 0xFFFFF4F4, 0x0000038C, 0x00001F08, 0xFFFFF4F4, 0x0000038C }, + { 0x0213EA94DE120904, 0x00002453, 0xFFFFF3B0, 0x0000038D, 0x00001AED, 0xFFFFF8A2, 0x000002EA, 0x00001AED, 0xFFFFF8A2, 0x000002EA }, + { 0x0213EA94DE1C3024, 0x00002459, 0xFFFFF409, 0x000003A8, 0x000017B5, 0xFFFFFA53, 0x000002E1, 0x000017B5, 0xFFFFFA53, 0x000002E1 }, + { 0x0213EA94DE021184, 0x0000310D, 0xFFFFEB78, 0x000004D0, 0x00001DC9, 0xFFFFF5D5, 0x00000368, 0x00001DC9, 0xFFFFF5D5, 0x00000368 }, + { 0x0213EA94DE023104, 0x000031BF, 0xFFFFECA3, 0x00000498, 0x00001DC9, 0xFFFFF717, 0x00000336, 0x00001DC9, 0xFFFFF717, 0x00000336 }, + { 0x0213F0FD42CE2104, 0x00003896, 0xFFFFE5DD, 0x000005C5, 0x000023E2, 0xFFFFF1A1, 0x00000416, 0x000023E2, 0xFFFFF1A1, 0x00000416 }, + { 0x0213EA94DE323904, 0x000023CB, 0xFFFFF4C8, 0x00000372, 0x00001C33, 0xFFFFF7D5, 0x0000032A, 0x00001C33, 0xFFFFF7D5, 0x0000032A }, + { 0x0213F0FD42D020C4, 0x00002F6B, 0xFFFFEBF0, 0x000004CE, 0x00001C89, 0xFFFFF689, 0x0000034D, 0x00001C89, 0xFFFFF689, 0x0000034D }, + { 0x0213F0FD42CE3904, 0x00003E72, 0xFFFFE211, 0x0000065D, 0x0000218D, 0xFFFFF309, 0x000003DC, 0x0000218D, 0xFFFFF309, 0x000003DC }, + { 0x0213EA94DE022084, 0x00002612, 0xFFFFF2C3, 0x000003AD, 0x000019F7, 0xFFFFF891, 0x000002FE, 0x000019F7, 0xFFFFF891, 0x000002FE }, + { 0x0213EA94DE164184, 0x0000205D, 0xFFFFF59F, 0x00000372, 0x000012E6, 0xFFFFFD0A, 0x00000270, 0x000012E6, 0xFFFFFD0A, 0x00000270 }, + { 0x0213F0FD42CA2124, 0x00002ECB, 0xFFFFEC47, 0x000004BD, 0x00001936, 0xFFFFF8D9, 0x000002E4, 0x00001936, 0xFFFFF8D9, 0x000002E4 }, + { 0x0213EA94DE064904, 0x00002BDB, 0xFFFFEE6D, 0x00000458, 0x00001852, 0xFFFFF943, 0x000002D9, 0x00001852, 0xFFFFF943, 0x000002D9 }, + { 0x0213EA94DE124904, 0x00003387, 0xFFFFE958, 0x00000534, 0x00001932, 0xFFFFF8FA, 0x000002E4, 0x00001932, 0xFFFFF8FA, 0x000002E4 }, + { 0x0213EA94DE0208C4, 0x00002E3C, 0xFFFFED26, 0x00000495, 0x00001858, 0xFFFFF990, 0x000002D1, 0x00001858, 0xFFFFF990, 0x000002D1 }, + { 0x0213EA94DE022964, 0x000033B8, 0xFFFFEA5C, 0x000004F9, 0x00001BD1, 0xFFFFF76A, 0x0000032E, 0x00001BD1, 0xFFFFF76A, 0x0000032E }, + { 0x0213EA94DE062984, 0x00002BCE, 0xFFFFEEE9, 0x00000443, 0x00001982, 0xFFFFF90D, 0x000002DF, 0x00001982, 0xFFFFF90D, 0x000002DF }, + { 0x0213F0FD42D048E4, 0x00003495, 0xFFFFE7D9, 0x0000057B, 0x00001D2A, 0xFFFFF5A5, 0x00000372, 0x00001D2A, 0xFFFFF5A5, 0x00000372 }, + { 0x0213F0FD42CA38E4, 0x000034B1, 0xFFFFE88D, 0x00000556, 0x00002014, 0xFFFFF43A, 0x000003AA, 0x00002014, 0xFFFFF43A, 0x000003AA }, + { 0x0213F0FD42CC3124, 0x00002F96, 0xFFFFEC84, 0x000004AD, 0x000024A2, 0xFFFFF1CE, 0x0000040A, 0x000024A2, 0xFFFFF1CE, 0x0000040A }, + { 0x0213EA94DE161064, 0x0000203B, 0xFFFFF640, 0x00000359, 0x000014EC, 0xFFFFFC14, 0x0000029C, 0x000014EC, 0xFFFFFC14, 0x0000029C }, + { 0x0213F0FD42D02984, 0x000034E2, 0xFFFFE7B8, 0x00000582, 0x00001938, 0xFFFFF872, 0x000002FA, 0x00001938, 0xFFFFF872, 0x000002FA }, + { 0x0213EA94DE063124, 0x00002AC7, 0xFFFFF0C1, 0x000003F5, 0x00002268, 0xFFFFF39C, 0x000003C9, 0x00002268, 0xFFFFF39C, 0x000003C9 }, + { 0x0213F0FD42C63144, 0x000036F6, 0xFFFFE77F, 0x00000571, 0x000027D9, 0xFFFFEF6F, 0x00000461, 0x000027D9, 0xFFFFEF6F, 0x00000461 }, + { 0x0213EA94DE123124, 0x00002BAB, 0xFFFFF018, 0x00000419, 0x00002126, 0xFFFFF4E2, 0x0000038F, 0x00002126, 0xFFFFF4E2, 0x0000038F }, + { 0x0213EA94DE323924, 0x000028C4, 0xFFFFF161, 0x000003F8, 0x0000180C, 0xFFFFFA4B, 0x000002C8, 0x0000180C, 0xFFFFFA4B, 0x000002C8 }, + { 0x0213F0FD42CA2864, 0x00002F48, 0xFFFFEB62, 0x000004EE, 0x00001912, 0xFFFFF8C8, 0x000002EA, 0x00001912, 0xFFFFF8C8, 0x000002EA }, + { 0x0213F0FD42CE2864, 0x000032DF, 0xFFFFE911, 0x00000545, 0x00001F06, 0xFFFFF485, 0x0000039C, 0x00001F06, 0xFFFFF485, 0x0000039C }, + { 0x0213F0FD42D04144, 0x000035B8, 0xFFFFE74F, 0x00000590, 0x00001FD7, 0xFFFFF410, 0x000003AF, 0x00001FD7, 0xFFFFF410, 0x000003AF }, + { 0x0213F0FD42D050C4, 0x00003608, 0xFFFFE6D7, 0x000005A9, 0x000024A6, 0xFFFFF075, 0x00000450, 0x000024A6, 0xFFFFF075, 0x00000450 }, + { 0x0213F0FD42CA3884, 0x000030AB, 0xFFFFEAED, 0x000004F5, 0x000019EE, 0xFFFFF84E, 0x000002FC, 0x000019EE, 0xFFFFF84E, 0x000002FC }, + { 0x0213EA94DE0620C4, 0x000030C6, 0xFFFFEC92, 0x0000049E, 0x000019BB, 0xFFFFF8F1, 0x000002F3, 0x000019BB, 0xFFFFF8F1, 0x000002F3 }, + { 0x0213F0FD42C630A4, 0x00003B27, 0xFFFFE544, 0x000005C1, 0x00002697, 0xFFFFF072, 0x00000438, 0x00002697, 0xFFFFF072, 0x00000438 }, + { 0x0213EA94DE1248E4, 0x00002F23, 0xFFFFEC48, 0x000004B9, 0x0000199A, 0xFFFFF8CF, 0x000002E9, 0x0000199A, 0xFFFFF8CF, 0x000002E9 }, + { 0x0213EA94DE0629A4, 0x00002BD7, 0xFFFFEEAC, 0x00000450, 0x00001991, 0xFFFFF8F4, 0x000002E2, 0x00001991, 0xFFFFF8F4, 0x000002E2 }, + { 0x0213EA94DE022024, 0x00003210, 0xFFFFEB24, 0x000004DE, 0x00001BDF, 0xFFFFF744, 0x00000333, 0x00001BDF, 0xFFFFF744, 0x00000333 }, + { 0x0213EA94DE244144, 0x00002DDC, 0xFFFFED0D, 0x000004AC, 0x000019D0, 0xFFFFF869, 0x0000030F, 0x000019D0, 0xFFFFF869, 0x0000030F }, + { 0x0213EA94DE203964, 0x000023E6, 0xFFFFF40C, 0x000003A9, 0x000014EB, 0xFFFFFBC4, 0x000002AF, 0x000014EB, 0xFFFFFBC4, 0x000002AF }, + { 0x0213F0FD42CA29A4, 0x000030CE, 0xFFFFE9A5, 0x0000053C, 0x00001C45, 0xFFFFF60E, 0x0000035D, 0x00001C45, 0xFFFFF60E, 0x0000035D }, + { 0x0213EA94DE161084, 0x00001E89, 0xFFFFF73A, 0x00000337, 0x0000157C, 0xFFFFFBC0, 0x000002AA, 0x0000157C, 0xFFFFFBC0, 0x000002AA }, + { 0x0213F0FD42D04124, 0x000036C6, 0xFFFFE6CF, 0x000005A1, 0x00002457, 0xFFFFF11D, 0x0000042D, 0x00002457, 0xFFFFF11D, 0x0000042D }, + { 0x0213EA94DE321944, 0x00002815, 0xFFFFF19A, 0x000003F2, 0x000016D2, 0xFFFFFB40, 0x00000299, 0x000016D2, 0xFFFFFB40, 0x00000299 }, + { 0x0213EA94DE1C19A4, 0x00001FE2, 0xFFFFF660, 0x00000354, 0x000015A7, 0xFFFFFB47, 0x000002C1, 0x000015A7, 0xFFFFFB47, 0x000002C1 }, + { 0x0213EA94DE161964, 0x00002114, 0xFFFFF634, 0x00000356, 0x000016C1, 0xFFFFFB43, 0x000002B8, 0x000016C1, 0xFFFFFB43, 0x000002B8 }, + { 0x0213F0FD42CC28C4, 0x000028E3, 0xFFFFF075, 0x00000414, 0x0000203C, 0xFFFFF438, 0x000003B3, 0x0000203C, 0xFFFFF438, 0x000003B3 }, + { 0x0213EA94DE1C3924, 0x00001EEB, 0xFFFFF7BB, 0x0000031A, 0x00001580, 0xFFFFFBD7, 0x000002AD, 0x00001580, 0xFFFFFBD7, 0x000002AD }, + { 0x0213EA94DE2408C4, 0x00002BB2, 0xFFFFEE72, 0x00000470, 0x0000192C, 0xFFFFF91E, 0x000002E7, 0x0000192C, 0xFFFFF91E, 0x000002E7 }, + { 0x0213EA94DE0650E4, 0x00003A3D, 0xFFFFE49D, 0x000005F5, 0x00001A3B, 0xFFFFF7B1, 0x00000320, 0x00001A3B, 0xFFFFF7B1, 0x00000320 }, + { 0x0213F0FD42CE3164, 0x00002E93, 0xFFFFEC5A, 0x000004B4, 0x000025EB, 0xFFFFF03C, 0x0000044A, 0x000025EB, 0xFFFFF03C, 0x0000044A }, + { 0x0213F0FD42CA20C4, 0x0000331F, 0xFFFFE97A, 0x00000531, 0x00001A06, 0xFFFFF850, 0x000002FD, 0x00001A06, 0xFFFFF850, 0x000002FD }, + { 0x0213F0FD42C63964, 0x00003937, 0xFFFFE5A0, 0x000005C7, 0x0000235E, 0xFFFFF234, 0x000003F2, 0x0000235E, 0xFFFFF234, 0x000003F2 }, + { 0x0213EA94DE1E3924, 0x00001DD0, 0xFFFFF80E, 0x00000319, 0x000015C7, 0xFFFFFB91, 0x000002BC, 0x000015C7, 0xFFFFFB91, 0x000002BC }, + { 0x0213F0FD42D03964, 0x00003328, 0xFFFFE905, 0x0000054A, 0x00002054, 0xFFFFF3BF, 0x000003C0, 0x00002054, 0xFFFFF3BF, 0x000003C0 }, + { 0x0213F0FD42CC1104, 0x00002FE5, 0xFFFFEA65, 0x00000520, 0x0000188B, 0xFFFFF8A7, 0x000002F5, 0x0000188B, 0xFFFFF8A7, 0x000002F5 }, + { 0x0213F0FD42CA38A4, 0x00002ED3, 0xFFFFEC51, 0x000004B9, 0x00001888, 0xFFFFF96A, 0x000002CA, 0x00001888, 0xFFFFF96A, 0x000002CA }, + { 0x0213F0FD42D03084, 0x00002FCC, 0xFFFFEB60, 0x000004EA, 0x00001F8D, 0xFFFFF436, 0x000003B4, 0x00001F8D, 0xFFFFF436, 0x000003B4 }, + { 0x0213F0FD42CE4084, 0x0000329F, 0xFFFFE8F7, 0x0000054F, 0x000023DB, 0xFFFFF0EE, 0x0000043A, 0x000023DB, 0xFFFFF0EE, 0x0000043A }, + { 0x0213EA94DE0438A4, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001AFD, 0xFFFFF781, 0x00000329, 0x00001AFD, 0xFFFFF781, 0x00000329 }, + { 0x0213EA94DE1E19A4, 0x00001BBF, 0xFFFFF8E2, 0x000002F7, 0x00001722, 0xFFFFFA85, 0x000002DB, 0x00001722, 0xFFFFFA85, 0x000002DB }, + { 0x0213EA94DE022044, 0x000030E4, 0xFFFFEBE6, 0x000004BB, 0x00001C80, 0xFFFFF6E1, 0x0000033E, 0x00001C80, 0xFFFFF6E1, 0x0000033E }, + { 0x0213EA94DE122944, 0x000030E2, 0xFFFFECD0, 0x00000492, 0x00001CE0, 0xFFFFF753, 0x0000032F, 0x00001CE0, 0xFFFFF753, 0x0000032F }, + { 0x0213EA94DE322864, 0x00002513, 0xFFFFF323, 0x000003BC, 0x00001965, 0xFFFFF93C, 0x000002F0, 0x00001965, 0xFFFFF93C, 0x000002F0 }, + { 0x0213EA94DE1610A4, 0x00002147, 0xFFFFF585, 0x0000037A, 0x000014CC, 0xFFFFFC3B, 0x00000296, 0x000014CC, 0xFFFFFC3B, 0x00000296 }, + { 0x0213EA94DE322124, 0x00002507, 0xFFFFF432, 0x0000038A, 0x00001890, 0xFFFFFA61, 0x000002C6, 0x00001890, 0xFFFFFA61, 0x000002C6 }, + { 0x0213EA94DE0638A4, 0x0000339B, 0xFFFFEA7D, 0x000004F0, 0x0000191E, 0xFFFFF944, 0x000002DF, 0x0000191E, 0xFFFFF944, 0x000002DF }, + { 0x0213F0FD42CC28A4, 0x00002842, 0xFFFFF043, 0x00000427, 0x00001988, 0xFFFFF892, 0x000002F7, 0x00001988, 0xFFFFF892, 0x000002F7 }, + { 0x0213F0FD42C618A4, 0x0000389D, 0xFFFFE5D8, 0x000005BF, 0x00001EE1, 0xFFFFF4EF, 0x00000387, 0x00001EE1, 0xFFFFF4EF, 0x00000387 }, + { 0x0213F0FD42CE3184, 0x0000396D, 0xFFFFE4D7, 0x000005F2, 0x000020DA, 0xFFFFF34E, 0x000003CD, 0x000020DA, 0xFFFFF34E, 0x000003CD }, + { 0x0213F0FD42CA3104, 0x0000355F, 0xFFFFE85A, 0x0000055F, 0x0000281F, 0xFFFFEF28, 0x0000047D, 0x0000281F, 0xFFFFEF28, 0x0000047D }, + { 0x0213EA94DE1C50E4, 0x00002284, 0xFFFFF46E, 0x00000399, 0x00001498, 0xFFFFFBE3, 0x0000029C, 0x00001498, 0xFFFFFBE3, 0x0000029C }, + { 0x0213EA94DE023944, 0x000031B6, 0xFFFFEB42, 0x000004D9, 0x00001F54, 0xFFFFF4D2, 0x00000399, 0x00001F54, 0xFFFFF4D2, 0x00000399 }, + { 0x0213F0FD42C63064, 0x000035CE, 0xFFFFE79D, 0x00000578, 0x00001C78, 0xFFFFF68C, 0x00000344, 0x00001C78, 0xFFFFF68C, 0x00000344 }, + { 0x0213EA94DE1E4964, 0x00001C0A, 0xFFFFF81B, 0x00000318, 0x00001492, 0xFFFFFBCC, 0x000002A5, 0x00001492, 0xFFFFFBCC, 0x000002A5 }, + { 0x0213EA94DE022184, 0x00003492, 0xFFFFE95C, 0x00000526, 0x00001A97, 0xFFFFF81B, 0x0000030B, 0x00001A97, 0xFFFFF81B, 0x0000030B }, + { 0x0213EA94DE163164, 0x00001E89, 0xFFFFF7D0, 0x0000031A, 0x000017A5, 0xFFFFFA99, 0x000002D9, 0x000017A5, 0xFFFFFA99, 0x000002D9 }, + { 0x0213F0FD42CA48C4, 0x00002DCC, 0xFFFFEBE0, 0x000004DE, 0x000019BA, 0xFFFFF7F5, 0x0000030D, 0x000019BA, 0xFFFFF7F5, 0x0000030D }, + { 0x0213EA94DE042984, 0x000030EF, 0xFFFFEBC1, 0x000004C0, 0x00001AA9, 0xFFFFF814, 0x0000030A, 0x00001AA9, 0xFFFFF814, 0x0000030A }, + { 0x0213EA94DE245124, 0x00002EA3, 0xFFFFEBF6, 0x000004D8, 0x00001DCF, 0xFFFFF521, 0x00000399, 0x00001DCF, 0xFFFFF521, 0x00000399 }, + { 0x0213EA94DE324164, 0x00002B5F, 0xFFFFEEA1, 0x0000046C, 0x000017EB, 0xFFFFF9C9, 0x000002D4, 0x000017EB, 0xFFFFF9C9, 0x000002D4 }, + { 0x0213EA94DE024104, 0x00002C63, 0xFFFFEE82, 0x00000455, 0x00002268, 0xFFFFF29D, 0x000003F6, 0x00002268, 0xFFFFF29D, 0x000003F6 }, + { 0x0213EA94DE121904, 0x00002B1A, 0xFFFFF016, 0x0000041C, 0x000019AA, 0xFFFFF988, 0x000002D2, 0x000019AA, 0xFFFFF988, 0x000002D2 }, + { 0x0213F0FD42CA2964, 0x0000332F, 0xFFFFE934, 0x0000053B, 0x00001E47, 0xFFFFF566, 0x00000374, 0x00001E47, 0xFFFFF566, 0x00000374 }, + { 0x0213F0FD42CA48E4, 0x00002995, 0xFFFFEEC1, 0x00000465, 0x0000178F, 0xFFFFF995, 0x000002C5, 0x0000178F, 0xFFFFF995, 0x000002C5 }, + { 0x0213EA94DE201884, 0x00001C2E, 0xFFFFF932, 0x000002E9, 0x000015C2, 0xFFFFFBC5, 0x000002AD, 0x000015C2, 0xFFFFFBC5, 0x000002AD }, + { 0x0213F0FD42C640E4, 0x00003B08, 0xFFFFE4E8, 0x000005D8, 0x0000209D, 0xFFFFF444, 0x00000398, 0x0000209D, 0xFFFFF444, 0x00000398 }, + { 0x0213EA94DE0450E4, 0x00002F1F, 0xFFFFEB74, 0x000004EB, 0x00001F4C, 0xFFFFF3D4, 0x000003CE, 0x00001F4C, 0xFFFFF3D4, 0x000003CE }, + { 0x0213EA94DE043884, 0x00003415, 0xFFFFE89F, 0x00000553, 0x0000186B, 0xFFFFF8E1, 0x000002EF, 0x0000186B, 0xFFFFF8E1, 0x000002EF }, + { 0x0213F0FD42CC10C4, 0x00003441, 0xFFFFE779, 0x0000059D, 0x000019EA, 0xFFFFF7B2, 0x0000031F, 0x000019EA, 0xFFFFF7B2, 0x0000031F }, + { 0x0213EA94DE164064, 0x00002174, 0xFFFFF546, 0x00000378, 0x00001456, 0xFFFFFC5F, 0x00000284, 0x00001456, 0xFFFFFC5F, 0x00000284 }, + { 0x0213F0FD42CE40C4, 0x00003788, 0xFFFFE61E, 0x000005BF, 0x00001DF4, 0xFFFFF562, 0x00000374, 0x00001DF4, 0xFFFFF562, 0x00000374 }, + { 0x0213EA94DE1E1844, 0x00001C41, 0xFFFFF8C1, 0x000002FC, 0x0000171E, 0xFFFFFA93, 0x000002DE, 0x0000171E, 0xFFFFFA93, 0x000002DE }, + { 0x0213F0FD42CA3864, 0x00002B15, 0xFFFFEDEC, 0x00000487, 0x000017E4, 0xFFFFF934, 0x000002DF, 0x000017E4, 0xFFFFF934, 0x000002DF }, + { 0x0213F0FD42CC3144, 0x0000327A, 0xFFFFEA71, 0x000004FF, 0x00001D96, 0xFFFFF63B, 0x00000351, 0x00001D96, 0xFFFFF63B, 0x00000351 }, + { 0x0213EA94DE1E4064, 0x000023C6, 0xFFFFF3E5, 0x000003B6, 0x000014DE, 0xFFFFFC29, 0x00000294, 0x000014DE, 0xFFFFFC29, 0x00000294 }, + { 0x0213EA94DE164944, 0x00001F96, 0xFFFFF5FA, 0x00000364, 0x00001397, 0xFFFFFC9D, 0x0000027D, 0x00001397, 0xFFFFFC9D, 0x0000027D }, + { 0x0213EA94DE063144, 0x00002B51, 0xFFFFEFB5, 0x00000420, 0x00001ACA, 0xFFFFF824, 0x0000030D, 0x00001ACA, 0xFFFFF824, 0x0000030D }, + { 0x0213EA94DE1E4944, 0x000020DB, 0xFFFFF55B, 0x0000037C, 0x0000153D, 0xFFFFFB5F, 0x000002BA, 0x0000153D, 0xFFFFFB5F, 0x000002BA }, + { 0x0213EA94DE0221A4, 0x000030BB, 0xFFFFEBDA, 0x000004BC, 0x00001B0E, 0xFFFFF7A8, 0x0000031E, 0x00001B0E, 0xFFFFF7A8, 0x0000031E }, + { 0x0213F0FD42C62904, 0x000033C4, 0xFFFFEA41, 0x000004FA, 0x000022C6, 0xFFFFF363, 0x000003BC, 0x000022C6, 0xFFFFF363, 0x000003BC }, + { 0x0213EA94DE240924, 0x00002D47, 0xFFFFEE01, 0x00000477, 0x000021CD, 0xFFFFF36E, 0x000003D6, 0x000021CD, 0xFFFFF36E, 0x000003D6 }, + { 0x0213EA94DE1E31A4, 0x00001E7B, 0xFFFFF733, 0x00000339, 0x00001668, 0xFFFFFB29, 0x000002BF, 0x00001668, 0xFFFFFB29, 0x000002BF }, + { 0x0213F0FD42CA2984, 0x00002F7E, 0xFFFFEAFF, 0x000004FC, 0x000018D4, 0xFFFFF8BE, 0x000002E8, 0x000018D4, 0xFFFFF8BE, 0x000002E8 }, + { 0x0213EA94DE3238A4, 0x00002635, 0xFFFFF2E1, 0x000003BC, 0x000017A4, 0xFFFFFA67, 0x000002C3, 0x000017A4, 0xFFFFFA67, 0x000002C3 }, + { 0x0213EA94DE1230A4, 0x000026CA, 0xFFFFF2C1, 0x000003B2, 0x00001C3E, 0xFFFFF7AE, 0x0000031F, 0x00001C3E, 0xFFFFF7AE, 0x0000031F }, + { 0x0213EA94DE1C1064, 0x00002550, 0xFFFFF380, 0x000003B5, 0x000019F5, 0xFFFFF8E7, 0x00000313, 0x000019F5, 0xFFFFF8E7, 0x00000313 }, + { 0x0213F0FD42CA4904, 0x00002FBC, 0xFFFFEAF8, 0x000004FA, 0x000018CC, 0xFFFFF8C6, 0x000002E8, 0x000018CC, 0xFFFFF8C6, 0x000002E8 }, + { 0x0213F0FD42D018E4, 0x00002FCC, 0xFFFFEB60, 0x000004EA, 0x00001EFF, 0xFFFFF4DA, 0x0000038F, 0x00001EFF, 0xFFFFF4DA, 0x0000038F }, + { 0x0213EA94DE164084, 0x000023E6, 0xFFFFF413, 0x000003A1, 0x00001544, 0xFFFFFC16, 0x0000028B, 0x00001544, 0xFFFFFC16, 0x0000028B }, + { 0x0213F0FD42CE3024, 0x00003251, 0xFFFFEAA2, 0x000004F5, 0x000025B0, 0xFFFFF0DF, 0x00000431, 0x000025B0, 0xFFFFF0DF, 0x00000431 }, + { 0x0213F0FD42D03984, 0x00002F6F, 0xFFFFEB67, 0x000004E6, 0x00002275, 0xFFFFF249, 0x000003FB, 0x00002275, 0xFFFFF249, 0x000003FB }, + { 0x0213EA94DE322964, 0x00002597, 0xFFFFF34A, 0x000003B1, 0x00001BCC, 0xFFFFF822, 0x0000031A, 0x00001BCC, 0xFFFFF822, 0x0000031A }, + { 0x0213F0FD42C63864, 0x00003B1D, 0xFFFFE40E, 0x0000060D, 0x00001F61, 0xFFFFF470, 0x0000039F, 0x00001F61, 0xFFFFF470, 0x0000039F }, + { 0x0213F0FD42C64144, 0x0000379F, 0xFFFFE6DB, 0x0000058C, 0x00002460, 0xFFFFF170, 0x00000415, 0x00002460, 0xFFFFF170, 0x00000415 }, + { 0x0213EA94DE165144, 0x00002442, 0xFFFFF2FB, 0x000003D9, 0x00001414, 0xFFFFFBDC, 0x000002A2, 0x00001414, 0xFFFFFBDC, 0x000002A2 }, + { 0x0213EA94DE0240C4, 0x00003270, 0xFFFFEA0D, 0x0000051C, 0x00001AFD, 0xFFFFF783, 0x00000328, 0x00001AFD, 0xFFFFF783, 0x00000328 }, + { 0x0213EA94DE161104, 0x00001B23, 0xFFFFF94B, 0x000002EB, 0x000015F1, 0xFFFFFB82, 0x000002B4, 0x000015F1, 0xFFFFFB82, 0x000002B4 }, + { 0x0213EA94DE323844, 0x000026AE, 0xFFFFF21A, 0x000003DB, 0x00001827, 0xFFFFFA10, 0x000002C8, 0x00001827, 0xFFFFFA10, 0x000002C8 }, + { 0x0213F0FD42CA4884, 0x00002DCF, 0xFFFFEBD8, 0x000004DB, 0x00001A75, 0xFFFFF719, 0x0000033A, 0x00001A75, 0xFFFFF719, 0x0000033A }, + { 0x0213F0FD42CE40E4, 0x00003983, 0xFFFFE500, 0x000005EA, 0x000022A6, 0xFFFFF25F, 0x000003F1, 0x000022A6, 0xFFFFF25F, 0x000003F1 }, + { 0x0213EA94DE1218C4, 0x00002AD5, 0xFFFFF07A, 0x00000406, 0x000019FB, 0xFFFFF961, 0x000002D8, 0x000019FB, 0xFFFFF961, 0x000002D8 }, + { 0x0213F0FD42CA39A4, 0x00002A43, 0xFFFFEE43, 0x00000474, 0x00001D65, 0xFFFFF538, 0x00000387, 0x00001D65, 0xFFFFF538, 0x00000387 }, + { 0x0213F0FD42C62084, 0x0000311E, 0xFFFFEAF8, 0x000004E8, 0x00001959, 0xFFFFF8E4, 0x000002DC, 0x00001959, 0xFFFFF8E4, 0x000002DC }, + { 0x0213F0FD42D031A4, 0x0000339A, 0xFFFFE8A7, 0x00000559, 0x00001A04, 0xFFFFF7E5, 0x00000311, 0x00001A04, 0xFFFFF7E5, 0x00000311 }, + { 0x0213EA94DE204144, 0x000021B3, 0xFFFFF50F, 0x00000389, 0x00001470, 0xFFFFFBF7, 0x000002A5, 0x00001470, 0xFFFFFBF7, 0x000002A5 }, + { 0x0213EA94DE021884, 0x00003417, 0xFFFFE9A6, 0x0000051D, 0x000018A4, 0xFFFFF984, 0x000002CF, 0x000018A4, 0xFFFFF984, 0x000002CF }, + { 0x0213EA94DE202984, 0x00001FED, 0xFFFFF6A2, 0x00000347, 0x00001639, 0xFFFFFB59, 0x000002BB, 0x00001639, 0xFFFFFB59, 0x000002BB }, + { 0x0213EA94DE1218A4, 0x000032D2, 0xFFFFEB18, 0x000004DC, 0x00001A01, 0xFFFFF95E, 0x000002CF, 0x00001A01, 0xFFFFF95E, 0x000002CF }, + { 0x0213F0FD42D04084, 0x00003147, 0xFFFFEA3B, 0x00000518, 0x0000241D, 0xFFFFF11C, 0x00000431, 0x0000241D, 0xFFFFF11C, 0x00000431 }, + { 0x0213EA94DE1C0904, 0x00001D44, 0xFFFFF7E7, 0x0000031A, 0x0000153F, 0xFFFFFBBC, 0x000002A9, 0x0000153F, 0xFFFFFBBC, 0x000002A9 }, + { 0x0213F0FD42CC4104, 0x00003690, 0xFFFFE6E3, 0x000005A4, 0x000018DE, 0xFFFFF908, 0x000002DD, 0x000018DE, 0xFFFFF908, 0x000002DD }, + { 0x0213F0FD42CC2184, 0x00003561, 0xFFFFE6F8, 0x000005AB, 0x000018B5, 0xFFFFF8A0, 0x000002F3, 0x000018B5, 0xFFFFF8A0, 0x000002F3 }, + { 0x0213EA94DE323124, 0x000028F4, 0xFFFFF23A, 0x000003CE, 0x00001BC6, 0xFFFFF881, 0x00000311, 0x00001BC6, 0xFFFFF881, 0x00000311 }, + { 0x0213F0FD42D03184, 0x000035D7, 0xFFFFE71C, 0x0000059B, 0x00001D49, 0xFFFFF5C8, 0x00000368, 0x00001D49, 0xFFFFF5C8, 0x00000368 }, + { 0x0213F0FD42CE18A4, 0x0000397E, 0xFFFFE4CB, 0x000005F4, 0x00001989, 0xFFFFF844, 0x000002FD, 0x00001989, 0xFFFFF844, 0x000002FD }, + { 0x0213F0FD42C62064, 0x00003BAB, 0xFFFFE332, 0x0000063F, 0x00001A69, 0xFFFFF7B9, 0x00000312, 0x00001A69, 0xFFFFF7B9, 0x00000312 }, + { 0x0213F0FD42D03064, 0x00002F26, 0xFFFFEB82, 0x000004E8, 0x00001D7D, 0xFFFFF590, 0x00000379, 0x00001D7D, 0xFFFFF590, 0x00000379 }, + { 0x0213EA94DE0631A4, 0x00002FDC, 0xFFFFEBE0, 0x000004C3, 0x00001940, 0xFFFFF8CC, 0x000002EE, 0x00001940, 0xFFFFF8CC, 0x000002EE }, + { 0x0213EA94DE1C08E4, 0x000021B2, 0xFFFFF558, 0x00000379, 0x00001643, 0xFFFFFB1C, 0x000002C3, 0x00001643, 0xFFFFFB1C, 0x000002C3 }, + { 0x0213EA94DE321904, 0x00002897, 0xFFFFF181, 0x000003F7, 0x00001990, 0xFFFFF994, 0x000002E2, 0x00001990, 0xFFFFF994, 0x000002E2 }, + { 0x0213EA94DE1E0924, 0x00001D19, 0xFFFFF829, 0x0000031A, 0x00001558, 0xFFFFFBCA, 0x000002AF, 0x00001558, 0xFFFFFBCA, 0x000002AF }, + { 0x0213EA94DE043144, 0x00003311, 0xFFFFEAD9, 0x000004E1, 0x00001BDC, 0xFFFFF79E, 0x0000031D, 0x00001BDC, 0xFFFFF79E, 0x0000031D }, + { 0x0213EA94DE1E29C4, 0x00001E54, 0xFFFFF740, 0x00000333, 0x000016A1, 0xFFFFFAF0, 0x000002C4, 0x000016A1, 0xFFFFFAF0, 0x000002C4 }, + { 0x0213F0FD42CE3964, 0x00003266, 0xFFFFE9A8, 0x00000527, 0x00002307, 0xFFFFF219, 0x000003FC, 0x00002307, 0xFFFFF219, 0x000003FC }, + { 0x0213EA94DE321144, 0x00001D1F, 0xFFFFF82B, 0x000002F0, 0x000013F0, 0xFFFFFD0B, 0x0000024E, 0x000013F0, 0xFFFFFD0B, 0x0000024E }, + { 0x0213F0FD42C648A4, 0x0000312E, 0xFFFFEA67, 0x00000502, 0x0000222A, 0xFFFFF253, 0x000003F9, 0x0000222A, 0xFFFFF253, 0x000003F9 }, + { 0x0213F0FD42CA4124, 0x000032B2, 0xFFFFE9AD, 0x00000523, 0x00001E97, 0xFFFFF527, 0x0000037F, 0x00001E97, 0xFFFFF527, 0x0000037F }, + { 0x0213EA94DE1640E4, 0x00001F6A, 0xFFFFF6FC, 0x00000338, 0x0000164B, 0xFFFFFB2C, 0x000002C2, 0x0000164B, 0xFFFFFB2C, 0x000002C2 }, + { 0x0213EA94DE0228C4, 0x00002603, 0xFFFFF386, 0x00000392, 0x00001EE0, 0xFFFFF601, 0x00000369, 0x00001EE0, 0xFFFFF601, 0x00000369 }, + { 0x0213EA94DE201164, 0x00001D0C, 0xFFFFF803, 0x00000317, 0x00001345, 0xFFFFFD52, 0x00000260, 0x00001345, 0xFFFFFD52, 0x00000260 }, + { 0x0213F0FD42CC1884, 0x0000327A, 0xFFFFE8E5, 0x0000055C, 0x00001680, 0xFFFFFA2D, 0x000002B2, 0x00001680, 0xFFFFFA2D, 0x000002B2 }, + { 0x0213F0FD42CA3964, 0x000032B8, 0xFFFFE91A, 0x0000054A, 0x00001BAB, 0xFFFFF6EC, 0x00000338, 0x00001BAB, 0xFFFFF6EC, 0x00000338 }, + { 0x0213F0FD42CC3044, 0x00002F79, 0xFFFFEB63, 0x000004EF, 0x000017BB, 0xFFFFF9B1, 0x000002CA, 0x000017BB, 0xFFFFF9B1, 0x000002CA }, + { 0x0213EA94DE0438E4, 0x00002AE5, 0xFFFFEFCB, 0x0000041D, 0x0000214A, 0xFFFFF3A7, 0x000003C7, 0x0000214A, 0xFFFFF3A7, 0x000003C7 }, + { 0x0213EA94DE322064, 0x0000212C, 0xFFFFF5BC, 0x0000034F, 0x000017ED, 0xFFFFFA4C, 0x000002C1, 0x000017ED, 0xFFFFFA4C, 0x000002C1 }, + { 0x0213EA94DE121124, 0x00002BE7, 0xFFFFEF40, 0x0000043C, 0x00001AE2, 0xFFFFF8CF, 0x000002E3, 0x00001AE2, 0xFFFFF8CF, 0x000002E3 }, + { 0x0213F0FD42D05144, 0x000032DC, 0xFFFFE90F, 0x00000549, 0x00002A2D, 0xFFFFECC9, 0x000004ED, 0x00002A2D, 0xFFFFECC9, 0x000004ED }, + { 0x0213EA94DE1618A4, 0x00001DE3, 0xFFFFF80D, 0x00000319, 0x000016FA, 0xFFFFFB42, 0x000002BC, 0x000016FA, 0xFFFFFB42, 0x000002BC }, + { 0x0213EA94DE1E2844, 0x00001F1B, 0xFFFFF6DE, 0x00000346, 0x00001502, 0xFFFFFC23, 0x00000298, 0x00001502, 0xFFFFFC23, 0x00000298 }, + { 0x0213EA94DE061864, 0x00003203, 0xFFFFEA87, 0x000004FE, 0x0000194E, 0xFFFFF8E3, 0x000002EC, 0x0000194E, 0xFFFFF8E3, 0x000002EC }, + { 0x0213F0FD42D02144, 0x0000337A, 0xFFFFE8DD, 0x00000551, 0x00001E3C, 0xFFFFF534, 0x00000385, 0x00001E3C, 0xFFFFF534, 0x00000385 }, + { 0x0213F0FD42CA4864, 0x000036F6, 0xFFFFE62A, 0x000005C5, 0x000023C0, 0xFFFFF117, 0x00000435, 0x000023C0, 0xFFFFF117, 0x00000435 }, + { 0x0213F0FD42CC2144, 0x00003125, 0xFFFFEA4E, 0x0000051A, 0x00001E6C, 0xFFFFF503, 0x0000038E, 0x00001E6C, 0xFFFFF503, 0x0000038E }, + { 0x0213EA94DE1C08A4, 0x00001CD4, 0xFFFFF82D, 0x0000030E, 0x0000156D, 0xFFFFFB64, 0x000002B8, 0x0000156D, 0xFFFFFB64, 0x000002B8 }, + { 0x0213EA94DE0240A4, 0x00002F14, 0xFFFFEC46, 0x000004B8, 0x000017F1, 0xFFFFF977, 0x000002D2, 0x000017F1, 0xFFFFF977, 0x000002D2 }, + { 0x0213EA94DE0640A4, 0x000031F1, 0xFFFFEAD4, 0x000004ED, 0x0000184C, 0xFFFFF983, 0x000002D4, 0x0000184C, 0xFFFFF983, 0x000002D4 }, + { 0x0213F0FD42D04984, 0x00002EA9, 0xFFFFEBD7, 0x000004D5, 0x0000288D, 0xFFFFEDDB, 0x000004C0, 0x0000288D, 0xFFFFEDDB, 0x000004C0 }, + { 0x0213F0FD42CA3984, 0x0000335F, 0xFFFFE82C, 0x00000579, 0x00001DBF, 0xFFFFF512, 0x0000038C, 0x00001DBF, 0xFFFFF512, 0x0000038C }, + { 0x0213EA94DE201184, 0x0000224F, 0xFFFFF4B5, 0x00000391, 0x0000138C, 0xFFFFFCC3, 0x0000027A, 0x0000138C, 0xFFFFFCC3, 0x0000027A }, + { 0x0213EA94DE1240A4, 0x0000320D, 0xFFFFEACD, 0x000004F5, 0x00001976, 0xFFFFF913, 0x000002E2, 0x00001976, 0xFFFFF913, 0x000002E2 }, + { 0x0213EA94DE202104, 0x00001BEB, 0xFFFFF99C, 0x000002E4, 0x000016A4, 0xFFFFFB77, 0x000002C3, 0x000016A4, 0xFFFFFB77, 0x000002C3 }, + { 0x0213EA94DE063044, 0x0000396E, 0xFFFFE616, 0x000005A9, 0x000018F4, 0xFFFFF91A, 0x000002E3, 0x000018F4, 0xFFFFF91A, 0x000002E3 }, + { 0x0213EA94DE022864, 0x00003251, 0xFFFFEA8E, 0x000004FA, 0x000018EF, 0xFFFFF910, 0x000002E4, 0x000018EF, 0xFFFFF910, 0x000002E4 }, + { 0x0213EA94DE1C1924, 0x00001DAF, 0xFFFFF857, 0x0000030D, 0x00001915, 0xFFFFF9D8, 0x000002F7, 0x00001915, 0xFFFFF9D8, 0x000002F7 }, + { 0x0213EA94DE2041A4, 0x000025B6, 0xFFFFF26B, 0x000003E5, 0x00001531, 0xFFFFFB68, 0x000002AF, 0x00001531, 0xFFFFFB68, 0x000002AF }, + { 0x0213EA94DE061884, 0x00002B2E, 0xFFFFEF2E, 0x00000440, 0x00001968, 0xFFFFF91A, 0x000002DF, 0x00001968, 0xFFFFF91A, 0x000002DF }, + { 0x0213EA94DE1C2064, 0x00002305, 0xFFFFF528, 0x00000377, 0x000018A4, 0xFFFFF9EB, 0x000002F0, 0x000018A4, 0xFFFFF9EB, 0x000002F0 }, + { 0x0213F0FD42CA40C4, 0x000032A1, 0xFFFFE992, 0x0000052E, 0x00001A55, 0xFFFFF826, 0x000002FE, 0x00001A55, 0xFFFFF826, 0x000002FE }, + { 0x0213EA94DE042184, 0x00002CCD, 0xFFFFEE35, 0x00000462, 0x00001B09, 0xFFFFF7E6, 0x0000030F, 0x00001B09, 0xFFFFF7E6, 0x0000030F }, + { 0x0213EA94DE323084, 0x00002602, 0xFFFFF2CF, 0x000003C5, 0x000016EE, 0xFFFFFAD4, 0x000002B4, 0x000016EE, 0xFFFFFAD4, 0x000002B4 }, + { 0x0213F0FD42D01964, 0x00003370, 0xFFFFE891, 0x00000560, 0x000017F0, 0xFFFFF930, 0x000002DF, 0x000017F0, 0xFFFFF930, 0x000002DF }, + { 0x0213F0FD42CA1884, 0x00002EDC, 0xFFFFEB6D, 0x000004EC, 0x000016E6, 0xFFFFF9ED, 0x000002BC, 0x000016E6, 0xFFFFF9ED, 0x000002BC }, + { 0x0213EA94DE1228C4, 0x00002A05, 0xFFFFF13D, 0x000003F0, 0x00002065, 0xFFFFF57B, 0x00000378, 0x00002065, 0xFFFFF57B, 0x00000378 }, + { 0x0213F0FD42CE2044, 0x00002F8A, 0xFFFFEB6E, 0x000004E4, 0x00001E3E, 0xFFFFF50E, 0x0000038D, 0x00001E3E, 0xFFFFF50E, 0x0000038D }, + { 0x0213F0FD42CA3044, 0x00002BB5, 0xFFFFED6A, 0x000004A1, 0x000017BF, 0xFFFFF937, 0x000002E5, 0x000017BF, 0xFFFFF937, 0x000002E5 }, + { 0x0213EA94DE201964, 0x0000202C, 0xFFFFF6CE, 0x0000033F, 0x000015EE, 0xFFFFFB83, 0x000002B9, 0x000015EE, 0xFFFFFB83, 0x000002B9 }, + { 0x0213EA94DE022884, 0x00002C0C, 0xFFFFEF10, 0x0000043F, 0x00001A73, 0xFFFFF83E, 0x0000030C, 0x00001A73, 0xFFFFF83E, 0x0000030C }, + { 0x0213EA94DE324104, 0x0000234F, 0xFFFFF460, 0x00000385, 0x000018C3, 0xFFFFF9A5, 0x000002DD, 0x000018C3, 0xFFFFF9A5, 0x000002DD }, + { 0x0213F0FD42CE1904, 0x00003679, 0xFFFFE704, 0x00000595, 0x00002177, 0xFFFFF31A, 0x000003D7, 0x00002177, 0xFFFFF31A, 0x000003D7 }, + { 0x0213F0FD42CA2924, 0x00003008, 0xFFFFEBB8, 0x000004D5, 0x000024FF, 0xFFFFF112, 0x00000430, 0x000024FF, 0xFFFFF112, 0x00000430 }, + { 0x0213F0FD42C641A4, 0x00003848, 0xFFFFE6A3, 0x00000594, 0x00002958, 0xFFFFEE37, 0x000004A0, 0x00002958, 0xFFFFEE37, 0x000004A0 }, + { 0x0213F0FD42CC1924, 0x00002FDF, 0xFFFFEB08, 0x000004FD, 0x00001D77, 0xFFFFF58B, 0x0000037A, 0x00001D77, 0xFFFFF58B, 0x0000037A }, + { 0x0213EA94DE063064, 0x00002EC8, 0xFFFFED41, 0x00000481, 0x00001949, 0xFFFFF91C, 0x000002DF, 0x00001949, 0xFFFFF91C, 0x000002DF }, + { 0x0213F0FD42D041A4, 0x000037C1, 0xFFFFE5BA, 0x000005D7, 0x0000252C, 0xFFFFF023, 0x00000460, 0x0000252C, 0xFFFFF023, 0x00000460 }, + { 0x0213F0FD42CE2944, 0x00003716, 0xFFFFE70C, 0x0000058A, 0x000028CC, 0xFFFFEE57, 0x0000049D, 0x000028CC, 0xFFFFEE57, 0x0000049D }, + { 0x0213F0FD42CA40E4, 0x000033D1, 0xFFFFE8E8, 0x00000547, 0x00001AB1, 0xFFFFF7E5, 0x00000309, 0x00001AB1, 0xFFFFF7E5, 0x00000309 }, + { 0x0213F0FD42CC2944, 0x00002D72, 0xFFFFED65, 0x0000048E, 0x00001E0D, 0xFFFFF5A7, 0x00000370, 0x00001E0D, 0xFFFFF5A7, 0x00000370 }, + { 0x0213EA94DE1C39A4, 0x00002292, 0xFFFFF49F, 0x00000393, 0x000017F4, 0xFFFFF9CD, 0x000002F5, 0x000017F4, 0xFFFFF9CD, 0x000002F5 }, + { 0x0213EA94DE243044, 0x000026EE, 0xFFFFF18C, 0x000003F7, 0x000018A7, 0xFFFFF95A, 0x000002E5, 0x000018A7, 0xFFFFF95A, 0x000002E5 }, + { 0x0213EA94DE042164, 0x00002F62, 0xFFFFEC9B, 0x000004A4, 0x0000194E, 0xFFFFF932, 0x000002D9, 0x0000194E, 0xFFFFF932, 0x000002D9 }, + { 0x0213EA94DE1E3984, 0x00001CE8, 0xFFFFF7FA, 0x0000031C, 0x000014CE, 0xFFFFFBD4, 0x000002AB, 0x000014CE, 0xFFFFFBD4, 0x000002AB }, + { 0x0213EA94DE1210E4, 0x00002E5A, 0xFFFFEDAB, 0x0000047C, 0x00001A82, 0xFFFFF8F7, 0x000002DE, 0x00001A82, 0xFFFFF8F7, 0x000002DE }, + { 0x0213F0FD42CC30E4, 0x00003057, 0xFFFFEC34, 0x000004B9, 0x00002296, 0xFFFFF342, 0x000003D0, 0x00002296, 0xFFFFF342, 0x000003D0 }, + { 0x0213EA94DE0418A4, 0x00002B0F, 0xFFFFEF58, 0x00000434, 0x00001BFD, 0xFFFFF721, 0x00000330, 0x00001BFD, 0xFFFFF721, 0x00000330 }, + { 0x0213EA94DE2010A4, 0x00001F01, 0xFFFFF751, 0x0000032F, 0x00001502, 0xFFFFFC3E, 0x00000296, 0x00001502, 0xFFFFFC3E, 0x00000296 }, + { 0x0213F0FD42CA3064, 0x00002FF4, 0xFFFFEAE2, 0x00000503, 0x00001B36, 0xFFFFF736, 0x00000330, 0x00001B36, 0xFFFFF736, 0x00000330 }, + { 0x0213F0FD42CE2064, 0x00003762, 0xFFFFE5AB, 0x000005DE, 0x000018CB, 0xFFFFF896, 0x000002F4, 0x000018CB, 0xFFFFF896, 0x000002F4 }, + { 0x0213F0FD42CC2064, 0x00002890, 0xFFFFEF92, 0x00000445, 0x0000191D, 0xFFFFF86F, 0x00000302, 0x0000191D, 0xFFFFF86F, 0x00000302 }, + { 0x0213EA94DE043064, 0x00002F76, 0xFFFFEC0E, 0x000004BF, 0x00001F7D, 0xFFFFF41A, 0x000003C0, 0x00001F7D, 0xFFFFF41A, 0x000003C0 }, + { 0x0213EA94DE1E08A4, 0x00001D55, 0xFFFFF7F8, 0x0000031E, 0x000015DF, 0xFFFFFB79, 0x000002B7, 0x000015DF, 0xFFFFFB79, 0x000002B7 }, + { 0x0213EA94DE204924, 0x00001FE9, 0xFFFFF64A, 0x00000353, 0x000019E8, 0xFFFFF882, 0x0000032A, 0x000019E8, 0xFFFFF882, 0x0000032A }, + { 0x0213EA94DE063964, 0x000030B5, 0xFFFFEBB8, 0x000004C4, 0x00001857, 0xFFFFF968, 0x000002D8, 0x00001857, 0xFFFFF968, 0x000002D8 }, + { 0x0213F0FD42CA28C4, 0x00003398, 0xFFFFE9A3, 0x00000524, 0x00001FF9, 0xFFFFF458, 0x000003AD, 0x00001FF9, 0xFFFFF458, 0x000003AD }, + { 0x0213F0FD42CE2964, 0x00003897, 0xFFFFE5BD, 0x000005C8, 0x00002519, 0xFFFFF0BA, 0x00000438, 0x00002519, 0xFFFFF0BA, 0x00000438 }, + { 0x0213F0FD42D04064, 0x00003234, 0xFFFFE9B1, 0x00000530, 0x000022CC, 0xFFFFF20E, 0x00000409, 0x000022CC, 0xFFFFF20E, 0x00000409 }, + { 0x0213EA94DE205104, 0x00001FD2, 0xFFFFF641, 0x00000354, 0x000017C9, 0xFFFFF9C0, 0x000002FB, 0x000017C9, 0xFFFFF9C0, 0x000002FB }, + { 0x0213F0FD42CE48E4, 0x00003234, 0xFFFFE946, 0x0000053D, 0x00002267, 0xFFFFF1F5, 0x0000040D, 0x00002267, 0xFFFFF1F5, 0x0000040D }, + { 0x0213EA94DE2029A4, 0x00002330, 0xFFFFF474, 0x00000399, 0x00001490, 0xFFFFFC67, 0x00000288, 0x00001490, 0xFFFFFC67, 0x00000288 }, + { 0x0213F0FD42D03924, 0x000032A3, 0xFFFFE9EB, 0x0000051B, 0x0000234D, 0xFFFFF23C, 0x000003F7, 0x0000234D, 0xFFFFF23C, 0x000003F7 }, + { 0x0213EA94DE200904, 0x0000217E, 0xFFFFF53A, 0x00000384, 0x00001511, 0xFFFFFBF5, 0x0000029E, 0x00001511, 0xFFFFFBF5, 0x0000029E }, + { 0x0213F0FD42CE50E4, 0x0000384F, 0xFFFFE562, 0x000005E2, 0x0000295A, 0xFFFFED53, 0x000004D3, 0x0000295A, 0xFFFFED53, 0x000004D3 }, + { 0x0213F0FD42D05124, 0x00003315, 0xFFFFE8D1, 0x00000552, 0x000025D1, 0xFFFFEFAF, 0x00000471, 0x000025D1, 0xFFFFEFAF, 0x00000471 }, + { 0x0213F0FD42C64924, 0x00004183, 0xFFFFDF61, 0x000006DA, 0x0000193C, 0xFFFFF88F, 0x000002EC, 0x0000193C, 0xFFFFF88F, 0x000002EC }, + { 0x0213EA94DE242164, 0x00002DFC, 0xFFFFEDF2, 0x0000047A, 0x00001755, 0xFFFFFAC2, 0x000002AC, 0x00001755, 0xFFFFFAC2, 0x000002AC }, + { 0x0213F0FD42CA31A4, 0x000033FE, 0xFFFFE774, 0x0000059F, 0x00001E70, 0xFFFFF492, 0x000003A0, 0x00001E70, 0xFFFFF492, 0x000003A0 }, + { 0x0213F0FD42C629A4, 0x000040D7, 0xFFFFDFB8, 0x000006CE, 0x00001AC8, 0xFFFFF773, 0x0000031D, 0x00001AC8, 0xFFFFF773, 0x0000031D }, + { 0x0213EA94DE1E1164, 0x00001D02, 0xFFFFF803, 0x00000322, 0x000015FE, 0xFFFFFB71, 0x000002BB, 0x000015FE, 0xFFFFFB71, 0x000002BB }, + { 0x0213F0FD42D02884, 0x00002EB0, 0xFFFFEC31, 0x000004C4, 0x00001B3C, 0xFFFFF73B, 0x00000330, 0x00001B3C, 0xFFFFF73B, 0x00000330 }, + { 0x0213F0FD42CA4984, 0x00002D9F, 0xFFFFECBF, 0x000004A8, 0x000022B0, 0xFFFFF23C, 0x000003F9, 0x000022B0, 0xFFFFF23C, 0x000003F9 }, + { 0x0213F0FD42CC18E4, 0x00002C6A, 0xFFFFEDAC, 0x00000488, 0x00002419, 0xFFFFF159, 0x00000427, 0x00002419, 0xFFFFF159, 0x00000427 }, + { 0x0213EA94DE1210A4, 0x00002991, 0xFFFFF06C, 0x0000040E, 0x00001AA9, 0xFFFFF8D0, 0x000002E1, 0x00001AA9, 0xFFFFF8D0, 0x000002E1 }, + { 0x0213EA94DE123904, 0x00002F8E, 0xFFFFED1B, 0x00000493, 0x00001DE4, 0xFFFFF69C, 0x00000347, 0x00001DE4, 0xFFFFF69C, 0x00000347 }, + { 0x0213EA94DE204184, 0x00002136, 0xFFFFF540, 0x0000037C, 0x000014FF, 0xFFFFFB83, 0x000002B2, 0x000014FF, 0xFFFFFB83, 0x000002B2 }, + { 0x0213EA94DE0618E4, 0x0000354C, 0xFFFFE97D, 0x0000051A, 0x00001906, 0xFFFFF965, 0x000002DD, 0x00001906, 0xFFFFF965, 0x000002DD }, + { 0x0213F0FD42C620C4, 0x0000348B, 0xFFFFE94D, 0x0000051F, 0x0000285B, 0xFFFFEF1A, 0x00000473, 0x0000285B, 0xFFFFEF1A, 0x00000473 }, + { 0x0213EA94DE3218A4, 0x000026E6, 0xFFFFF24E, 0x000003D6, 0x0000141F, 0xFFFFFCCE, 0x00000260, 0x0000141F, 0xFFFFFCCE, 0x00000260 }, + { 0x0213F0FD42C64164, 0x00003CED, 0xFFFFE2A5, 0x0000064E, 0x00002060, 0xFFFFF3E0, 0x000003B0, 0x00002060, 0xFFFFF3E0, 0x000003B0 }, + { 0x0213EA94DE021084, 0x000029D4, 0xFFFFEFF7, 0x00000426, 0x00001976, 0xFFFFF8E1, 0x000002EE, 0x00001976, 0xFFFFF8E1, 0x000002EE }, + { 0x0213F0FD42CA40A4, 0x00003767, 0xFFFFE601, 0x000005CC, 0x00001D22, 0xFFFFF5F4, 0x00000361, 0x00001D22, 0xFFFFF5F4, 0x00000361 }, + { 0x0213F0FD42C650C4, 0x00003CE8, 0xFFFFE2E8, 0x00000637, 0x0000232C, 0xFFFFF1E7, 0x00000405, 0x0000232C, 0xFFFFF1E7, 0x00000405 }, + { 0x0213EA94DE201064, 0x000023A8, 0xFFFFF4CD, 0x00000386, 0x00001944, 0xFFFFF983, 0x00000300, 0x00001944, 0xFFFFF983, 0x00000300 }, + { 0x0213F0FD42CC30A4, 0x00003451, 0xFFFFE8B9, 0x00000551, 0x00001AD7, 0xFFFFF7BF, 0x00000318, 0x00001AD7, 0xFFFFF7BF, 0x00000318 }, + { 0x0213F0FD42CE2984, 0x0000381B, 0xFFFFE5A0, 0x000005D0, 0x00001E0F, 0xFFFFF521, 0x00000382, 0x00001E0F, 0xFFFFF521, 0x00000382 }, + { 0x0213EA94DE2038C4, 0x000023A4, 0xFFFFF4A6, 0x00000394, 0x0000171F, 0xFFFFFABB, 0x000002D9, 0x0000171F, 0xFFFFFABB, 0x000002D9 }, + { 0x0213F0FD42C620A4, 0x00003C2B, 0xFFFFE447, 0x000005F0, 0x0000207F, 0xFFFFF44E, 0x0000039A, 0x0000207F, 0xFFFFF44E, 0x0000039A }, + { 0x0213F0FD42CC3984, 0x00002F07, 0xFFFFEB70, 0x000004E9, 0x00001765, 0xFFFFF9A5, 0x000002C6, 0x00001765, 0xFFFFF9A5, 0x000002C6 }, + { 0x0213F0FD42C62984, 0x00003A01, 0xFFFFE4E0, 0x000005E7, 0x0000227A, 0xFFFFF292, 0x000003E5, 0x0000227A, 0xFFFFF292, 0x000003E5 }, + { 0x0213F0FD42CE20A4, 0x0000376E, 0xFFFFE686, 0x000005A6, 0x00001FCF, 0xFFFFF43B, 0x000003A8, 0x00001FCF, 0xFFFFF43B, 0x000003A8 }, + { 0x0213F0FFEF5A4984, 0x0000485F, 0xFFFFDCC1, 0x00000713, 0x00002CF8, 0xFFFFEC45, 0x000004DA, 0x00002CF8, 0xFFFFEC45, 0x000004DA }, + { 0x0213F0FFEF5C3184, 0x0000331C, 0xFFFFE8FF, 0x00000541, 0x00002366, 0xFFFFF19D, 0x00000411, 0x00002366, 0xFFFFF19D, 0x00000411 }, + { 0x0213F0FFEF643864, 0x00003CF3, 0xFFFFE15A, 0x00000694, 0x00002FB3, 0xFFFFE827, 0x000005B9, 0x00002FB3, 0xFFFFE827, 0x000005B9 }, + { 0x0213EA94DE321104, 0x000023F3, 0xFFFFF3EA, 0x0000039A, 0x00001345, 0xFFFFFD6B, 0x00000241, 0x00001345, 0xFFFFFD6B, 0x00000241 }, + { 0x0213F0FFEF5C28A4, 0x000038C0, 0xFFFFE58A, 0x000005CC, 0x000023CA, 0xFFFFF1AA, 0x00000408, 0x000023CA, 0xFFFFF1AA, 0x00000408 }, + { 0x0213F0FFEF662944, 0x00004976, 0xFFFFDD6A, 0x000006D7, 0x000033C6, 0xFFFFE8EB, 0x0000054D, 0x000033C6, 0xFFFFE8EB, 0x0000054D }, + { 0x0213F0FFEF644904, 0x00004049, 0xFFFFDF6D, 0x000006D8, 0x00003129, 0xFFFFE716, 0x000005E9, 0x00003129, 0xFFFFE716, 0x000005E9 }, + { 0x0213F0FFEF661164, 0x000046C2, 0xFFFFDCEB, 0x0000071C, 0x00002E6D, 0xFFFFEA8F, 0x0000052E, 0x00002E6D, 0xFFFFEA8F, 0x0000052E }, + { 0x0213F0FFEF6238A4, 0x00004080, 0xFFFFE1E1, 0x0000063A, 0x0000396D, 0xFFFFE40A, 0x0000062C, 0x0000396D, 0xFFFFE40A, 0x0000062C }, + { 0x0213F0FFEF5E2124, 0x00003DE0, 0xFFFFE358, 0x0000060C, 0x00002AA2, 0xFFFFEDBF, 0x000004A0, 0x00002AA2, 0xFFFFEDBF, 0x000004A0 }, + { 0x0213F0FFEF5E3144, 0x00003FC0, 0xFFFFE2A1, 0x0000061A, 0x000027D8, 0xFFFFEFEC, 0x0000043A, 0x000027D8, 0xFFFFEFEC, 0x0000043A }, + { 0x0213F0FFEF661924, 0x00003FBF, 0xFFFFE2F5, 0x00000603, 0x000032D7, 0xFFFFE900, 0x00000552, 0x000032D7, 0xFFFFE900, 0x00000552 }, + { 0x0213F0FFEF5C10E4, 0x000035EE, 0xFFFFE6CA, 0x000005A2, 0x0000247C, 0xFFFFF088, 0x00000446, 0x0000247C, 0xFFFFF088, 0x00000446 }, + { 0x0213F0FFEF643884, 0x000039C8, 0xFFFFE3AE, 0x0000062A, 0x000028AF, 0xFFFFED24, 0x000004DF, 0x000028AF, 0xFFFFED24, 0x000004DF }, + { 0x0213F0FFEF5C2884, 0x00003BDE, 0xFFFFE33B, 0x00000632, 0x00001B6C, 0xFFFFF720, 0x00000326, 0x00001B6C, 0xFFFFF720, 0x00000326 }, + { 0x0213F0FFEF7210A4, 0x00003818, 0xFFFFE57D, 0x000005D4, 0x000020EF, 0xFFFFF327, 0x000003CE, 0x000020EF, 0xFFFFF327, 0x000003CE }, + { 0x0213F0FFEF5E19A4, 0x000038DA, 0xFFFFE561, 0x000005D3, 0x0000297D, 0xFFFFED6D, 0x000004C5, 0x0000297D, 0xFFFFED6D, 0x000004C5 }, + { 0x0213F0FFEF684884, 0x000027AC, 0xFFFFF0CE, 0x00000417, 0x00001F5F, 0xFFFFF484, 0x000003B2, 0x00001F5F, 0xFFFFF484, 0x000003B2 }, + { 0x0213F0FFEF6648A4, 0x00003F02, 0xFFFFE222, 0x00000643, 0x000026D4, 0xFFFFF000, 0x00000443, 0x000026D4, 0xFFFFF000, 0x00000443 }, + { 0x0213F0FFEF624164, 0x00004303, 0xFFFFDFE3, 0x00000690, 0x0000312C, 0xFFFFE912, 0x00000561, 0x0000312C, 0xFFFFE912, 0x00000561 }, + { 0x0213F0FFEF600904, 0x000039E5, 0xFFFFE31F, 0x00000657, 0x00001D23, 0xFFFFF51F, 0x00000386, 0x00001D23, 0xFFFFF51F, 0x00000386 }, + { 0x0213F0FFEF661144, 0x000041FA, 0xFFFFE01B, 0x00000697, 0x00002767, 0xFFFFEF90, 0x00000455, 0x00002767, 0xFFFFEF90, 0x00000455 }, + { 0x0213F0FFEF6830A4, 0x00002888, 0xFFFFF11C, 0x00000403, 0x00001864, 0xFFFFF9D8, 0x000002D3, 0x00001864, 0xFFFFF9D8, 0x000002D3 }, + { 0x0213EA94DE201864, 0x0000215C, 0xFFFFF5B6, 0x0000036D, 0x000015C5, 0xFFFFFB8A, 0x000002B5, 0x000015C5, 0xFFFFFB8A, 0x000002B5 }, + { 0x0213F0FFEF683984, 0x00002FAF, 0xFFFFEC27, 0x000004CA, 0x00002184, 0xFFFFF39C, 0x000003CD, 0x00002184, 0xFFFFF39C, 0x000003CD }, + { 0x0213F0FFEF5E10C4, 0x00004ACE, 0xFFFFD9A3, 0x000007BC, 0x00001A5D, 0xFFFFF7F6, 0x000002FC, 0x00001A5D, 0xFFFFF7F6, 0x000002FC }, + { 0x0213F0FFEF5A3044, 0x00003763, 0xFFFFE797, 0x0000055F, 0x000029B5, 0xFFFFEEA1, 0x00000474, 0x000029B5, 0xFFFFEEA1, 0x00000474 }, + { 0x0213F0FFEF5E3164, 0x00003832, 0xFFFFE6F9, 0x00000575, 0x00002C99, 0xFFFFEC42, 0x000004E3, 0x00002C99, 0xFFFFEC42, 0x000004E3 }, + { 0x0213F0FFEF604164, 0x000041C9, 0xFFFFDE33, 0x0000071E, 0x0000199D, 0xFFFFF808, 0x000002F9, 0x0000199D, 0xFFFFF808, 0x000002F9 }, + { 0x0213F0FFEF641164, 0x0000474A, 0xFFFFD96E, 0x00000802, 0x00002A30, 0xFFFFEB57, 0x0000053F, 0x00002A30, 0xFFFFEB57, 0x0000053F }, + { 0x0213F0FFEF5C31C4, 0x0000312F, 0xFFFFEA6A, 0x00000508, 0x000029D3, 0xFFFFED38, 0x000004D3, 0x000029D3, 0xFFFFED38, 0x000004D3 }, + { 0x0213F0FFEF7210C4, 0x00003BD6, 0xFFFFE2E7, 0x00000644, 0x00002093, 0xFFFFF37B, 0x000003BD, 0x00002093, 0xFFFFF37B, 0x000003BD }, + { 0x0213F0FFEF6840E4, 0x00002F94, 0xFFFFECD4, 0x000004A3, 0x00002196, 0xFFFFF40B, 0x000003B5, 0x00002196, 0xFFFFF40B, 0x000003B5 }, + { 0x0213F0FFEF5E1944, 0x0000369B, 0xFFFFE762, 0x00000571, 0x00002726, 0xFFFFEF99, 0x00000459, 0x00002726, 0xFFFFEF99, 0x00000459 }, + { 0x0213F0FFEF642064, 0x00003F57, 0xFFFFDF47, 0x000006F4, 0x00002E5F, 0xFFFFE8AE, 0x000005AB, 0x00002E5F, 0xFFFFE8AE, 0x000005AB }, + { 0x0213EA94DE0A40C4, 0x00004313, 0xFFFFDD81, 0x0000072D, 0x00002468, 0xFFFFF068, 0x00000440, 0x00002468, 0xFFFFF068, 0x00000440 }, + { 0x0213F0FFEF683044, 0x00002A35, 0xFFFFEFA8, 0x00000441, 0x00001F3F, 0xFFFFF4F3, 0x000003A0, 0x00001F3F, 0xFFFFF4F3, 0x000003A0 }, + { 0x0213F0FFEF6630A4, 0x00003E33, 0xFFFFE4B0, 0x000005AF, 0x00002802, 0xFFFFF092, 0x00000412, 0x00002802, 0xFFFFF092, 0x00000412 }, + { 0x0213EA94DE323904, 0x00002815, 0xFFFFF20E, 0x000003DD, 0x00001C33, 0xFFFFF7D5, 0x0000032A, 0x00001C33, 0xFFFFF7D5, 0x0000032A }, + { 0x0213F0FFEF5A2184, 0x00003CC2, 0xFFFFE43E, 0x000005DE, 0x00002C16, 0xFFFFECED, 0x000004BA, 0x00002C16, 0xFFFFECED, 0x000004BA }, + { 0x0213F0FFEF5C4084, 0x00003CFA, 0xFFFFE1EE, 0x00000673, 0x00001F7D, 0xFFFFF402, 0x000003AE, 0x00001F7D, 0xFFFFF402, 0x000003AE }, + { 0x0213F0FFEF622104, 0x0000486E, 0xFFFFDD43, 0x000006EE, 0x000036F0, 0xFFFFE609, 0x000005D5, 0x000036F0, 0xFFFFE609, 0x000005D5 }, + { 0x0213F0FFEF5C4964, 0x000039FE, 0xFFFFE41F, 0x00000613, 0x0000266C, 0xFFFFEF35, 0x0000047D, 0x0000266C, 0xFFFFEF35, 0x0000047D }, + { 0x0213EA94DE123124, 0x00002EA4, 0xFFFFEE3B, 0x00000462, 0x00002126, 0xFFFFF4E2, 0x0000038F, 0x00002126, 0xFFFFF4E2, 0x0000038F }, + { 0x0213F0FFEF683944, 0x00002D2E, 0xFFFFEE7B, 0x00000462, 0x0000229D, 0xFFFFF363, 0x000003D4, 0x0000229D, 0xFFFFF363, 0x000003D4 }, + { 0x0213F0FFEF5E2844, 0x0000375C, 0xFFFFE695, 0x0000059D, 0x00002319, 0xFFFFF237, 0x000003EE, 0x00002319, 0xFFFFF237, 0x000003EE }, + { 0x0213F0FFEF7250C4, 0x00004522, 0xFFFFDC71, 0x0000075E, 0x0000247E, 0xFFFFF0A0, 0x0000043C, 0x0000247E, 0xFFFFF0A0, 0x0000043C }, + { 0x0213EA94DE1248E4, 0x00002E58, 0xFFFFECB9, 0x000004A9, 0x0000199A, 0xFFFFF8CF, 0x000002E9, 0x0000199A, 0xFFFFF8CF, 0x000002E9 }, + { 0x0213F0FFEF6438E4, 0x00003791, 0xFFFFE5FE, 0x000005B6, 0x000029F5, 0xFFFFED0D, 0x000004CD, 0x000029F5, 0xFFFFED0D, 0x000004CD }, + { 0x0213EA94DE244144, 0x00002E9E, 0xFFFFEC8D, 0x000004C1, 0x000019D0, 0xFFFFF869, 0x0000030F, 0x000019D0, 0xFFFFF869, 0x0000030F }, + { 0x0213EA94DE203964, 0x0000237C, 0xFFFFF435, 0x000003A6, 0x000014EB, 0xFFFFFBC4, 0x000002AF, 0x000014EB, 0xFFFFFBC4, 0x000002AF }, + { 0x0213F0FFEF662924, 0x00003FE5, 0xFFFFE4A2, 0x000005A0, 0x00003416, 0xFFFFE995, 0x00000523, 0x00003416, 0xFFFFE995, 0x00000523 }, + { 0x0213F0FFEF5C0924, 0x00002B27, 0xFFFFED51, 0x000004A5, 0x000025D1, 0xFFFFEF18, 0x00000492, 0x000025D1, 0xFFFFEF18, 0x00000492 }, + { 0x0213F0FFEF684904, 0x00002D77, 0xFFFFED79, 0x00000494, 0x00002196, 0xFFFFF352, 0x000003DE, 0x00002196, 0xFFFFF352, 0x000003DE }, + { 0x0213F0FFEF5C20C4, 0x00003750, 0xFFFFE6AC, 0x00000596, 0x00002524, 0xFFFFF0B5, 0x00000431, 0x00002524, 0xFFFFF0B5, 0x00000431 }, + { 0x0213EA94DE122944, 0x00002896, 0xFFFFF1BB, 0x000003D9, 0x00001CE0, 0xFFFFF753, 0x0000032F, 0x00001CE0, 0xFFFFF753, 0x0000032F }, + { 0x0213F0FFEF641984, 0x00003CA7, 0xFFFFE0F7, 0x000006B1, 0x00002CB8, 0xFFFFE9AB, 0x00000587, 0x00002CB8, 0xFFFFE9AB, 0x00000587 }, + { 0x0213EA94DE322864, 0x00002513, 0xFFFFF323, 0x000003BC, 0x00001965, 0xFFFFF93C, 0x000002F0, 0x00001965, 0xFFFFF93C, 0x000002F0 }, + { 0x0213F0FFEF662164, 0x00003914, 0xFFFFE683, 0x00000586, 0x00003120, 0xFFFFE9A6, 0x00000543, 0x00003120, 0xFFFFE9A6, 0x00000543 }, + { 0x0213F0FFEF643904, 0x000040D0, 0xFFFFE007, 0x000006AC, 0x00002B9E, 0xFFFFEBF5, 0x000004FB, 0x00002B9E, 0xFFFFEBF5, 0x000004FB }, + { 0x0213F0FFEF5A4884, 0x00004412, 0xFFFFDF5F, 0x000006A9, 0x00002A9E, 0xFFFFEDCE, 0x00000498, 0x00002A9E, 0xFFFFEDCE, 0x00000498 }, + { 0x0213F0FFEF624884, 0x000042A6, 0xFFFFDFEF, 0x00000696, 0x00002E65, 0xFFFFEAAE, 0x00000529, 0x00002E65, 0xFFFFEAAE, 0x00000529 }, + { 0x0213EA94DE322124, 0x000022E8, 0xFFFFF565, 0x0000035F, 0x00001890, 0xFFFFFA61, 0x000002C6, 0x00001890, 0xFFFFFA61, 0x000002C6 }, + { 0x0213F0FFEF6239A4, 0x00004637, 0xFFFFDDD8, 0x000006E9, 0x0000349D, 0xFFFFE6C8, 0x000005C7, 0x0000349D, 0xFFFFE6C8, 0x000005C7 }, + { 0x0213EA94DE263904, 0x00004686, 0xFFFFDC58, 0x0000073D, 0x00003972, 0xFFFFE27B, 0x0000068E, 0x00003972, 0xFFFFE27B, 0x0000068E }, + { 0x0213F0FFEF6808E4, 0x00002B35, 0xFFFFEE9C, 0x0000046C, 0x00001F5B, 0xFFFFF4A3, 0x000003A9, 0x00001F5B, 0xFFFFF4A3, 0x000003A9 }, + { 0x0213F0FFEF724144, 0x00003AC9, 0xFFFFE3B2, 0x0000061B, 0x000023A1, 0xFFFFF170, 0x0000040F, 0x000023A1, 0xFFFFF170, 0x0000040F }, + { 0x0213F0FFEF5E1884, 0x00003C50, 0xFFFFE37E, 0x00000617, 0x0000218F, 0xFFFFF339, 0x000003C4, 0x0000218F, 0xFFFFF339, 0x000003C4 }, + { 0x0213F0FFEF663044, 0x00003793, 0xFFFFE761, 0x0000055D, 0x000029C7, 0xFFFFEE03, 0x00000496, 0x000029C7, 0xFFFFEE03, 0x00000496 }, + { 0x0213F0FFEF6438A4, 0x000040B5, 0xFFFFDF78, 0x000006DA, 0x00002DED, 0xFFFFEA20, 0x00000551, 0x00002DED, 0xFFFFEA20, 0x00000551 }, + { 0x0213F0FFEF601144, 0x000039D6, 0xFFFFE37D, 0x0000063C, 0x00001AED, 0xFFFFF6E2, 0x00000331, 0x00001AED, 0xFFFFF6E2, 0x00000331 }, + { 0x0213F0FFEF662144, 0x0000431F, 0xFFFFE09B, 0x0000066A, 0x00002BDF, 0xFFFFED93, 0x00000496, 0x00002BDF, 0xFFFFED93, 0x00000496 }, + { 0x0213F0FFEF623864, 0x00004887, 0xFFFFDC65, 0x00000721, 0x00003669, 0xFFFFE5C4, 0x000005E9, 0x00003669, 0xFFFFE5C4, 0x000005E9 }, + { 0x0213F0FFEF640924, 0x00004120, 0xFFFFDDAE, 0x00000748, 0x0000303B, 0xFFFFE70D, 0x000005FC, 0x0000303B, 0xFFFFE70D, 0x000005FC }, + { 0x0213F0FFEF5E28A4, 0x0000415D, 0xFFFFE0BE, 0x0000067B, 0x00002FA7, 0xFFFFEA28, 0x00000538, 0x00002FA7, 0xFFFFEA28, 0x00000538 }, + { 0x0213F0FFEF681904, 0x00002B12, 0xFFFFEFF9, 0x00000428, 0x00001DDA, 0xFFFFF693, 0x00000356, 0x00001DDA, 0xFFFFF693, 0x00000356 }, + { 0x0213F0FFEF5E3184, 0x00003ED3, 0xFFFFE28D, 0x0000062D, 0x00002B00, 0xFFFFED4E, 0x000004B3, 0x00002B00, 0xFFFFED4E, 0x000004B3 }, + { 0x0213F0FFEF6250A4, 0x00004218, 0xFFFFE039, 0x0000068F, 0x00002F84, 0xFFFFEA0C, 0x00000541, 0x00002F84, 0xFFFFEA0C, 0x00000541 }, + { 0x0213F0FFEF5A3844, 0x00003FF5, 0xFFFFE2A3, 0x00000617, 0x00003017, 0xFFFFEA7A, 0x00000520, 0x00003017, 0xFFFFEA7A, 0x00000520 }, + { 0x0213F0FFEF5A08A4, 0x00004304, 0xFFFFDFCC, 0x0000069E, 0x00002E0C, 0xFFFFEB51, 0x00000505, 0x00002E0C, 0xFFFFEB51, 0x00000505 }, + { 0x0213F0FFEF641944, 0x00003D3A, 0xFFFFE17F, 0x00000687, 0x0000284C, 0xFFFFED83, 0x000004CD, 0x0000284C, 0xFFFFED83, 0x000004CD }, + { 0x0213F0FFEF5E40A4, 0x000042F5, 0xFFFFDF76, 0x000006B2, 0x000027B6, 0xFFFFEF72, 0x00000455, 0x000027B6, 0xFFFFEF72, 0x00000455 }, + { 0x0213F0FFEF5C38C4, 0x00004267, 0xFFFFDF29, 0x000006D5, 0x0000298F, 0xFFFFEDBD, 0x000004AC, 0x0000298F, 0xFFFFEDBD, 0x000004AC }, + { 0x0213EA94DE240924, 0x0000303E, 0xFFFFEC00, 0x000004CB, 0x000021CD, 0xFFFFF36E, 0x000003D6, 0x000021CD, 0xFFFFF36E, 0x000003D6 }, + { 0x0213F0FFEF5E28C4, 0x00003127, 0xFFFFEBDB, 0x000004A6, 0x00002E95, 0xFFFFEB78, 0x000004F3, 0x00002E95, 0xFFFFEB78, 0x000004F3 }, + { 0x0213EA94DE1C1064, 0x00002655, 0xFFFFF2D9, 0x000003CF, 0x000019F5, 0xFFFFF8E7, 0x00000313, 0x000019F5, 0xFFFFF8E7, 0x00000313 }, + { 0x0213EA94DE164084, 0x00002372, 0xFFFFF449, 0x0000039B, 0x00001544, 0xFFFFFC16, 0x0000028B, 0x00001544, 0xFFFFFC16, 0x0000028B }, + { 0x0213F0FFEF6628C4, 0x0000348E, 0xFFFFEB20, 0x000004B2, 0x00002BE8, 0xFFFFEE80, 0x00000467, 0x00002BE8, 0xFFFFEE80, 0x00000467 }, + { 0x0213F0FFEF5E1104, 0x00004092, 0xFFFFE073, 0x0000069B, 0x00002061, 0xFFFFF403, 0x000003A0, 0x00002061, 0xFFFFF403, 0x000003A0 }, + { 0x0213F0FFEF7220E4, 0x000039D1, 0xFFFFE55D, 0x000005CC, 0x000025CB, 0xFFFFF0C0, 0x00000428, 0x000025CB, 0xFFFFF0C0, 0x00000428 }, + { 0x0213F0FFEF5E4884, 0x000042AA, 0xFFFFDF68, 0x000006C2, 0x0000290B, 0xFFFFEE78, 0x00000485, 0x0000290B, 0xFFFFEE78, 0x00000485 }, + { 0x0213F0FFEF7218C4, 0x0000356F, 0xFFFFE7AC, 0x0000056E, 0x00001BE8, 0xFFFFF6E3, 0x0000032A, 0x00001BE8, 0xFFFFF6E3, 0x0000032A }, + { 0x0213F0FFEF5E1144, 0x00003525, 0xFFFFE7FF, 0x0000055D, 0x0000242C, 0xFFFFF12E, 0x0000041D, 0x0000242C, 0xFFFFF12E, 0x0000041D }, + { 0x0213F0FFEF5C48C4, 0x00003360, 0xFFFFE895, 0x00000550, 0x00002175, 0xFFFFF29E, 0x000003E9, 0x00002175, 0xFFFFF29E, 0x000003E9 }, + { 0x0213F0FFEF6440A4, 0x00003C94, 0xFFFFE1C4, 0x0000067E, 0x00002E28, 0xFFFFE964, 0x0000057F, 0x00002E28, 0xFFFFE964, 0x0000057F }, + { 0x0213F0FFEF724124, 0x0000431C, 0xFFFFDE4B, 0x000006FF, 0x00002270, 0xFFFFF268, 0x000003E5, 0x00002270, 0xFFFFF268, 0x000003E5 }, + { 0x0213EA94DE1218C4, 0x00002B67, 0xFFFFF01D, 0x00000414, 0x000019FB, 0xFFFFF961, 0x000002D8, 0x000019FB, 0xFFFFF961, 0x000002D8 }, + { 0x0213F0FFEF5E3984, 0x0000400B, 0xFFFFE13D, 0x0000066F, 0x000024F3, 0xFFFFF125, 0x00000417, 0x000024F3, 0xFFFFF125, 0x00000417 }, + { 0x0213F0FFEF5A20A4, 0x00004460, 0xFFFFE00E, 0x0000067B, 0x000023DF, 0xFFFFF2E6, 0x000003BB, 0x000023DF, 0xFFFFF2E6, 0x000003BB }, + { 0x0213F0FFEF641864, 0x00003AFB, 0xFFFFE2C5, 0x00000650, 0x00002D46, 0xFFFFE9C4, 0x00000571, 0x00002D46, 0xFFFFE9C4, 0x00000571 }, + { 0x0213F0FFEF622924, 0x00005482, 0xFFFFD5BC, 0x0000081A, 0x00003250, 0xFFFFE961, 0x00000541, 0x00003250, 0xFFFFE961, 0x00000541 }, + { 0x0213F0FFEF5C2944, 0x00003D27, 0xFFFFE2FA, 0x00000632, 0x00002A4D, 0xFFFFED6A, 0x000004BB, 0x00002A4D, 0xFFFFED6A, 0x000004BB }, + { 0x0213F0FFEF6018A4, 0x00003E03, 0xFFFFE142, 0x00000690, 0x00001E08, 0xFFFFF555, 0x0000036C, 0x00001E08, 0xFFFFF555, 0x0000036C }, + { 0x0213F0FFEF5C2064, 0x000031B5, 0xFFFFE97D, 0x00000535, 0x0000232E, 0xFFFFF166, 0x00000422, 0x0000232E, 0xFFFFF166, 0x00000422 }, + { 0x0213F0FFEF5E18E4, 0x00003753, 0xFFFFE724, 0x00000575, 0x0000281A, 0xFFFFEF1A, 0x0000046B, 0x0000281A, 0xFFFFEF1A, 0x0000046B }, + { 0x0213EA94DE204144, 0x00002071, 0xFFFFF5C9, 0x0000036F, 0x00001470, 0xFFFFFBF7, 0x000002A5, 0x00001470, 0xFFFFFBF7, 0x000002A5 }, + { 0x0213F0FFEF683144, 0x00002799, 0xFFFFF223, 0x000003CF, 0x00001CD3, 0xFFFFF74A, 0x00000333, 0x00001CD3, 0xFFFFF74A, 0x00000333 }, + { 0x0213F0FFEF6610C4, 0x000040DF, 0xFFFFE11C, 0x00000664, 0x000031D4, 0xFFFFE8BC, 0x0000056F, 0x000031D4, 0xFFFFE8BC, 0x0000056F }, + { 0x0213F0FFEF6440C4, 0x00003A4D, 0xFFFFE3A6, 0x00000627, 0x00002871, 0xFFFFEDA0, 0x000004C0, 0x00002871, 0xFFFFEDA0, 0x000004C0 }, + { 0x0213F0FFEF681984, 0x00002AF9, 0xFFFFEED7, 0x00000464, 0x0000219B, 0xFFFFF368, 0x000003D6, 0x0000219B, 0xFFFFF368, 0x000003D6 }, + { 0x0213EA94DE323124, 0x000026D5, 0xFFFFF36C, 0x000003A3, 0x00001BC6, 0xFFFFF881, 0x00000311, 0x00001BC6, 0xFFFFF881, 0x00000311 }, + { 0x0213F0FFEF5E2044, 0x0000325D, 0xFFFFEA07, 0x0000050B, 0x000026D1, 0xFFFFEFB3, 0x0000045A, 0x000026D1, 0xFFFFEFB3, 0x0000045A }, + { 0x0213F0FFEF682864, 0x00002F75, 0xFFFFEC64, 0x000004BE, 0x00001EEB, 0xFFFFF559, 0x00000386, 0x00001EEB, 0xFFFFF559, 0x00000386 }, + { 0x0213F0FFEF5A38A4, 0x00003C2F, 0xFFFFE541, 0x000005A3, 0x000025B6, 0xFFFFF16F, 0x000003FA, 0x000025B6, 0xFFFFF16F, 0x000003FA }, + { 0x0213F0FFEF684924, 0x00002BC2, 0xFFFFEE89, 0x0000046A, 0x00001D04, 0xFFFFF651, 0x00000361, 0x00001D04, 0xFFFFF651, 0x00000361 }, + { 0x0213F0FFEF6829A4, 0x00002DD0, 0xFFFFED40, 0x0000049F, 0x00001C8C, 0xFFFFF6B3, 0x00000353, 0x00001C8C, 0xFFFFF6B3, 0x00000353 }, + { 0x0213EA94DE1C08E4, 0x000021ED, 0xFFFFF530, 0x00000380, 0x00001643, 0xFFFFFB1C, 0x000002C3, 0x00001643, 0xFFFFFB1C, 0x000002C3 }, + { 0x0213EA94DE321904, 0x000028C7, 0xFFFFF160, 0x000003FD, 0x00001990, 0xFFFFF994, 0x000002E2, 0x00001990, 0xFFFFF994, 0x000002E2 }, + { 0x0213F0FFEF6610A4, 0x0000431C, 0xFFFFDF9D, 0x000006A3, 0x000034A6, 0xFFFFE6B0, 0x000005C9, 0x000034A6, 0xFFFFE6B0, 0x000005C9 }, + { 0x0213EA94DE2630A4, 0x00004115, 0xFFFFE0D6, 0x00000667, 0x000031AD, 0xFFFFE850, 0x00000585, 0x000031AD, 0xFFFFE850, 0x00000585 }, + { 0x0213F0FFEF643924, 0x0000424A, 0xFFFFDEEC, 0x000006E1, 0x0000346A, 0xFFFFE5EA, 0x00000602, 0x0000346A, 0xFFFFE5EA, 0x00000602 }, + { 0x0213F0FFEF661984, 0x00004990, 0xFFFFDAFA, 0x00000771, 0x00002A9C, 0xFFFFED37, 0x000004BC, 0x00002A9C, 0xFFFFED37, 0x000004BC }, + { 0x0213F0FFEF6428A4, 0x00003858, 0xFFFFE568, 0x000005D2, 0x00003030, 0xFFFFE8B0, 0x0000058E, 0x00003030, 0xFFFFE8B0, 0x0000058E }, + { 0x0213F0FFEF684164, 0x00001EDC, 0xFFFFF6CD, 0x00000322, 0x00001FCA, 0xFFFFF4BD, 0x0000039E, 0x00001FCA, 0xFFFFF4BD, 0x0000039E }, + { 0x0213F0FFEF662124, 0x00004C88, 0xFFFFDBA3, 0x0000071B, 0x000030C4, 0xFFFFEAFD, 0x000004F7, 0x000030C4, 0xFFFFEAFD, 0x000004F7 }, + { 0x0213F0FFEF680904, 0x00002B9A, 0xFFFFEE41, 0x0000047D, 0x00002131, 0xFFFFF344, 0x000003E5, 0x00002131, 0xFFFFF344, 0x000003E5 }, + { 0x0213F0FFEF623984, 0x00003E4B, 0xFFFFE33C, 0x000005FA, 0x00003877, 0xFFFFE437, 0x0000062E, 0x00003877, 0xFFFFE437, 0x0000062E }, + { 0x0213EA94DE322064, 0x00002376, 0xFFFFF444, 0x0000038A, 0x000017ED, 0xFFFFFA4C, 0x000002C1, 0x000017ED, 0xFFFFFA4C, 0x000002C1 }, + { 0x0213F0FFEF661084, 0x00004517, 0xFFFFDDF4, 0x000006F2, 0x000030DC, 0xFFFFE8EF, 0x00000571, 0x000030DC, 0xFFFFE8EF, 0x00000571 }, + { 0x0213F0FFEF681944, 0x0000270C, 0xFFFFF1F3, 0x000003DF, 0x0000207B, 0xFFFFF474, 0x000003AD, 0x0000207B, 0xFFFFF474, 0x000003AD }, + { 0x0213F0FFEF645144, 0x00004086, 0xFFFFDF39, 0x000006E3, 0x00002A24, 0xFFFFEC2B, 0x000004FF, 0x00002A24, 0xFFFFEC2B, 0x000004FF }, + { 0x0213F0FFEF5C3124, 0x00003BDE, 0xFFFFE45E, 0x000005EB, 0x00002CD5, 0xFFFFEC45, 0x000004DD, 0x00002CD5, 0xFFFFEC45, 0x000004DD }, + { 0x0213F0FFEF7230E4, 0x00003803, 0xFFFFE714, 0x00000579, 0x0000288A, 0xFFFFEF21, 0x0000046B, 0x0000288A, 0xFFFFEF21, 0x0000046B }, + { 0x0213F0FFEF601104, 0x00003F50, 0xFFFFE002, 0x000006CD, 0x00001AD4, 0xFFFFF72E, 0x0000031F, 0x00001AD4, 0xFFFFF72E, 0x0000031F }, + { 0x0213F0FFEF6820E4, 0x00002968, 0xFFFFF100, 0x00000402, 0x00001FB5, 0xFFFFF57C, 0x0000037F, 0x00001FB5, 0xFFFFF57C, 0x0000037F }, + { 0x0213F0FFEF662104, 0x00004283, 0xFFFFE2A7, 0x000005F5, 0x00003165, 0xFFFFEB0C, 0x000004EC, 0x00003165, 0xFFFFEB0C, 0x000004EC }, + { 0x0213F0FFEF6431A4, 0x00004253, 0xFFFFDDA8, 0x00000732, 0x00002E5C, 0xFFFFE90A, 0x00000593, 0x00002E5C, 0xFFFFE90A, 0x00000593 }, + { 0x0213F0FFEF5C50A4, 0x00003551, 0xFFFFE756, 0x0000058D, 0x000029A7, 0xFFFFED0C, 0x000004DE, 0x000029A7, 0xFFFFED0C, 0x000004DE }, + { 0x0213F0FFEF6428C4, 0x00003728, 0xFFFFE604, 0x000005C4, 0x00002832, 0xFFFFEE64, 0x00000493, 0x00002832, 0xFFFFEE64, 0x00000493 }, + { 0x0213F0FFEF623964, 0x00004796, 0xFFFFDCC8, 0x00000715, 0x000032AB, 0xFFFFE848, 0x0000057C, 0x000032AB, 0xFFFFE848, 0x0000057C }, + { 0x0213F0FFEF6210C4, 0x000049DF, 0xFFFFDB24, 0x0000075F, 0x00003076, 0xFFFFE967, 0x0000055C, 0x00003076, 0xFFFFE967, 0x0000055C }, + { 0x0213F0FFEF721104, 0x00003F13, 0xFFFFE099, 0x000006A8, 0x00002279, 0xFFFFF226, 0x000003F3, 0x00002279, 0xFFFFF226, 0x000003F3 }, + { 0x0213F0FFEF6430A4, 0x00003E03, 0xFFFFE19F, 0x00000674, 0x00002D66, 0xFFFFEAA7, 0x00000537, 0x00002D66, 0xFFFFEAA7, 0x00000537 }, + { 0x0213F0FFEF5C4104, 0x000037DA, 0xFFFFE63F, 0x000005A7, 0x00002543, 0xFFFFF0A0, 0x00000431, 0x00002543, 0xFFFFF0A0, 0x00000431 }, + { 0x0213F0FFEF624944, 0x00003D82, 0xFFFFE3F5, 0x000005D9, 0x0000332F, 0xFFFFE834, 0x00000577, 0x0000332F, 0xFFFFE834, 0x00000577 }, + { 0x0213EA94DE1228C4, 0x00002915, 0xFFFFF1E0, 0x000003D4, 0x00002065, 0xFFFFF57B, 0x00000378, 0x00002065, 0xFFFFF57B, 0x00000378 }, + { 0x0213F0FFEF5E4904, 0x000036FC, 0xFFFFE72D, 0x00000577, 0x00002811, 0xFFFFEF30, 0x00000464, 0x00002811, 0xFFFFEF30, 0x00000464 }, + { 0x0213F0FFEF623184, 0x00004767, 0xFFFFDD30, 0x000006FD, 0x00003703, 0xFFFFE564, 0x000005F8, 0x00003703, 0xFFFFE564, 0x000005F8 }, + { 0x0213F0FFEF603184, 0x00003094, 0xFFFFEAA9, 0x000004F5, 0x000022E7, 0xFFFFF200, 0x000003FB, 0x000022E7, 0xFFFFF200, 0x000003FB }, + { 0x0213F0FFEF641144, 0x00003EF0, 0xFFFFDF83, 0x000006ED, 0x00002A27, 0xFFFFEB7C, 0x00000537, 0x00002A27, 0xFFFFEB7C, 0x00000537 }, + { 0x0213F0FFEF681124, 0x0000243C, 0xFFFFF358, 0x000003AC, 0x00001DC4, 0xFFFFF5E9, 0x00000372, 0x00001DC4, 0xFFFFF5E9, 0x00000372 }, + { 0x0213F0FFEF722144, 0x0000284B, 0xFFFFF036, 0x0000040F, 0x00001FCD, 0xFFFFF445, 0x00000395, 0x00001FCD, 0xFFFFF445, 0x00000395 }, + { 0x0213F0FFEF6840C4, 0x00002611, 0xFFFFF285, 0x000003C7, 0x00001CFE, 0xFFFFF6A0, 0x00000355, 0x00001CFE, 0xFFFFF6A0, 0x00000355 }, + { 0x0213EA94DE1C39A4, 0x00002292, 0xFFFFF49F, 0x00000393, 0x000017F4, 0xFFFFF9CD, 0x000002F5, 0x000017F4, 0xFFFFF9CD, 0x000002F5 }, + { 0x0213F0FFEF5E38A4, 0x000037F3, 0xFFFFE68D, 0x00000590, 0x00002443, 0xFFFFF1AD, 0x000003FA, 0x00002443, 0xFFFFF1AD, 0x000003FA }, + { 0x0213F0FFEF682144, 0x00002C01, 0xFFFFEF3F, 0x00000444, 0x0000210A, 0xFFFFF475, 0x000003A7, 0x0000210A, 0xFFFFF475, 0x000003A7 }, + { 0x0213EA94DE1210E4, 0x00002C0E, 0xFFFFEF0F, 0x00000446, 0x00001A82, 0xFFFFF8F7, 0x000002DE, 0x00001A82, 0xFFFFF8F7, 0x000002DE }, + { 0x0213F0FFEF5E20C4, 0x00003FA6, 0xFFFFE20A, 0x0000063F, 0x00002E29, 0xFFFFEB21, 0x00000510, 0x00002E29, 0xFFFFEB21, 0x00000510 }, + { 0x0213F0FFEF5C2164, 0x00003BCD, 0xFFFFE31B, 0x0000063C, 0x000019AF, 0xFFFFF83D, 0x000002F8, 0x000019AF, 0xFFFFF83D, 0x000002F8 }, + { 0x0213F0FFEF664164, 0x000044C8, 0xFFFFDF08, 0x000006B0, 0x00002E2E, 0xFFFFEB62, 0x000004FD, 0x00002E2E, 0xFFFFEB62, 0x000004FD }, + { 0x0213F0FFEF5C1884, 0x00003790, 0xFFFFE571, 0x000005E3, 0x00002042, 0xFFFFF35D, 0x000003CF, 0x00002042, 0xFFFFF35D, 0x000003CF }, + { 0x0213F0FFEF6050E4, 0x000038AC, 0xFFFFE46C, 0x00000609, 0x0000215E, 0xFFFFF22D, 0x00000403, 0x0000215E, 0xFFFFF22D, 0x00000403 }, + { 0x0213F0FFEF5E29A4, 0x00003A1E, 0xFFFFE536, 0x000005C9, 0x000024F3, 0xFFFFF11A, 0x0000041B, 0x000024F3, 0xFFFFF11A, 0x0000041B }, + { 0x0213F0FFEF6650E4, 0x0000431A, 0xFFFFDF1B, 0x000006C5, 0x00002F34, 0xFFFFEA02, 0x00000545, 0x00002F34, 0xFFFFEA02, 0x00000545 }, + { 0x0213F0FFEF641904, 0x000042DC, 0xFFFFDE28, 0x0000070C, 0x00003B53, 0xFFFFE0EA, 0x000006E2, 0x00003B53, 0xFFFFE0EA, 0x000006E2 }, + { 0x0213F0FFEF683164, 0x0000264B, 0xFFFFF29A, 0x000003C4, 0x000021D0, 0xFFFFF3CE, 0x000003C4, 0x000021D0, 0xFFFFF3CE, 0x000003C4 }, + { 0x0213F0FFEF5A4064, 0x00004225, 0xFFFFE0E8, 0x00000665, 0x00002B53, 0xFFFFED89, 0x0000049F, 0x00002B53, 0xFFFFED89, 0x0000049F }, + { 0x0213EA94DE204924, 0x00001FCC, 0xFFFFF63F, 0x00000358, 0x000019E8, 0xFFFFF882, 0x0000032A, 0x000019E8, 0xFFFFF882, 0x0000032A }, + { 0x0213F0FFEF6240A4, 0x000045E0, 0xFFFFDDD0, 0x000006ED, 0x00003193, 0xFFFFE8BD, 0x00000572, 0x00003193, 0xFFFFE8BD, 0x00000572 }, + { 0x0213F0FFEF683924, 0x000024FC, 0xFFFFF366, 0x000003A6, 0x00001FE8, 0xFFFFF509, 0x00000394, 0x00001FE8, 0xFFFFF509, 0x00000394 }, + { 0x0213F0FFEF5C4884, 0x0000378F, 0xFFFFE54B, 0x000005F1, 0x00001C9B, 0xFFFFF5C7, 0x00000368, 0x00001C9B, 0xFFFFF5C7, 0x00000368 }, + { 0x0213F0FFEF6418A4, 0x00003CF3, 0xFFFFE15A, 0x00000694, 0x00002CDD, 0xFFFFEA44, 0x00000557, 0x00002CDD, 0xFFFFEA44, 0x00000557 }, + { 0x0213EA94DE200904, 0x000021EC, 0xFFFFF4F4, 0x0000038F, 0x00001511, 0xFFFFFBF5, 0x0000029E, 0x00001511, 0xFFFFFBF5, 0x0000029E }, + { 0x0213F0FFEF6010A4, 0x00003C8A, 0xFFFFE1C1, 0x00000685, 0x000019C7, 0xFFFFF7E2, 0x00000301, 0x000019C7, 0xFFFFF7E2, 0x00000301 }, + { 0x0213F0FFEF5E2064, 0x00003908, 0xFFFFE5C7, 0x000005B3, 0x00002793, 0xFFFFEF46, 0x00000465, 0x00002793, 0xFFFFEF46, 0x00000465 }, + { 0x0213F0FFEF605104, 0x000040A3, 0xFFFFDE61, 0x00000725, 0x00002077, 0xFFFFF2CE, 0x000003E8, 0x00002077, 0xFFFFF2CE, 0x000003E8 }, + { 0x0213F0FFEF664144, 0x00003DCA, 0xFFFFE34D, 0x00000608, 0x00002D66, 0xFFFFEBDF, 0x000004E8, 0x00002D66, 0xFFFFEBDF, 0x000004E8 }, + { 0x0213F0FFEF5E50C4, 0x00003085, 0xFFFFEB70, 0x000004C8, 0x000029B1, 0xFFFFEDD9, 0x000004A5, 0x000029B1, 0xFFFFEDD9, 0x000004A5 }, + { 0x0213EA94DE083884, 0x00004C73, 0xFFFFD676, 0x0000086C, 0x0000280A, 0xFFFFED89, 0x000004C2, 0x0000280A, 0xFFFFED89, 0x000004C2 }, + { 0x0213EA94DE242164, 0x00002CE5, 0xFFFFEE8C, 0x00000466, 0x00001755, 0xFFFFFAC2, 0x000002AC, 0x00001755, 0xFFFFFAC2, 0x000002AC }, + { 0x0213F0FFEF621124, 0x0000489F, 0xFFFFDBF1, 0x0000073E, 0x0000332D, 0xFFFFE786, 0x000005AD, 0x0000332D, 0xFFFFE786, 0x000005AD }, + { 0x0213F0FFEF602864, 0x00003D09, 0xFFFFE193, 0x00000689, 0x00001E82, 0xFFFFF4C0, 0x00000386, 0x00001E82, 0xFFFFF4C0, 0x00000386 }, + { 0x0213F0FFEF644104, 0x00003E4C, 0xFFFFE131, 0x00000689, 0x00002F4E, 0xFFFFE925, 0x0000057B, 0x00002F4E, 0xFFFFE925, 0x0000057B }, + { 0x0213F0FFEF5A4084, 0x00003B31, 0xFFFFE53F, 0x000005B3, 0x0000248A, 0xFFFFF211, 0x000003DF, 0x0000248A, 0xFFFFF211, 0x000003DF }, + { 0x0213F0FFEF644124, 0x000038DD, 0xFFFFE54A, 0x000005C9, 0x00002B6D, 0xFFFFEBDF, 0x00000502, 0x00002B6D, 0xFFFFEBDF, 0x00000502 }, + { 0x0213F0FFEF684064, 0x00002698, 0xFFFFF1A8, 0x000003F2, 0x00002163, 0xFFFFF34B, 0x000003E3, 0x00002163, 0xFFFFF34B, 0x000003E3 }, + { 0x0213EA94DE201064, 0x000023A8, 0xFFFFF4CD, 0x00000386, 0x00001944, 0xFFFFF983, 0x00000300, 0x00001944, 0xFFFFF983, 0x00000300 }, + { 0x0213F0FFEF6418C4, 0x00003EAF, 0xFFFFE0C3, 0x000006A0, 0x000030AB, 0xFFFFE829, 0x000005A6, 0x000030AB, 0xFFFFE829, 0x000005A6 }, + { 0x0213F0FFEF684944, 0x00002E89, 0xFFFFECA6, 0x000004B6, 0x00001FA0, 0xFFFFF4A8, 0x000003A3, 0x00001FA0, 0xFFFFF4A8, 0x000003A3 }, + { 0x0213F0FFEF6828A4, 0x000028A4, 0xFFFFF112, 0x00000402, 0x00001F7C, 0xFFFFF545, 0x0000038A, 0x00001F7C, 0xFFFFF545, 0x0000038A }, + { 0x0213F0FFEF6650A4, 0x00004135, 0xFFFFDFA2, 0x000006C5, 0x0000324C, 0xFFFFE7AA, 0x000005AF, 0x0000324C, 0xFFFFE7AA, 0x000005AF }, + { 0x0213EA94DE2038C4, 0x00002012, 0xFFFFF693, 0x00000352, 0x0000171F, 0xFFFFFABB, 0x000002D9, 0x0000171F, 0xFFFFFABB, 0x000002D9 }, + { 0x0213F0FFEF643084, 0x00003D7C, 0xFFFFE1BC, 0x00000671, 0x00002A45, 0xFFFFEC84, 0x000004EC, 0x00002A45, 0xFFFFEC84, 0x000004EC }, + { 0x0213F0FFEF723064, 0x00004172, 0xFFFFDF58, 0x000006DA, 0x00002504, 0xFFFFF0A6, 0x00000431, 0x00002504, 0xFFFFF0A6, 0x00000431 }, + { 0x0213F0FE99281944, 0x000029C7, 0xFFFFF087, 0x00000414, 0x00001DCB, 0xFFFFF675, 0x0000035F, 0x00001DCB, 0xFFFFF675, 0x0000035F }, + { 0x0213F0FE992A29A4, 0x000027F0, 0xFFFFF05A, 0x00000432, 0x00001707, 0xFFFFFA0E, 0x000002D1, 0x00001707, 0xFFFFFA0E, 0x000002D1 }, + { 0x0213F0FE99222144, 0x00003279, 0xFFFFE9F7, 0x00000511, 0x00001B5E, 0xFFFFF787, 0x00000317, 0x00001B5E, 0xFFFFF787, 0x00000317 }, + { 0x0213F0FE99322184, 0x000030A5, 0xFFFFEABC, 0x000004FF, 0x000019D1, 0xFFFFF83C, 0x00000304, 0x000019D1, 0xFFFFF83C, 0x00000304 }, + { 0x0213F0FE99282844, 0x0000283B, 0xFFFFF122, 0x00000402, 0x000019C2, 0xFFFFF8E9, 0x000002FB, 0x000019C2, 0xFFFFF8E9, 0x000002FB }, + { 0x0213F0FE992C2084, 0x00003376, 0xFFFFE9E1, 0x00000510, 0x000021A7, 0xFFFFF39F, 0x000003BF, 0x000021A7, 0xFFFFF39F, 0x000003BF }, + { 0x0213F0FE993218C4, 0x000031D2, 0xFFFFEA9C, 0x000004FC, 0x00001F66, 0xFFFFF4E4, 0x00000390, 0x00001F66, 0xFFFFF4E4, 0x00000390 }, + { 0x0213F0FE991A3864, 0x00003006, 0xFFFFEB18, 0x000004F2, 0x000019B3, 0xFFFFF84E, 0x00000301, 0x000019B3, 0xFFFFF84E, 0x00000301 }, + { 0x0213F0FE993039A4, 0x0000364F, 0xFFFFE81F, 0x00000556, 0x00002AC9, 0xFFFFED87, 0x000004BD, 0x00002AC9, 0xFFFFED87, 0x000004BD }, + { 0x0213F0FE992E3844, 0x00003043, 0xFFFFEBAE, 0x000004CD, 0x00001B0C, 0xFFFFF7ED, 0x0000030C, 0x00001B0C, 0xFFFFF7ED, 0x0000030C }, + { 0x0213F0FE993048A4, 0x000037CE, 0xFFFFE69E, 0x00000596, 0x0000276B, 0xFFFFEF65, 0x0000046E, 0x0000276B, 0xFFFFEF65, 0x0000046E }, + { 0x0213F0FE992C3104, 0x00003063, 0xFFFFED5E, 0x0000046F, 0x000024AE, 0xFFFFF2C4, 0x000003D8, 0x000024AE, 0xFFFFF2C4, 0x000003D8 }, + { 0x0213F0FE992E08A4, 0x00002F5D, 0xFFFFEBDC, 0x000004D3, 0x00001EDB, 0xFFFFF50F, 0x0000038E, 0x00001EDB, 0xFFFFF50F, 0x0000038E }, + { 0x0213F0FE992E48A4, 0x00003148, 0xFFFFEA9A, 0x000004FB, 0x0000192D, 0xFFFFF8E9, 0x000002DF, 0x0000192D, 0xFFFFF8E9, 0x000002DF }, + { 0x0213F0FE992C2064, 0x00003682, 0xFFFFE7E4, 0x0000055C, 0x0000250E, 0xFFFFF150, 0x0000041A, 0x0000250E, 0xFFFFF150, 0x0000041A }, + { 0x0213F0FE992A2084, 0x0000284E, 0xFFFFF15A, 0x000003F8, 0x00001CE2, 0xFFFFF6F9, 0x0000034F, 0x00001CE2, 0xFFFFF6F9, 0x0000034F }, + { 0x0213F0FE993018A4, 0x00003171, 0xFFFFEAE9, 0x000004ED, 0x00001F40, 0xFFFFF513, 0x00000384, 0x00001F40, 0xFFFFF513, 0x00000384 }, + { 0x0213F0FE99323044, 0x000031BD, 0xFFFFEA64, 0x0000050A, 0x00001EFD, 0xFFFFF4F7, 0x00000390, 0x00001EFD, 0xFFFFF4F7, 0x00000390 }, + { 0x0213F0FE992E50E4, 0x00003050, 0xFFFFEB29, 0x000004EA, 0x000019B3, 0xFFFFF878, 0x000002F9, 0x000019B3, 0xFFFFF878, 0x000002F9 }, + { 0x0213F0FE992C1904, 0x00003400, 0xFFFFE9A0, 0x0000051A, 0x00002460, 0xFFFFF1DA, 0x00000409, 0x00002460, 0xFFFFF1DA, 0x00000409 }, + { 0x0213F0FE992C4884, 0x000034A1, 0xFFFFE86F, 0x00000558, 0x0000255D, 0xFFFFF09E, 0x00000443, 0x0000255D, 0xFFFFF09E, 0x00000443 }, + { 0x0213F0FE992E48E4, 0x00003103, 0xFFFFEAD7, 0x000004F0, 0x00001896, 0xFFFFF95A, 0x000002CC, 0x00001896, 0xFFFFF95A, 0x000002CC }, + { 0x0213F0FE993018E4, 0x00003120, 0xFFFFEB9E, 0x000004CB, 0x000021E8, 0xFFFFF3A2, 0x000003C1, 0x000021E8, 0xFFFFF3A2, 0x000003C1 }, + { 0x0213F0FE991C50E4, 0x00003558, 0xFFFFE812, 0x00000565, 0x0000256E, 0xFFFFF097, 0x00000447, 0x0000256E, 0xFFFFF097, 0x00000447 }, + { 0x0213F0FE991A2844, 0x00002DA8, 0xFFFFECA8, 0x000004B7, 0x0000180B, 0xFFFFF96D, 0x000002D8, 0x0000180B, 0xFFFFF96D, 0x000002D8 }, + { 0x0213F0FE992E3064, 0x00003232, 0xFFFFEA66, 0x000004FF, 0x00001DDE, 0xFFFFF5FE, 0x0000035A, 0x00001DDE, 0xFFFFF5FE, 0x0000035A }, + { 0x0213F0FE993050E4, 0x000034D2, 0xFFFFE89F, 0x00000548, 0x0000246C, 0xFFFFF17F, 0x00000418, 0x0000246C, 0xFFFFF17F, 0x00000418 }, + { 0x0213F0FE99304904, 0x000033EC, 0xFFFFE954, 0x0000052A, 0x00002323, 0xFFFFF279, 0x000003EE, 0x00002323, 0xFFFFF279, 0x000003EE }, + { 0x0213F0FE99303884, 0x000033AA, 0xFFFFE955, 0x0000052D, 0x0000229F, 0xFFFFF2B2, 0x000003E7, 0x0000229F, 0xFFFFF2B2, 0x000003E7 }, + { 0x0213F0FE99324964, 0x00003258, 0xFFFFE9AA, 0x0000052A, 0x00001D5F, 0xFFFFF5D1, 0x0000036B, 0x00001D5F, 0xFFFFF5D1, 0x0000036B }, + { 0x0213F0FE993029A4, 0x0000323A, 0xFFFFEA5F, 0x00000504, 0x00002108, 0xFFFFF3D5, 0x000003BA, 0x00002108, 0xFFFFF3D5, 0x000003BA }, + { 0x0213F0FE992C2184, 0x00003216, 0xFFFFEA6B, 0x000004FF, 0x00001D6E, 0xFFFFF640, 0x00000350, 0x00001D6E, 0xFFFFF640, 0x00000350 }, + { 0x0213F0FE993210E4, 0x000030C5, 0xFFFFEAC4, 0x000004FC, 0x00001924, 0xFFFFF8C2, 0x000002EE, 0x00001924, 0xFFFFF8C2, 0x000002EE }, + { 0x0213F0FE99305104, 0x000032BB, 0xFFFFE9F1, 0x00000515, 0x00002211, 0xFFFFF31B, 0x000003D5, 0x00002211, 0xFFFFF31B, 0x000003D5 }, + { 0x0213F0FE993048C4, 0x0000352C, 0xFFFFE85B, 0x00000553, 0x00002410, 0xFFFFF1B4, 0x0000040F, 0x00002410, 0xFFFFF1B4, 0x0000040F }, + { 0x0213F0FE992238C4, 0x000036A0, 0xFFFFE7E8, 0x0000055D, 0x00002901, 0xFFFFEEB8, 0x00000489, 0x00002901, 0xFFFFEEB8, 0x00000489 }, + { 0x0213F0FE992C3044, 0x00003340, 0xFFFFE9D9, 0x00000516, 0x00002332, 0xFFFFF27A, 0x000003F0, 0x00002332, 0xFFFFF27A, 0x000003F0 }, + { 0x0213F0FE991A38A4, 0x00003564, 0xFFFFE86D, 0x0000054E, 0x00002613, 0xFFFFF07C, 0x00000444, 0x00002613, 0xFFFFF07C, 0x00000444 }, + { 0x0213F0FE99280904, 0x00002AD1, 0xFFFFEF0B, 0x0000045C, 0x00001DEA, 0xFFFFF5C8, 0x00000381, 0x00001DEA, 0xFFFFF5C8, 0x00000381 }, + { 0x0213F0FE992220E4, 0x000035B0, 0xFFFFE846, 0x00000555, 0x000027BE, 0xFFFFEF5D, 0x00000474, 0x000027BE, 0xFFFFEF5D, 0x00000474 }, + { 0x0213F0FE992238A4, 0x000032C4, 0xFFFFEA48, 0x00000502, 0x000022C6, 0xFFFFF2DF, 0x000003DE, 0x000022C6, 0xFFFFF2DF, 0x000003DE }, + { 0x0213F0FE993008C4, 0x00003036, 0xFFFFEB0D, 0x000004F9, 0x00001FE8, 0xFFFFF41A, 0x000003BC, 0x00001FE8, 0xFFFFF41A, 0x000003BC }, + { 0x0213F0FE991A0904, 0x000030F8, 0xFFFFEA13, 0x00000524, 0x00001B6A, 0xFFFFF6C9, 0x0000034A, 0x00001B6A, 0xFFFFF6C9, 0x0000034A }, + { 0x0213F0FE993010A4, 0x00002EE2, 0xFFFFEC0C, 0x000004CB, 0x00001A39, 0xFFFFF814, 0x0000030F, 0x00001A39, 0xFFFFF814, 0x0000030F }, + { 0x0213F0FE991C3184, 0x00003457, 0xFFFFE924, 0x0000052A, 0x00001E9D, 0xFFFFF59C, 0x00000363, 0x00001E9D, 0xFFFFF59C, 0x00000363 }, + { 0x0213F0FE99322844, 0x000030BF, 0xFFFFEB18, 0x000004ED, 0x00001D37, 0xFFFFF636, 0x0000035C, 0x00001D37, 0xFFFFF636, 0x0000035C }, + { 0x0213F0FE992E4084, 0x000031AF, 0xFFFFEA75, 0x000004FE, 0x000019F2, 0xFFFFF87A, 0x000002F0, 0x000019F2, 0xFFFFF87A, 0x000002F0 }, + { 0x0213F0FE99302884, 0x00003642, 0xFFFFE85B, 0x00000547, 0x00002975, 0xFFFFEE98, 0x0000048B, 0x00002975, 0xFFFFEE98, 0x0000048B }, + { 0x0213F0FE992E2884, 0x00002E8B, 0xFFFFED1E, 0x0000048E, 0x000019C1, 0xFFFFF917, 0x000002D6, 0x000019C1, 0xFFFFF917, 0x000002D6 }, + { 0x0213F0FE993241A4, 0x000033D9, 0xFFFFE8E1, 0x00000548, 0x0000224B, 0xFFFFF298, 0x000003F4, 0x0000224B, 0xFFFFF298, 0x000003F4 }, + { 0x0213F0FE992E28C4, 0x000032BC, 0xFFFFEB0F, 0x000004D6, 0x00002488, 0xFFFFF240, 0x000003F2, 0x00002488, 0xFFFFF240, 0x000003F2 }, + { 0x0213F0FE99304944, 0x000035FD, 0xFFFFE838, 0x00000553, 0x00002762, 0xFFFFEFBC, 0x00000460, 0x00002762, 0xFFFFEFBC, 0x00000460 }, + { 0x0213F0FE992818A4, 0x0000268B, 0xFFFFF263, 0x000003D1, 0x00001914, 0xFFFFF977, 0x000002E8, 0x00001914, 0xFFFFF977, 0x000002E8 }, + { 0x0213F0FE992C3184, 0x0000330B, 0xFFFFEA1E, 0x00000505, 0x000020B1, 0xFFFFF44D, 0x0000039E, 0x000020B1, 0xFFFFF44D, 0x0000039E }, + { 0x0213F0FE99222084, 0x0000326E, 0xFFFFEA26, 0x00000508, 0x00001C17, 0xFFFFF722, 0x00000328, 0x00001C17, 0xFFFFF722, 0x00000328 }, + { 0x0213F0FE992A31A4, 0x00002A3F, 0xFFFFEEE8, 0x0000046D, 0x00001B2B, 0xFFFFF737, 0x0000034D, 0x00001B2B, 0xFFFFF737, 0x0000034D }, + { 0x0213F0FE992C4064, 0x00003732, 0xFFFFE765, 0x00000574, 0x00002A6D, 0xFFFFEDA8, 0x000004B7, 0x00002A6D, 0xFFFFEDA8, 0x000004B7 }, + { 0x0213F0FE99300924, 0x000034D3, 0xFFFFE827, 0x00000569, 0x000027AA, 0xFFFFEEE7, 0x00000492, 0x000027AA, 0xFFFFEEE7, 0x00000492 }, + { 0x0213F0FE992E40C4, 0x00003306, 0xFFFFEA39, 0x000004FC, 0x00001DCC, 0xFFFFF655, 0x00000344, 0x00001DCC, 0xFFFFF655, 0x00000344 }, + { 0x0213F0FE99282044, 0x00002A48, 0xFFFFEFCA, 0x00000439, 0x00001DED, 0xFFFFF60D, 0x00000375, 0x00001DED, 0xFFFFF60D, 0x00000375 }, + { 0x0213F0FE993038C4, 0x000033A3, 0xFFFFEA36, 0x000004F9, 0x0000247C, 0xFFFFF21F, 0x000003F4, 0x0000247C, 0xFFFFF21F, 0x000003F4 }, + { 0x0213F0FE992C3164, 0x0000311B, 0xFFFFEB76, 0x000004D1, 0x00001EB1, 0xFFFFF5B6, 0x00000366, 0x00001EB1, 0xFFFFF5B6, 0x00000366 }, + { 0x0213F0FE99324164, 0x00003307, 0xFFFFE97F, 0x0000052A, 0x00001E76, 0xFFFFF54D, 0x0000037C, 0x00001E76, 0xFFFFF54D, 0x0000037C }, + { 0x0213F0FE991C2144, 0x0000344B, 0xFFFFE9C5, 0x00000509, 0x000020D6, 0xFFFFF486, 0x0000038F, 0x000020D6, 0xFFFFF486, 0x0000038F }, + { 0x0213F0FE992C3144, 0x000034B9, 0xFFFFEA0B, 0x000004F7, 0x000027B3, 0xFFFFF057, 0x0000043A, 0x000027B3, 0xFFFFF057, 0x0000043A }, + { 0x0213F0FE99301964, 0x00003360, 0xFFFFE984, 0x00000527, 0x00002238, 0xFFFFF2EE, 0x000003E0, 0x00002238, 0xFFFFF2EE, 0x000003E0 }, + { 0x0213F0FE99302124, 0x0000315C, 0xFFFFEC05, 0x000004B1, 0x000023C8, 0xFFFFF2CC, 0x000003DE, 0x000023C8, 0xFFFFF2CC, 0x000003DE }, + { 0x0213F0FE992C2864, 0x0000389B, 0xFFFFE6D5, 0x00000582, 0x00002C6C, 0xFFFFEC92, 0x000004DE, 0x00002C6C, 0xFFFFEC92, 0x000004DE }, + { 0x0213F0FE992E1124, 0x00003058, 0xFFFFEB30, 0x000004E6, 0x000019B5, 0xFFFFF88B, 0x000002F1, 0x000019B5, 0xFFFFF88B, 0x000002F1 }, + { 0x0213F0FE992E0904, 0x00002F69, 0xFFFFEB4A, 0x000004F1, 0x00001B82, 0xFFFFF6EC, 0x00000341, 0x00001B82, 0xFFFFF6EC, 0x00000341 }, + { 0x0213F0FE991A18E4, 0x000031EB, 0xFFFFEA64, 0x00000508, 0x00002059, 0xFFFFF427, 0x000003B0, 0x00002059, 0xFFFFF427, 0x000003B0 }, + { 0x0213F0FE99224124, 0x000033E2, 0xFFFFE94D, 0x0000052A, 0x000020BF, 0xFFFFF40B, 0x000003AB, 0x000020BF, 0xFFFFF40B, 0x000003AB }, + { 0x0213F0FE99283184, 0x00002AF9, 0xFFFFEFE9, 0x00000427, 0x00001F72, 0xFFFFF57A, 0x00000383, 0x00001F72, 0xFFFFF57A, 0x00000383 }, + { 0x0213F0FE992C2824, 0x00003282, 0xFFFFEA88, 0x000004FA, 0x00002561, 0xFFFFF126, 0x0000042B, 0x00002561, 0xFFFFF126, 0x0000042B }, + { 0x0213F0FE993010E4, 0x0000308A, 0xFFFFEB5D, 0x000004E0, 0x00001E83, 0xFFFFF577, 0x00000378, 0x00001E83, 0xFFFFF577, 0x00000378 }, + { 0x0213F0FE99324884, 0x0000336E, 0xFFFFE8C8, 0x00000553, 0x0000217C, 0xFFFFF2E1, 0x000003EB, 0x0000217C, 0xFFFFF2E1, 0x000003EB }, + { 0x0213F0FE991A2164, 0x000034A9, 0xFFFFE838, 0x00000561, 0x000020CE, 0xFFFFF38A, 0x000003C7, 0x000020CE, 0xFFFFF38A, 0x000003C7 }, + { 0x0213F0FE99222184, 0x00003152, 0xFFFFE9EB, 0x00000522, 0x00001755, 0xFFFFF9A9, 0x000002C6, 0x00001755, 0xFFFFF9A9, 0x000002C6 }, + { 0x0213F0FE99281884, 0x0000286E, 0xFFFFF136, 0x000003FD, 0x00001BAB, 0xFFFFF7C3, 0x0000032C, 0x00001BAB, 0xFFFFF7C3, 0x0000032C }, + { 0x0213F0FE99300944, 0x0000316B, 0xFFFFEA02, 0x00000528, 0x00002247, 0xFFFFF24E, 0x00000408, 0x00002247, 0xFFFFF24E, 0x00000408 }, + { 0x0213F0FE992C08E4, 0x000034CF, 0xFFFFE83D, 0x00000562, 0x00002458, 0xFFFFF130, 0x00000430, 0x00002458, 0xFFFFF130, 0x00000430 }, + { 0x0213F0FE992C2984, 0x00003352, 0xFFFFE9D1, 0x00000515, 0x0000212A, 0xFFFFF3DC, 0x000003B4, 0x0000212A, 0xFFFFF3DC, 0x000003B4 }, + { 0x0213F0FE992840A4, 0x00002946, 0xFFFFF09B, 0x00000415, 0x00001DC9, 0xFFFFF650, 0x00000366, 0x00001DC9, 0xFFFFF650, 0x00000366 }, + { 0x0213F0FE99301124, 0x00003080, 0xFFFFEB47, 0x000004E1, 0x00001BD5, 0xFFFFF73B, 0x00000329, 0x00001BD5, 0xFFFFF73B, 0x00000329 }, + { 0x0213F0FE991A1884, 0x00002FBD, 0xFFFFEB7B, 0x000004DD, 0x000017FC, 0xFFFFF99E, 0x000002C7, 0x000017FC, 0xFFFFF99E, 0x000002C7 }, + { 0x0213F0FE99281124, 0x00002A28, 0xFFFFF032, 0x0000041F, 0x00001B19, 0xFFFFF83A, 0x00000312, 0x00001B19, 0xFFFFF83A, 0x00000312 }, + { 0x0213F0FE992240C4, 0x00003420, 0xFFFFE936, 0x00000530, 0x000023C2, 0xFFFFF203, 0x00000406, 0x000023C2, 0xFFFFF203, 0x00000406 }, + { 0x0213F0FE99301144, 0x00002F7C, 0xFFFFEBBA, 0x000004D1, 0x0000185D, 0xFFFFF975, 0x000002CA, 0x0000185D, 0xFFFFF975, 0x000002CA }, + { 0x0213F0FE992E2044, 0x00002C51, 0xFFFFEE3B, 0x0000046F, 0x000019AA, 0xFFFFF8DD, 0x000002ED, 0x000019AA, 0xFFFFF8DD, 0x000002ED }, + { 0x0213F0FE991A4144, 0x000033D6, 0xFFFFE8F2, 0x0000053D, 0x00001D73, 0xFFFFF5FB, 0x0000035B, 0x00001D73, 0xFFFFF5FB, 0x0000035B }, + { 0x0213F0FE99323084, 0x000031D9, 0xFFFFEAF7, 0x000004E4, 0x00001EBD, 0xFFFFF5A6, 0x00000368, 0x00001EBD, 0xFFFFF5A6, 0x00000368 }, + { 0x0213F0FE991A20A4, 0x00003386, 0xFFFFE9CE, 0x00000515, 0x00002422, 0xFFFFF1F3, 0x00000405, 0x00002422, 0xFFFFF1F3, 0x00000405 }, + { 0x0213F0FE992C50E4, 0x000032FB, 0xFFFFE9BC, 0x00000520, 0x00002301, 0xFFFFF267, 0x000003F7, 0x00002301, 0xFFFFF267, 0x000003F7 }, + { 0x0213F0FE99322924, 0x000032C2, 0xFFFFEAC0, 0x000004EA, 0x0000250F, 0xFFFFF1A2, 0x00000413, 0x0000250F, 0xFFFFF1A2, 0x00000413 }, + { 0x0213F0FE991C2944, 0x00003722, 0xFFFFE8A6, 0x00000527, 0x000026E4, 0xFFFFF0F5, 0x0000041C, 0x000026E4, 0xFFFFF0F5, 0x0000041C }, + { 0x0213F0FE992C48C4, 0x000035A4, 0xFFFFE822, 0x00000558, 0x000022F2, 0xFFFFF288, 0x000003E8, 0x000022F2, 0xFFFFF288, 0x000003E8 }, + { 0x0213F0FE99280924, 0x00002CD1, 0xFFFFEDC6, 0x0000048C, 0x00001EAF, 0xFFFFF53D, 0x00000396, 0x00001EAF, 0xFFFFF53D, 0x00000396 }, + { 0x0213F0FE99301164, 0x00003156, 0xFFFFEA60, 0x0000050B, 0x00001BBC, 0xFFFFF704, 0x00000335, 0x00001BBC, 0xFFFFF704, 0x00000335 }, + { 0x0213F0FE992C5104, 0x000034A1, 0xFFFFE8C0, 0x00000544, 0x00002528, 0xFFFFF105, 0x0000042C, 0x00002528, 0xFFFFF105, 0x0000042C }, + { 0x0213F0FE99323064, 0x000032CE, 0xFFFFE9D3, 0x00000520, 0x000021FF, 0xFFFFF2FD, 0x000003E4, 0x000021FF, 0xFFFFF2FD, 0x000003E4 }, + { 0x0213F0FE991A50A4, 0x000034A0, 0xFFFFE823, 0x0000056D, 0x0000256F, 0xFFFFF047, 0x0000045A, 0x0000256F, 0xFFFFF047, 0x0000045A }, + { 0x0213F0FE99303944, 0x00003109, 0xFFFFEBD6, 0x000004BF, 0x000022D4, 0xFFFFF32D, 0x000003D0, 0x000022D4, 0xFFFFF32D, 0x000003D0 }, + { 0x0213F0FE992C1164, 0x000030B7, 0xFFFFEAF0, 0x000004F3, 0x00001AEC, 0xFFFFF7A9, 0x0000031B, 0x00001AEC, 0xFFFFF7A9, 0x0000031B }, + { 0x0213F0FE992C39A4, 0x00003078, 0xFFFFEBA4, 0x000004CF, 0x00001E7A, 0xFFFFF5AF, 0x0000036B, 0x00001E7A, 0xFFFFF5AF, 0x0000036B }, + { 0x0213F0FE99304124, 0x00003442, 0xFFFFE998, 0x00000518, 0x000025EA, 0xFFFFF0F3, 0x0000042B, 0x000025EA, 0xFFFFF0F3, 0x0000042B }, + { 0x0213F0FE993021A4, 0x000031CB, 0xFFFFEA80, 0x00000501, 0x000020A3, 0xFFFFF403, 0x000003B2, 0x000020A3, 0xFFFFF403, 0x000003B2 }, + { 0x0213F0FE992A2984, 0x00002947, 0xFFFFF018, 0x00000433, 0x00001BA5, 0xFFFFF75C, 0x00000340, 0x00001BA5, 0xFFFFF75C, 0x00000340 }, + { 0x0213F0FE992C3984, 0x000033F9, 0xFFFFE99D, 0x00000518, 0x00002231, 0xFFFFF358, 0x000003C5, 0x00002231, 0xFFFFF358, 0x000003C5 }, + { 0x0213F0FE99321124, 0x00003131, 0xFFFFEA45, 0x00000513, 0x00001973, 0xFFFFF85E, 0x00000301, 0x00001973, 0xFFFFF85E, 0x00000301 }, + { 0x0213F0FE991C29A4, 0x00003571, 0xFFFFE8AC, 0x00000539, 0x00002049, 0xFFFFF49C, 0x0000038D, 0x00002049, 0xFFFFF49C, 0x0000038D }, + { 0x0213F0FE992E3864, 0x0000309E, 0xFFFFEB1D, 0x000004E8, 0x000019ED, 0xFFFFF86E, 0x000002F8, 0x000019ED, 0xFFFFF86E, 0x000002F8 }, + { 0x0213F0FE99302984, 0x00003091, 0xFFFFEB9B, 0x000004CC, 0x00001D2C, 0xFFFFF6A2, 0x0000033D, 0x00001D2C, 0xFFFFF6A2, 0x0000033D }, + { 0x0213F0FE993008E4, 0x00003069, 0xFFFFEAFD, 0x000004F8, 0x00001E82, 0xFFFFF51C, 0x0000038D, 0x00001E82, 0xFFFFF51C, 0x0000038D }, + { 0x0213F0FE992210A4, 0x00003459, 0xFFFFE7F2, 0x00000572, 0x00001DA7, 0xFFFFF552, 0x0000037F, 0x00001DA7, 0xFFFFF552, 0x0000037F }, + { 0x0213F0FE99321104, 0x0000304B, 0xFFFFEAFB, 0x000004F4, 0x0000191E, 0xFFFFF8BD, 0x000002EE, 0x0000191E, 0xFFFFF8BD, 0x000002EE }, + { 0x0213F0FE993020C4, 0x0000346E, 0xFFFFEA07, 0x000004FD, 0x00002767, 0xFFFFF058, 0x00000440, 0x00002767, 0xFFFFF058, 0x00000440 }, + { 0x0213F0FE992E3084, 0x000030B5, 0xFFFFEBC1, 0x000004C1, 0x00001B3C, 0xFFFFF818, 0x000002FD, 0x00001B3C, 0xFFFFF818, 0x000002FD }, + { 0x0213F0FE99300904, 0x0000321F, 0xFFFFE9EA, 0x00000524, 0x00002380, 0xFFFFF1C2, 0x0000041A, 0x00002380, 0xFFFFF1C2, 0x0000041A }, + { 0x0213F0FE992E3044, 0x000030DF, 0xFFFFEB37, 0x000004E2, 0x00001E3C, 0xFFFFF5BB, 0x00000369, 0x00001E3C, 0xFFFFF5BB, 0x00000369 }, + { 0x0213F0FE992848A4, 0x000027E0, 0xFFFFF0E2, 0x00000416, 0x00001A6A, 0xFFFFF820, 0x00000321, 0x00001A6A, 0xFFFFF820, 0x00000321 }, + { 0x0213F0FE991A1084, 0x00002FA1, 0xFFFFEB63, 0x000004E7, 0x0000196B, 0xFFFFF880, 0x000002FB, 0x0000196B, 0xFFFFF880, 0x000002FB }, + { 0x0213F0FE991C1084, 0x0000310C, 0xFFFFEAAF, 0x000004FC, 0x000019EF, 0xFFFFF850, 0x000002FD, 0x000019EF, 0xFFFFF850, 0x000002FD }, + { 0x0213F0FE99323904, 0x0000334A, 0xFFFFEA07, 0x0000050B, 0x00002380, 0xFFFFF26F, 0x000003F0, 0x00002380, 0xFFFFF26F, 0x000003F0 }, + { 0x0213F0FE99302944, 0x00002FF9, 0xFFFFECDC, 0x00000492, 0x00002297, 0xFFFFF394, 0x000003BF, 0x00002297, 0xFFFFF394, 0x000003BF }, + { 0x0213F0FE992C2164, 0x0000354B, 0xFFFFE894, 0x00000546, 0x000024C4, 0xFFFFF16C, 0x0000041B, 0x000024C4, 0xFFFFF16C, 0x0000041B }, + { 0x0213F0FE99220924, 0x00003245, 0xFFFFE92F, 0x00000544, 0x00001829, 0xFFFFF8F1, 0x000002EA, 0x00001829, 0xFFFFF8F1, 0x000002EA }, + { 0x0213F0FE992E4884, 0x0000302F, 0xFFFFEB51, 0x000004E3, 0x0000199F, 0xFFFFF894, 0x000002F4, 0x0000199F, 0xFFFFF894, 0x000002F4 }, + { 0x0213F0FE992E18C4, 0x00002F54, 0xFFFFEC86, 0x000004A6, 0x00001A6F, 0xFFFFF891, 0x000002EC, 0x00001A6F, 0xFFFFF891, 0x000002EC }, + { 0x0213F0FE99284164, 0x00002908, 0xFFFFF0D8, 0x0000040A, 0x00001C9B, 0xFFFFF729, 0x00000342, 0x00001C9B, 0xFFFFF729, 0x00000342 }, + { 0x0213F0FE99302964, 0x000031D9, 0xFFFFEB40, 0x000004D7, 0x000023F5, 0xFFFFF259, 0x000003F4, 0x000023F5, 0xFFFFF259, 0x000003F4 }, + { 0x0213F0FE993048E4, 0x000034C8, 0xFFFFE8C6, 0x0000053F, 0x00002313, 0xFFFFF280, 0x000003EC, 0x00002313, 0xFFFFF280, 0x000003EC }, + { 0x0213F0FE993050C4, 0x000037D1, 0xFFFFE6A1, 0x0000059C, 0x00002C6A, 0xFFFFEBFF, 0x00000504, 0x00002C6A, 0xFFFFEBFF, 0x00000504 }, + { 0x0213F0FE99321964, 0x000030E9, 0xFFFFEA6B, 0x0000050F, 0x00001A2D, 0xFFFFF7DF, 0x00000316, 0x00001A2D, 0xFFFFF7DF, 0x00000316 }, + { 0x0213F0FE99302084, 0x0000323D, 0xFFFFEA95, 0x000004F4, 0x00001ED2, 0xFFFFF584, 0x0000036C, 0x00001ED2, 0xFFFFF584, 0x0000036C }, + { 0x0213F0FE992C3024, 0x000033D6, 0xFFFFE9DB, 0x00000510, 0x000027A7, 0xFFFFEFC7, 0x0000045E, 0x000027A7, 0xFFFFEFC7, 0x0000045E }, + { 0x0213F0FE991C3164, 0x00003444, 0xFFFFE98A, 0x00000517, 0x000020FD, 0xFFFFF43F, 0x0000039D, 0x000020FD, 0xFFFFF43F, 0x0000039D }, + { 0x0213F0FE992808E4, 0x00002987, 0xFFFFEFA1, 0x0000044B, 0x00001B06, 0xFFFFF788, 0x0000033C, 0x00001B06, 0xFFFFF788, 0x0000033C }, + { 0x0213F0FE992C28E4, 0x0000311D, 0xFFFFED20, 0x00000474, 0x000025DA, 0xFFFFF223, 0x000003F0, 0x000025DA, 0xFFFFF223, 0x000003F0 }, + { 0x0213F0FE992C1124, 0x000032A2, 0xFFFFEA0A, 0x0000050D, 0x00001D48, 0xFFFFF659, 0x0000034A, 0x00001D48, 0xFFFFF659, 0x0000034A }, + { 0x0213F0FE992208E4, 0x00003110, 0xFFFFE9EA, 0x00000529, 0x00001786, 0xFFFFF958, 0x000002DB, 0x00001786, 0xFFFFF958, 0x000002DB }, + { 0x0213F0FE992821A4, 0x000027F2, 0xFFFFF174, 0x000003F7, 0x00001C7A, 0xFFFFF72A, 0x00000348, 0x00001C7A, 0xFFFFF72A, 0x00000348 }, + { 0x0213F0FE991C10E4, 0x000031DB, 0xFFFFEA7D, 0x000004FB, 0x000019C4, 0xFFFFF8B1, 0x000002E6, 0x000019C4, 0xFFFFF8B1, 0x000002E6 }, + { 0x0213F0FE992C1104, 0x00003158, 0xFFFFEAAC, 0x000004FA, 0x00001BC1, 0xFFFFF737, 0x0000032B, 0x00001BC1, 0xFFFFF737, 0x0000032B }, + { 0x0213F0FE993010C4, 0x00002F36, 0xFFFFEBF9, 0x000004CA, 0x00001A2A, 0xFFFFF83F, 0x00000303, 0x00001A2A, 0xFFFFF83F, 0x00000303 }, + { 0x0213F0FE993238A4, 0x000032B4, 0xFFFFEA72, 0x000004FA, 0x000021FF, 0xFFFFF378, 0x000003C5, 0x000021FF, 0xFFFFF378, 0x000003C5 }, + { 0x0213F0FE99303164, 0x00003262, 0xFFFFEAFA, 0x000004DF, 0x00002441, 0xFFFFF237, 0x000003F6, 0x00002441, 0xFFFFF237, 0x000003F6 }, + { 0x0213F0FE99303924, 0x0000336A, 0xFFFFEAFB, 0x000004D1, 0x00002746, 0xFFFFF0B8, 0x0000042B, 0x00002746, 0xFFFFF0B8, 0x0000042B }, + { 0x0213F0FE991A4084, 0x000032E5, 0xFFFFE923, 0x00000541, 0x00001DF0, 0xFFFFF552, 0x00000380, 0x00001DF0, 0xFFFFF552, 0x00000380 }, + { 0x0213F0FE99304064, 0x000035D1, 0xFFFFE80B, 0x0000055F, 0x00002780, 0xFFFFEF74, 0x0000046F, 0x00002780, 0xFFFFEF74, 0x0000046F }, + { 0x0213F0FE993028A4, 0x000033EC, 0xFFFFEA48, 0x000004F4, 0x0000269F, 0xFFFFF0D8, 0x0000042A, 0x0000269F, 0xFFFFF0D8, 0x0000042A }, + { 0x0213F0FE99323884, 0x000030C4, 0xFFFFEB39, 0x000004E2, 0x00001B44, 0xFFFFF7AA, 0x00000318, 0x00001B44, 0xFFFFF7AA, 0x00000318 }, + { 0x0213F0FE99281144, 0x00002926, 0xFFFFF0AF, 0x0000040E, 0x0000194E, 0xFFFFF959, 0x000002E2, 0x0000194E, 0xFFFFF959, 0x000002E2 }, + { 0x0213F0FE992C10C4, 0x00003141, 0xFFFFEAAF, 0x000004F6, 0x00001864, 0xFFFFF97C, 0x000002C6, 0x00001864, 0xFFFFF97C, 0x000002C6 }, + { 0x0213F0FE99301064, 0x000030B2, 0xFFFFEB7C, 0x000004DB, 0x000022CE, 0xFFFFF2B5, 0x000003F0, 0x000022CE, 0xFFFFF2B5, 0x000003F0 }, + { 0x0213F0FE99301944, 0x0000318C, 0xFFFFEAC7, 0x000004F6, 0x00002113, 0xFFFFF3CA, 0x000003BD, 0x00002113, 0xFFFFF3CA, 0x000003BD }, + { 0x0213F0FE992E1104, 0x00002FD2, 0xFFFFEB8F, 0x000004D9, 0x00001996, 0xFFFFF89F, 0x000002F1, 0x00001996, 0xFFFFF89F, 0x000002F1 }, + { 0x0213F0FE991A28A4, 0x0000310D, 0xFFFFEB25, 0x000004E7, 0x00001F67, 0xFFFFF4EF, 0x0000038E, 0x00001F67, 0xFFFFF4EF, 0x0000038E }, + { 0x0213F0FE992A4964, 0x00002BBC, 0xFFFFEE68, 0x00000477, 0x00002050, 0xFFFFF41D, 0x000003C8, 0x00002050, 0xFFFFF41D, 0x000003C8 }, + { 0x0213F0FE99302104, 0x00003096, 0xFFFFECED, 0x00000486, 0x000024C9, 0xFFFFF278, 0x000003E7, 0x000024C9, 0xFFFFF278, 0x000003E7 }, + { 0x0213F0FE992C10A4, 0x00003401, 0xFFFFE8F1, 0x0000053C, 0x00001E75, 0xFFFFF55C, 0x00000376, 0x00001E75, 0xFFFFF55C, 0x00000376 }, + { 0x0213F0FE99302844, 0x0000319E, 0xFFFFEAB1, 0x000004F8, 0x00001EA3, 0xFFFFF567, 0x00000378, 0x00001EA3, 0xFFFFF567, 0x00000378 }, + { 0x0213F0FE99322964, 0x000030FD, 0xFFFFEB4C, 0x000004DB, 0x00001CA6, 0xFFFFF6E8, 0x00000335, 0x00001CA6, 0xFFFFF6E8, 0x00000335 }, + { 0x0213F0FE992E40A4, 0x000030D6, 0xFFFFEB1A, 0x000004E4, 0x00001A0D, 0xFFFFF87D, 0x000002EF, 0x00001A0D, 0xFFFFF87D, 0x000002EF }, + { 0x0213F0FE992C2124, 0x0000324B, 0xFFFFEB17, 0x000004D9, 0x00002225, 0xFFFFF3A8, 0x000003BA, 0x00002225, 0xFFFFF3A8, 0x000003BA }, + { 0x0213F0FE99284084, 0x00002A00, 0xFFFFF02E, 0x00000424, 0x00001E21, 0xFFFFF61D, 0x0000036C, 0x00001E21, 0xFFFFF61D, 0x0000036C }, + { 0x0213F0FE992A48A4, 0x000029CF, 0xFFFFEF53, 0x00000457, 0x00001B11, 0xFFFFF772, 0x0000033D, 0x00001B11, 0xFFFFF772, 0x0000033D }, + { 0x0213F0FE991A30A4, 0x000032A1, 0xFFFFEA63, 0x000004FB, 0x00001F83, 0xFFFFF516, 0x0000037E, 0x00001F83, 0xFFFFF516, 0x0000037E }, + { 0x0213F0FE992E20C4, 0x0000305C, 0xFFFFEC14, 0x000004B5, 0x00001D0B, 0xFFFFF6ED, 0x00000332, 0x00001D0B, 0xFFFFF6ED, 0x00000332 }, + { 0x0213F0FE992C1064, 0x00003467, 0xFFFFE8D5, 0x00000543, 0x0000243F, 0xFFFFF190, 0x00000418, 0x0000243F, 0xFFFFF190, 0x00000418 }, + { 0x0213F0FE992A2064, 0x00002796, 0xFFFFF133, 0x00000409, 0x00001903, 0xFFFFF91C, 0x000002FC, 0x00001903, 0xFFFFF91C, 0x000002FC }, + { 0x0213F0FE99302164, 0x000031F6, 0xFFFFEAB7, 0x000004F5, 0x000022B9, 0xFFFFF2D0, 0x000003E6, 0x000022B9, 0xFFFFF2D0, 0x000003E6 }, + { 0x0213F0FE992E5104, 0x00003196, 0xFFFFEA76, 0x00000503, 0x00001CC5, 0xFFFFF67D, 0x0000034A, 0x00001CC5, 0xFFFFF67D, 0x0000034A }, + { 0x0213F0FE99321144, 0x00002F9E, 0xFFFFEAD9, 0x00000505, 0x000017C1, 0xFFFFF93D, 0x000002DF, 0x000017C1, 0xFFFFF93D, 0x000002DF }, + { 0x0213F0FE992E2124, 0x00002FBC, 0xFFFFEC75, 0x000004A8, 0x00001D6D, 0xFFFFF6AC, 0x0000033D, 0x00001D6D, 0xFFFFF6AC, 0x0000033D }, + { 0x0213F0FE992C38A4, 0x00003541, 0xFFFFE921, 0x00000524, 0x00002662, 0xFFFFF0CB, 0x0000042B, 0x00002662, 0xFFFFF0CB, 0x0000042B }, + { 0x0213F0FE992A21A4, 0x00002953, 0xFFFFEF76, 0x00000459, 0x00001C05, 0xFFFFF6A0, 0x00000368, 0x00001C05, 0xFFFFF6A0, 0x00000368 }, + { 0x0213F0FE992C4924, 0x000034BC, 0xFFFFE8DD, 0x00000536, 0x0000210E, 0xFFFFF3F4, 0x000003A8, 0x0000210E, 0xFFFFF3F4, 0x000003A8 }, + { 0x0213F0FE992C29A4, 0x000034BE, 0xFFFFE916, 0x0000052F, 0x000024A1, 0xFFFFF1A6, 0x00000410, 0x000024A1, 0xFFFFF1A6, 0x00000410 }, + { 0x0213F0FE99304964, 0x000037B5, 0xFFFFE7A9, 0x0000055B, 0x000028A1, 0xFFFFEF51, 0x00000467, 0x000028A1, 0xFFFFEF51, 0x00000467 }, + { 0x0213F0FE99301104, 0x00002FC5, 0xFFFFEBBE, 0x000004D1, 0x00001BA5, 0xFFFFF757, 0x00000328, 0x00001BA5, 0xFFFFF757, 0x00000328 }, + { 0x0213F0FE993040A4, 0x000033CB, 0xFFFFE944, 0x0000052B, 0x00001FBE, 0xFFFFF4B1, 0x0000038C, 0x00001FBE, 0xFFFFF4B1, 0x0000038C }, + { 0x0213F0FE99301844, 0x000030AE, 0xFFFFEBA0, 0x000004D3, 0x00002268, 0xFFFFF316, 0x000003DD, 0x00002268, 0xFFFFF316, 0x000003DD }, + { 0x0213F0FE992C20A4, 0x00002F90, 0xFFFFEC5A, 0x000004B0, 0x00001C3A, 0xFFFFF752, 0x00000323, 0x00001C3A, 0xFFFFF752, 0x00000323 }, + { 0x0213F0FE992E38E4, 0x00003113, 0xFFFFEB91, 0x000004C8, 0x00001E3C, 0xFFFFF623, 0x0000034E, 0x00001E3C, 0xFFFFF623, 0x0000034E }, + { 0x0213F0FE99323984, 0x0000330B, 0xFFFFE94B, 0x00000539, 0x000020E7, 0xFFFFF37E, 0x000003CD, 0x000020E7, 0xFFFFF37E, 0x000003CD }, + { 0x0213F0FE992E2864, 0x000031D1, 0xFFFFEACB, 0x000004ED, 0x00001E82, 0xFFFFF5B2, 0x00000365, 0x00001E82, 0xFFFFF5B2, 0x00000365 }, + { 0x0213F0FE992A3984, 0x00002CD5, 0xFFFFEDC1, 0x0000048D, 0x000020F8, 0xFFFFF3C1, 0x000003D1, 0x000020F8, 0xFFFFF3C1, 0x000003D1 }, + { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } }; int pp_override_get_default_fuse_value(uint64_t key, - struct phm_fuses_default list[], struct phm_fuses_default *result) { + const struct phm_fuses_default *list = vega10_fuses_default; uint32_t i; - uint64_t temp_serial_numer; - uint32_t bit; - const char *temp; - for (i = 0; list[i].key != NULL; i++) { - temp = list[i].key; - temp_serial_numer = 0; - do { - bit = *temp=='1'? 1 : 0; - temp_serial_numer = (temp_serial_numer <<1 ) | bit; - temp++; - } while (*temp); - - if (key == temp_serial_numer) { + for (i = 0; list[i].key != 0; i++) { + if (key == list[i].key) { result->key = list[i].key; result->VFT2_m1 = list[i].VFT2_m1; result->VFT2_m2 = list[i].VFT2_m2; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h index 6e8f7a2119c1..c6ba0d64cfb7 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_overdriver.h @@ -28,7 +28,7 @@ #include <linux/kernel.h> struct phm_fuses_default { - const char *key; + uint64_t key; uint32_t VFT2_m1; uint32_t VFT2_m2; uint32_t VFT2_b; @@ -40,9 +40,7 @@ struct phm_fuses_default { uint32_t VFT0_b; }; -extern struct phm_fuses_default vega10_fuses_default[]; extern int pp_override_get_default_fuse_value(uint64_t key, - struct phm_fuses_default list[], struct phm_fuses_default *result); #endif
\ No newline at end of file diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c index 167cdc321db2..ffa44bbb218e 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_psm.c @@ -224,6 +224,8 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip, if (skip) return 0; + phm_display_configuration_changed(hwmgr); + if (new_ps != NULL) requested = new_ps; else @@ -232,7 +234,6 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip, pcurrent = hwmgr->current_ps; phm_apply_state_adjust_rules(hwmgr, requested, pcurrent); - if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr, &pcurrent->hardware, &requested->hardware, &equal))) equal = false; @@ -241,6 +242,9 @@ int psm_adjust_power_state_dynamic(struct pp_hwmgr *hwmgr, bool skip, phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware); memcpy(hwmgr->current_ps, hwmgr->request_ps, hwmgr->ps_size); } + + phm_notify_smc_display_config_after_ps_adjustment(hwmgr); + return 0; } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c index 485f7ebdc754..afae32ee2b0d 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c @@ -790,7 +790,7 @@ static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2( return pstate; } -static unsigned char soft_dummy_pp_table[] = { +static const unsigned char soft_dummy_pp_table[] = { 0xe1, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x4a, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x00, 0x02, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00, 0x88, 0x00, 0x00, 0x9e, 0x00, 0x17, 0x00, 0x00, 0x00, 0x9e, 0x00, 0x00, 0x00, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c index 9186b0788fac..3e0b267c74a8 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.c @@ -312,37 +312,37 @@ static int rv_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, } /* temporary hardcoded clock voltage breakdown tables */ -DpmClock_t VddDcfClk[]= { +static const DpmClock_t VddDcfClk[]= { { 300, 2600}, { 600, 3200}, { 600, 3600}, }; -DpmClock_t VddSocClk[]= { +static const DpmClock_t VddSocClk[]= { { 478, 2600}, { 722, 3200}, { 722, 3600}, }; -DpmClock_t VddFClk[]= { +static const DpmClock_t VddFClk[]= { { 400, 2600}, {1200, 3200}, {1200, 3600}, }; -DpmClock_t VddDispClk[]= { +static const DpmClock_t VddDispClk[]= { { 435, 2600}, { 661, 3200}, {1086, 3600}, }; -DpmClock_t VddDppClk[]= { +static const DpmClock_t VddDppClk[]= { { 435, 2600}, { 661, 3200}, { 661, 3600}, }; -DpmClock_t VddPhyClk[]= { +static const DpmClock_t VddPhyClk[]= { { 540, 2600}, { 810, 3200}, { 810, 3600}, @@ -350,7 +350,7 @@ DpmClock_t VddPhyClk[]= { static int rv_get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, struct rv_voltage_dependency_table **pptable, - uint32_t num_entry, DpmClock_t *pclk_dependency_table) + uint32_t num_entry, const DpmClock_t *pclk_dependency_table) { uint32_t table_size, i; struct rv_voltage_dependency_table *ptable; @@ -421,6 +421,26 @@ static int rv_populate_clock_table(struct pp_hwmgr *hwmgr) rv_get_clock_voltage_dependency_table(hwmgr, &pinfo->vdd_dep_on_phyclk, ARRAY_SIZE(VddPhyClk), &VddPhyClk[0]); + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetMinGfxclkFrequency), + "Attempt to get min GFXCLK Failed!", + return -1); + PP_ASSERT_WITH_CODE(!rv_read_arg_from_smc(hwmgr, + &result), + "Attempt to get min GFXCLK Failed!", + return -1); + rv_data->gfx_min_freq_limit = result * 100; + + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetMaxGfxclkFrequency), + "Attempt to get max GFXCLK Failed!", + return -1); + PP_ASSERT_WITH_CODE(!rv_read_arg_from_smc(hwmgr, + &result), + "Attempt to get max GFXCLK Failed!", + return -1); + rv_data->gfx_max_freq_limit = result * 100; + return 0; } @@ -599,43 +619,73 @@ static int rv_force_clock_level(struct pp_hwmgr *hwmgr, static int rv_print_clock_levels(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf) { - return 0; + struct rv_hwmgr *data = (struct rv_hwmgr *)(hwmgr->backend); + struct rv_voltage_dependency_table *mclk_table = + data->clock_vol_info.vdd_dep_on_fclk; + int i, now, size = 0; + + switch (type) { + case PP_SCLK: + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetGfxclkFrequency), + "Attempt to get current GFXCLK Failed!", + return -1); + PP_ASSERT_WITH_CODE(!rv_read_arg_from_smc(hwmgr, + &now), + "Attempt to get current GFXCLK Failed!", + return -1); + + size += sprintf(buf + size, "0: %uMhz %s\n", + data->gfx_min_freq_limit / 100, + ((data->gfx_min_freq_limit / 100) + == now) ? "*" : ""); + size += sprintf(buf + size, "1: %uMhz %s\n", + data->gfx_max_freq_limit / 100, + ((data->gfx_max_freq_limit / 100) + == now) ? "*" : ""); + break; + case PP_MCLK: + PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr, + PPSMC_MSG_GetFclkFrequency), + "Attempt to get current MEMCLK Failed!", + return -1); + PP_ASSERT_WITH_CODE(!rv_read_arg_from_smc(hwmgr, + &now), + "Attempt to get current MEMCLK Failed!", + return -1); + + for (i = 0; i < mclk_table->count; i++) + size += sprintf(buf + size, "%d: %uMhz %s\n", + i, + mclk_table->entries[i].clk / 100, + ((mclk_table->entries[i].clk / 100) + == now) ? "*" : ""); + break; + default: + break; + } + + return size; } static int rv_get_performance_level(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, PHM_PerformanceLevelDesignation designation, uint32_t index, PHM_PerformanceLevel *level) { - const struct rv_power_state *ps; struct rv_hwmgr *data; - uint32_t level_index; - uint32_t i; - uint32_t vol_dep_record_index = 0; if (level == NULL || hwmgr == NULL || state == NULL) return -EINVAL; data = (struct rv_hwmgr *)(hwmgr->backend); - ps = cast_const_rv_ps(state); - - level_index = index > ps->level - 1 ? ps->level - 1 : index; - level->coreClock = 30000; - - if (designation == PHM_PerformanceLevelDesignation_PowerContainment) { - for (i = 1; i < ps->level; i++) { - if (ps->levels[i].engine_clock > data->dce_slow_sclk_threshold) { - level->coreClock = 30000; - break; - } - } - } - if (level_index == 0) { - vol_dep_record_index = data->clock_vol_info.vdd_dep_on_fclk->count - 1; - level->memory_clock = - data->clock_vol_info.vdd_dep_on_fclk->entries[vol_dep_record_index].clk; - } else { + if (index == 0) { level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[0].clk; + level->coreClock = data->gfx_min_freq_limit; + } else { + level->memory_clock = data->clock_vol_info.vdd_dep_on_fclk->entries[ + data->clock_vol_info.vdd_dep_on_fclk->count - 1].clk; + level->coreClock = data->gfx_max_freq_limit; } level->nonLocalMemoryFreq = 0; @@ -830,13 +880,37 @@ static int rv_thermal_get_temperature(struct pp_hwmgr *hwmgr) static int rv_read_sensor(struct pp_hwmgr *hwmgr, int idx, void *value, int *size) { + uint32_t sclk, mclk; + int ret = 0; + switch (idx) { + case AMDGPU_PP_SENSOR_GFX_SCLK: + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetGfxclkFrequency); + if (!ret) { + rv_read_arg_from_smc(hwmgr, &sclk); + /* in units of 10KHZ */ + *((uint32_t *)value) = sclk * 100; + *size = 4; + } + break; + case AMDGPU_PP_SENSOR_GFX_MCLK: + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetFclkFrequency); + if (!ret) { + rv_read_arg_from_smc(hwmgr, &mclk); + /* in units of 10KHZ */ + *((uint32_t *)value) = mclk * 100; + *size = 4; + } + break; case AMDGPU_PP_SENSOR_GPU_TEMP: *((uint32_t *)value) = rv_thermal_get_temperature(hwmgr); - return 0; + break; default: - return -EINVAL; + ret = -EINVAL; + break; } + + return ret; } static const struct pp_hwmgr_func rv_hwmgr_funcs = { diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h index 68d61bd95ca0..9dc503055394 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/rv_hwmgr.h @@ -283,6 +283,8 @@ struct rv_hwmgr { uint32_t vclk_soft_min; uint32_t dclk_soft_min; uint32_t gfx_actual_soft_min_freq; + uint32_t gfx_min_freq_limit; + uint32_t gfx_max_freq_limit; bool vcn_power_gated; bool vcn_dpg_mode; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index 8dbe9148aad3..4466469cf8ab 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -815,7 +815,7 @@ uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr) { uint32_t reference_clock, tmp; struct cgs_display_info info = {0}; - struct cgs_mode_info mode_info; + struct cgs_mode_info mode_info = {0}; info.mode_info = &mode_info; @@ -3825,14 +3825,11 @@ static int smu7_notify_link_speed_change_after_state_change( static int smu7_notify_smc_display(struct pp_hwmgr *hwmgr) { struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int ret = 0; - if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) { + if (hwmgr->feature_mask & PP_VBI_TIME_SUPPORT_MASK) smum_send_msg_to_smc_with_parameter(hwmgr, (PPSMC_Msg)PPSMC_MSG_SetVBITimeout, data->frame_time_x2); - ret = (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay) == 0) ? 0 : -EINVAL; - } - return ret; + return (smum_send_msg_to_smc(hwmgr, (PPSMC_Msg)PPSMC_HasDisplay) == 0) ? 0 : -EINVAL; } static int smu7_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) @@ -3951,10 +3948,9 @@ static int smu7_program_display_gap(struct pp_hwmgr *hwmgr) uint32_t ref_clock; uint32_t refresh_rate = 0; struct cgs_display_info info = {0}; - struct cgs_mode_info mode_info; + struct cgs_mode_info mode_info = {0}; info.mode_info = &mode_info; - cgs_get_active_displays_info(hwmgr->device, &info); num_active_displays = info.display_count; @@ -3970,6 +3966,7 @@ static int smu7_program_display_gap(struct pp_hwmgr *hwmgr) frame_time_in_us = 1000000 / refresh_rate; pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us; + data->frame_time_x2 = frame_time_in_us * 2 / 100; display_gap2 = pre_vbi_time_in_us * (ref_clock / 100); @@ -4648,6 +4645,47 @@ static int smu7_avfs_control(struct pp_hwmgr *hwmgr, bool enable) return 0; } +static int smu7_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_ADDR_H), + mc_addr_hi); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_ADDR_L), + mc_addr_low); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_H), + virtual_addr_hi); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_PHY_ADDR_L), + virtual_addr_low); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + smum_get_offsetof(hwmgr, + SMU_SoftRegisters, DRAM_LOG_BUFF_SIZE), + size); + return 0; +} + static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .backend_init = &smu7_hwmgr_backend_init, .backend_fini = &smu7_hwmgr_backend_fini, @@ -4699,6 +4737,7 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = { .avfs_control = smu7_avfs_control, .disable_smc_firmware_ctf = smu7_thermal_disable_alert, .start_thermal_controller = smu7_start_thermal_controller, + .notify_cac_buffer_info = smu7_notify_cac_buffer_info, }; uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock, diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index a59d282797f5..4f79c21f27ed 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -56,7 +56,7 @@ #define HBM_MEMORY_CHANNEL_WIDTH 128 -uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2}; +static const uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2}; #define MEM_FREQ_LOW_LATENCY 25000 #define MEM_FREQ_HIGH_LATENCY 80000 @@ -81,7 +81,7 @@ uint32_t channel_number[] = {1, 2, 0, 4, 0, 8, 0, 16, 2}; static int vega10_force_clock_level(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); -const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic); +static const ULONG PhwVega10_Magic = (ULONG)(PHM_VIslands_Magic); struct vega10_power_state *cast_phw_vega10_power_state( struct pp_hw_power_state *hw_ps) @@ -1161,6 +1161,8 @@ static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr, { int i; + dpm_table->count = 0; + for (i = 0; i < dep_table->count; i++) { if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <= dep_table->entries[i].clk) { @@ -1269,10 +1271,6 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) return -EINVAL); /* Initialize Sclk DPM table based on allow Sclk values */ - data->dpm_table.soc_table.count = 0; - data->dpm_table.gfx_table.count = 0; - data->dpm_table.dcef_table.count = 0; - dpm_table = &(data->dpm_table.soc_table); vega10_setup_default_single_dpm_table(hwmgr, dpm_table, @@ -1809,6 +1807,10 @@ static int vega10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) mem_channels = (cgs_read_register(hwmgr->device, reg) & DF_CS_AON0_DramBaseAddress0__IntLvNumChan_MASK) >> DF_CS_AON0_DramBaseAddress0__IntLvNumChan__SHIFT; + PP_ASSERT_WITH_CODE(mem_channels < ARRAY_SIZE(channel_number), + "Mem Channel Index Exceeded maximum!", + return -1); + pp_table->NumMemoryChannels = cpu_to_le16(mem_channels); pp_table->MemoryChannelWidth = cpu_to_le16(HBM_MEMORY_CHANNEL_WIDTH * @@ -2364,7 +2366,7 @@ static int vega10_avfs_enable(struct pp_hwmgr *hwmgr, bool enable) } else { PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr, false, - data->smu_features[GNLD_AVFS].smu_feature_id), + data->smu_features[GNLD_AVFS].smu_feature_bitmap), "[avfs_control] Attempt to Disable AVFS feature Failed!", return -1); data->smu_features[GNLD_AVFS].enabled = false; @@ -2393,7 +2395,7 @@ static int vega10_populate_and_upload_avfs_fuse_override(struct pp_hwmgr *hwmgr) serial_number = ((uint64_t)bottom32 << 32) | top32; - if (pp_override_get_default_fuse_value(serial_number, vega10_fuses_default, &fuse) == 0) { + if (pp_override_get_default_fuse_value(serial_number, &fuse) == 0) { avfs_fuse_table->VFT0_b = fuse.VFT0_b; avfs_fuse_table->VFT0_m1 = fuse.VFT0_m1; avfs_fuse_table->VFT0_m2 = fuse.VFT0_m2; @@ -2881,6 +2883,15 @@ static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr) "DPM is already running right , skipping re-enablement!", return 0); + if ((data->smu_version == 0x001c2c00) || + (data->smu_version == 0x001c2d00)) { + tmp_result = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UpdatePkgPwrPidAlpha, 1); + PP_ASSERT_WITH_CODE(!tmp_result, + "Failed to set package power PID!", + return tmp_result); + } + tmp_result = vega10_construct_voltage_tables(hwmgr); PP_ASSERT_WITH_CODE(!tmp_result, "Failed to contruct voltage tables!", @@ -3127,6 +3138,8 @@ static int vega10_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, minimum_clocks.memoryClock = hwmgr->display_config.min_mem_set_clock; if (PP_CAP(PHM_PlatformCaps_StablePState)) { + stable_pstate_sclk_dpm_percentage = + data->registry_data.stable_pstate_sclk_dpm_percentage; PP_ASSERT_WITH_CODE( data->registry_data.stable_pstate_sclk_dpm_percentage >= 1 && data->registry_data.stable_pstate_sclk_dpm_percentage <= 100, @@ -4227,7 +4240,7 @@ static void vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) vega10_fan_ctrl_stop_smc_fan_control(hwmgr); break; case AMD_FAN_CTRL_AUTO: - if (!vega10_fan_ctrl_set_static_mode(hwmgr, mode)) + if (PP_CAP(PHM_PlatformCaps_MicrocodeFanControl)) vega10_fan_ctrl_start_smc_fan_control(hwmgr); break; default: @@ -4994,6 +5007,33 @@ static int vega10_set_mclk_od(struct pp_hwmgr *hwmgr, uint32_t value) return 0; } +static int vega10_notify_cac_buffer_info(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size) +{ + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSystemVirtualDramAddrHigh, + virtual_addr_hi); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetSystemVirtualDramAddrLow, + virtual_addr_low); + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramAddrHigh, + mc_addr_hi); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramAddrLow, + mc_addr_low); + + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_DramLogSetDramSize, + size); + return 0; +} + static int vega10_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info) { @@ -5079,7 +5119,9 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = { .get_mclk_od = vega10_get_mclk_od, .set_mclk_od = vega10_set_mclk_od, .avfs_control = vega10_avfs_enable, + .notify_cac_buffer_info = vega10_notify_cac_buffer_info, .register_internal_thermal_interrupt = vega10_register_thermal_interrupt, + .start_thermal_controller = vega10_start_thermal_controller, }; int vega10_hwmgr_init(struct pp_hwmgr *hwmgr) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h index 676cd7735883..b4b461c3b8ee 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h @@ -31,7 +31,6 @@ #include "vega10_ppsmc.h" #include "vega10_powertune.h" -extern const uint32_t PhwVega10_Magic; #define VEGA10_MAX_HARDWARE_POWERLEVELS 2 #define WaterMarksExist 1 diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c index d2f695692f77..598a194737a9 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c @@ -1243,8 +1243,8 @@ int vega10_enable_didt_config(struct pp_hwmgr *hwmgr) } if (0 == result) { - PP_ASSERT_WITH_CODE((!vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DIDT].smu_feature_bitmap)), - "[EnableDiDtConfig] Attempt to Enable DiDt feature Failed!", return result); + result = vega10_enable_smc_features(hwmgr, true, data->smu_features[GNLD_DIDT].smu_feature_bitmap); + PP_ASSERT_WITH_CODE((0 == result), "[EnableDiDtConfig] Attempt to Enable DiDt feature Failed!", return result); data->smu_features[GNLD_DIDT].enabled = true; } } @@ -1290,8 +1290,8 @@ int vega10_disable_didt_config(struct pp_hwmgr *hwmgr) } if (0 == result) { - PP_ASSERT_WITH_CODE((0 != vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DIDT].smu_feature_bitmap)), - "[DisableDiDtConfig] Attempt to Disable DiDt feature Failed!", return result); + result = vega10_enable_smc_features(hwmgr, false, data->smu_features[GNLD_DIDT].smu_feature_bitmap); + PP_ASSERT_WITH_CODE((0 == result), "[DisableDiDtConfig] Attempt to Disable DiDt feature Failed!", return result); data->smu_features[GNLD_DIDT].enabled = false; } } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c index e343df190375..f14c7611fad3 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c @@ -291,8 +291,7 @@ static int get_mm_clock_voltage_table( table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) * mm_dependency_table->ucNumEntries; - mm_table = (phm_ppt_v1_mm_clock_voltage_dependency_table *) - kzalloc(table_size, GFP_KERNEL); + mm_table = kzalloc(table_size, GFP_KERNEL); if (!mm_table) return -ENOMEM; @@ -519,8 +518,7 @@ static int get_socclk_voltage_dependency_table( sizeof(phm_ppt_v1_clock_voltage_dependency_record) * clk_dep_table->ucNumEntries; - clk_table = (phm_ppt_v1_clock_voltage_dependency_table *) - kzalloc(table_size, GFP_KERNEL); + clk_table = kzalloc(table_size, GFP_KERNEL); if (!clk_table) return -ENOMEM; @@ -554,8 +552,7 @@ static int get_mclk_voltage_dependency_table( sizeof(phm_ppt_v1_clock_voltage_dependency_record) * mclk_dep_table->ucNumEntries; - mclk_table = (phm_ppt_v1_clock_voltage_dependency_table *) - kzalloc(table_size, GFP_KERNEL); + mclk_table = kzalloc(table_size, GFP_KERNEL); if (!mclk_table) return -ENOMEM; @@ -596,8 +593,7 @@ static int get_gfxclk_voltage_dependency_table( sizeof(phm_ppt_v1_clock_voltage_dependency_record) * clk_dep_table->ucNumEntries; - clk_table = (struct phm_ppt_v1_clock_voltage_dependency_table *) - kzalloc(table_size, GFP_KERNEL); + clk_table = kzalloc(table_size, GFP_KERNEL); if (!clk_table) return -ENOMEM; @@ -663,8 +659,7 @@ static int get_pix_clk_voltage_dependency_table( sizeof(phm_ppt_v1_clock_voltage_dependency_record) * clk_dep_table->ucNumEntries; - clk_table = (struct phm_ppt_v1_clock_voltage_dependency_table *) - kzalloc(table_size, GFP_KERNEL); + clk_table = kzalloc(table_size, GFP_KERNEL); if (!clk_table) return -ENOMEM; @@ -728,8 +723,7 @@ static int get_dcefclk_voltage_dependency_table( sizeof(phm_ppt_v1_clock_voltage_dependency_record) * num_entries; - clk_table = (struct phm_ppt_v1_clock_voltage_dependency_table *) - kzalloc(table_size, GFP_KERNEL); + clk_table = kzalloc(table_size, GFP_KERNEL); if (!clk_table) return -ENOMEM; @@ -772,8 +766,7 @@ static int get_pcie_table(struct pp_hwmgr *hwmgr, sizeof(struct phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; - pcie_table = (struct phm_ppt_v1_pcie_table *) - kzalloc(table_size, GFP_KERNEL); + pcie_table = kzalloc(table_size, GFP_KERNEL); if (!pcie_table) return -ENOMEM; @@ -1026,10 +1019,9 @@ static int get_vddc_lookup_table( table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; - table = (phm_ppt_v1_voltage_lookup_table *) - kzalloc(table_size, GFP_KERNEL); + table = kzalloc(table_size, GFP_KERNEL); - if (NULL == table) + if (table == NULL) return -ENOMEM; table->count = vddc_lookup_pp_tables->ucNumEntries; @@ -1138,12 +1130,12 @@ int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v2_information), GFP_KERNEL); - PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable), + PP_ASSERT_WITH_CODE((hwmgr->pptable != NULL), "Failed to allocate hwmgr->pptable!", return -ENOMEM); powerplay_table = get_powerplay_table(hwmgr); - PP_ASSERT_WITH_CODE((NULL != powerplay_table), + PP_ASSERT_WITH_CODE((powerplay_table != NULL), "Missing PowerPlay Table!", return -1); result = check_powerplay_tables(hwmgr, powerplay_table); @@ -1182,7 +1174,6 @@ int vega10_pp_tables_initialize(struct pp_hwmgr *hwmgr) static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) { - int result = 0; struct phm_ppt_v2_information *pp_table_info = (struct phm_ppt_v2_information *)(hwmgr->pptable); @@ -1225,7 +1216,7 @@ static int vega10_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) kfree(hwmgr->pptable); hwmgr->pptable = NULL; - return result; + return 0; } const struct pp_table_func vega10_pptable_funcs = { @@ -1238,7 +1229,7 @@ int vega10_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) const ATOM_Vega10_State_Array *state_arrays; const ATOM_Vega10_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); - PP_ASSERT_WITH_CODE((NULL != pp_table), + PP_ASSERT_WITH_CODE((pp_table != NULL), "Missing PowerPlay Table!", return -1); PP_ASSERT_WITH_CODE((pp_table->sHeader.format_revision >= ATOM_Vega10_TABLE_REVISION_VEGA10), diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c index 1feefac49ea9..dc3761bcb9b6 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c @@ -365,8 +365,8 @@ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr) temp = cgs_read_register(hwmgr->device, reg); - temp = (temp & CG_MULT_THERMAL_STATUS__ASIC_MAX_TEMP_MASK) >> - CG_MULT_THERMAL_STATUS__ASIC_MAX_TEMP__SHIFT; + temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >> + CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT; temp = temp & 0x1ff; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h index f34ce04cfd89..82f10bdd5f07 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h @@ -71,7 +71,8 @@ extern int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, extern int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr); extern int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr); - +extern int vega10_start_thermal_controller(struct pp_hwmgr *hwmgr, + struct PP_TemperatureRange *range); extern uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr); #endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h index 435da2647727..95932cc88460 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -33,8 +33,6 @@ extern const struct amd_ip_funcs pp_ip_funcs; extern const struct amd_pm_funcs pp_dpm_funcs; -#define PP_DPM_DISABLED 0xCCCC - enum amd_pp_sensors { AMDGPU_PP_SENSOR_GFX_SCLK = 0, AMDGPU_PP_SENSOR_VDDNB, @@ -268,16 +266,12 @@ struct pp_display_clock_request { state << PP_STATE_SHIFT) struct amd_powerplay { + struct cgs_device *cgs_device; void *pp_handle; const struct amd_ip_funcs *ip_funcs; const struct amd_pm_funcs *pp_funcs; }; -int amd_powerplay_create(struct amd_pp_init *pp_init, - void **handle); - -int amd_powerplay_destroy(void *handle); - int amd_powerplay_reset(void *handle); int amd_powerplay_display_configuration_change(void *handle, @@ -310,6 +304,5 @@ int amd_powerplay_display_clock_voltage_request(void *handle, int amd_powerplay_get_display_mode_validation_clocks(void *handle, struct amd_pp_simple_clock_info *output); -int amd_set_clockgating_by_smu(void *handle, uint32_t msg_id); #endif /* _AMD_POWERPLAY_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h b/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h deleted file mode 100644 index 8a31665321a8..000000000000 --- a/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h +++ /dev/null @@ -1,10299 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _FIJI_PWRVIRUS_H_ -#define _FIJI_PWRVIRUS_H_ - -#define mmCP_HYP_MEC1_UCODE_ADDR 0xf81a -#define mmCP_HYP_MEC1_UCODE_DATA 0xf81b -#define mmCP_HYP_MEC2_UCODE_ADDR 0xf81c -#define mmCP_HYP_MEC2_UCODE_DATA 0xf81d - -enum PWR_Command -{ - PwrCmdNull = 0, - PwrCmdWrite, - PwrCmdEnd, - PwrCmdMax -}; -typedef enum PWR_Command PWR_Command; - -struct PWR_Command_Table -{ - PWR_Command command; - ULONG data; - ULONG reg; -}; -typedef struct PWR_Command_Table PWR_Command_Table; - -#define PWR_VIRUS_TABLE_SIZE 10243 -static const PWR_Command_Table PwrVirusTable[PWR_VIRUS_TABLE_SIZE] = -{ - { PwrCmdWrite, 0x100100b6, mmPCIE_INDEX }, - { PwrCmdWrite, 0x00000000, mmPCIE_DATA }, - { PwrCmdWrite, 0x100100b6, mmPCIE_INDEX }, - { PwrCmdWrite, 0x0300078c, mmPCIE_DATA }, - { PwrCmdWrite, 0x00000000, mmBIF_CLK_CTRL }, - { PwrCmdWrite, 0x00000001, mmBIF_CLK_CTRL }, - { PwrCmdWrite, 0x00000000, mmBIF_CLK_CTRL }, - { PwrCmdWrite, 0x00000003, mmBIF_FB_EN }, - { PwrCmdWrite, 0x00000000, mmBIF_FB_EN }, - { PwrCmdWrite, 0x00000001, mmBIF_DOORBELL_APER_EN }, - { PwrCmdWrite, 0x00000000, mmBIF_DOORBELL_APER_EN }, - { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX }, - { PwrCmdWrite, 0x00000000, mmPCIE_DATA }, - { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX }, - { PwrCmdWrite, 0x22000000, mmPCIE_DATA }, - { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX }, - { PwrCmdWrite, 0x00000000, mmPCIE_DATA }, - /* - { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION }, - { PwrCmdWrite, 0x00000000, mmMC_CITF_CNTL }, - { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION }, - { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION }, - { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION }, - { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION }, - { PwrCmdWrite, 0x00000000, mmMC_VM_FB_OFFSET },*/ - { PwrCmdWrite, 0x00000000, mmRLC_CSIB_ADDR_LO }, - { PwrCmdWrite, 0x00000000, mmRLC_CSIB_ADDR_HI }, - { PwrCmdWrite, 0x00000000, mmRLC_CSIB_LENGTH }, - /* - { PwrCmdWrite, 0x00000000, mmMC_VM_MX_L1_TLB_CNTL }, - { PwrCmdWrite, 0x00000001, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR }, - { PwrCmdWrite, 0x00000000, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR }, - { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION }, - { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION },*/ - { PwrCmdWrite, 0x00000000, mmVM_CONTEXT0_CNTL }, - { PwrCmdWrite, 0x00000000, mmVM_CONTEXT1_CNTL }, - /* - { PwrCmdWrite, 0x00000000, mmMC_VM_AGP_BASE }, - { PwrCmdWrite, 0x00000002, mmMC_VM_AGP_BOT }, - { PwrCmdWrite, 0x00000000, mmMC_VM_AGP_TOP },*/ - { PwrCmdWrite, 0x04000000, mmATC_VM_APERTURE0_LOW_ADDR }, - { PwrCmdWrite, 0x0400ff20, mmATC_VM_APERTURE0_HIGH_ADDR }, - { PwrCmdWrite, 0x00000002, mmATC_VM_APERTURE0_CNTL }, - { PwrCmdWrite, 0x0000ffff, mmATC_VM_APERTURE0_CNTL2 }, - { PwrCmdWrite, 0x00000001, mmATC_VM_APERTURE1_LOW_ADDR }, - { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_HIGH_ADDR }, - { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_CNTL }, - { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_CNTL2 }, - //{ PwrCmdWrite, 0x00000000, mmMC_ARB_RAMCFG }, - { PwrCmdWrite, 0x12011003, mmGB_ADDR_CONFIG }, - { PwrCmdWrite, 0x00800010, mmGB_TILE_MODE0 }, - { PwrCmdWrite, 0x00800810, mmGB_TILE_MODE1 }, - { PwrCmdWrite, 0x00801010, mmGB_TILE_MODE2 }, - { PwrCmdWrite, 0x00801810, mmGB_TILE_MODE3 }, - { PwrCmdWrite, 0x00802810, mmGB_TILE_MODE4 }, - { PwrCmdWrite, 0x00802808, mmGB_TILE_MODE5 }, - { PwrCmdWrite, 0x00802814, mmGB_TILE_MODE6 }, - { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE7 }, - { PwrCmdWrite, 0x00000004, mmGB_TILE_MODE8 }, - { PwrCmdWrite, 0x02000008, mmGB_TILE_MODE9 }, - { PwrCmdWrite, 0x02000010, mmGB_TILE_MODE10 }, - { PwrCmdWrite, 0x06000014, mmGB_TILE_MODE11 }, - { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE12 }, - { PwrCmdWrite, 0x02400008, mmGB_TILE_MODE13 }, - { PwrCmdWrite, 0x02400010, mmGB_TILE_MODE14 }, - { PwrCmdWrite, 0x02400030, mmGB_TILE_MODE15 }, - { PwrCmdWrite, 0x06400014, mmGB_TILE_MODE16 }, - { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE17 }, - { PwrCmdWrite, 0x0040000c, mmGB_TILE_MODE18 }, - { PwrCmdWrite, 0x0100000c, mmGB_TILE_MODE19 }, - { PwrCmdWrite, 0x0100001c, mmGB_TILE_MODE20 }, - { PwrCmdWrite, 0x01000034, mmGB_TILE_MODE21 }, - { PwrCmdWrite, 0x01000024, mmGB_TILE_MODE22 }, - { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE23 }, - { PwrCmdWrite, 0x0040001c, mmGB_TILE_MODE24 }, - { PwrCmdWrite, 0x01000020, mmGB_TILE_MODE25 }, - { PwrCmdWrite, 0x01000038, mmGB_TILE_MODE26 }, - { PwrCmdWrite, 0x02c00008, mmGB_TILE_MODE27 }, - { PwrCmdWrite, 0x02c00010, mmGB_TILE_MODE28 }, - { PwrCmdWrite, 0x06c00014, mmGB_TILE_MODE29 }, - { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE30 }, - { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE31 }, - { PwrCmdWrite, 0x000000a8, mmGB_MACROTILE_MODE0 }, - { PwrCmdWrite, 0x000000a4, mmGB_MACROTILE_MODE1 }, - { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE2 }, - { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE3 }, - { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE4 }, - { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE5 }, - { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE6 }, - { PwrCmdWrite, 0x00000000, mmGB_MACROTILE_MODE7 }, - { PwrCmdWrite, 0x000000ee, mmGB_MACROTILE_MODE8 }, - { PwrCmdWrite, 0x000000ea, mmGB_MACROTILE_MODE9 }, - { PwrCmdWrite, 0x000000e9, mmGB_MACROTILE_MODE10 }, - { PwrCmdWrite, 0x000000e5, mmGB_MACROTILE_MODE11 }, - { PwrCmdWrite, 0x000000e4, mmGB_MACROTILE_MODE12 }, - { PwrCmdWrite, 0x000000e0, mmGB_MACROTILE_MODE13 }, - { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE14 }, - { PwrCmdWrite, 0x00000000, mmGB_MACROTILE_MODE15 }, - { PwrCmdWrite, 0x00900000, mmHDP_NONSURFACE_BASE }, - { PwrCmdWrite, 0x00008000, mmHDP_NONSURFACE_INFO }, - { PwrCmdWrite, 0x3fffffff, mmHDP_NONSURFACE_SIZE }, - { PwrCmdWrite, 0x00000003, mmBIF_FB_EN }, - //{ PwrCmdWrite, 0x00000000, mmMC_VM_FB_OFFSET }, - { PwrCmdWrite, 0x00000000, mmSRBM_CNTL }, - { PwrCmdWrite, 0x00020000, mmSRBM_CNTL }, - { PwrCmdWrite, 0x80000000, mmATC_VMID0_PASID_MAPPING }, - { PwrCmdWrite, 0x00000000, mmATC_VMID_PASID_MAPPING_UPDATE_STATUS }, - { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, - { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, - { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, - { PwrCmdWrite, 0xe0000000, mmGRBM_GFX_INDEX }, - { PwrCmdWrite, 0x00000000, mmCGTS_TCC_DISABLE }, - { PwrCmdWrite, 0x00000000, mmTCP_ADDR_CONFIG }, - { PwrCmdWrite, 0x000000ff, mmTCP_ADDR_CONFIG }, - { PwrCmdWrite, 0x76543210, mmTCP_CHAN_STEER_LO }, - { PwrCmdWrite, 0xfedcba98, mmTCP_CHAN_STEER_HI }, - { PwrCmdWrite, 0x00000000, mmDB_DEBUG2 }, - { PwrCmdWrite, 0x00000000, mmDB_DEBUG }, - { PwrCmdWrite, 0x00002b16, mmCP_QUEUE_THRESHOLDS }, - { PwrCmdWrite, 0x00006030, mmCP_MEQ_THRESHOLDS }, - { PwrCmdWrite, 0x01000104, mmSPI_CONFIG_CNTL_1 }, - { PwrCmdWrite, 0x98184020, mmPA_SC_FIFO_SIZE }, - { PwrCmdWrite, 0x00000001, mmVGT_NUM_INSTANCES }, - { PwrCmdWrite, 0x00000000, mmCP_PERFMON_CNTL }, - { PwrCmdWrite, 0x01180000, mmSQ_CONFIG }, - { PwrCmdWrite, 0x00000000, mmVGT_CACHE_INVALIDATION }, - { PwrCmdWrite, 0x00000000, mmSQ_THREAD_TRACE_BASE }, - { PwrCmdWrite, 0x0000df80, mmSQ_THREAD_TRACE_MASK }, - { PwrCmdWrite, 0x02249249, mmSQ_THREAD_TRACE_MODE }, - { PwrCmdWrite, 0x00000000, mmPA_SC_LINE_STIPPLE_STATE }, - { PwrCmdWrite, 0x00000000, mmCB_PERFCOUNTER0_SELECT1 }, - { PwrCmdWrite, 0x06000100, mmCGTT_VGT_CLK_CTRL }, - { PwrCmdWrite, 0x00000007, mmPA_CL_ENHANCE }, - { PwrCmdWrite, 0x00000001, mmPA_SC_ENHANCE }, - { PwrCmdWrite, 0x00ffffff, mmPA_SC_FORCE_EOV_MAX_CNTS }, - { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000010, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000020, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000030, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000040, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000050, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000060, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000070, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000080, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000090, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x000000a0, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x000000b0, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x000000c0, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x000000d0, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x000000e0, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x000000f0, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmRLC_PG_CNTL }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS2 }, - { PwrCmdWrite, 0x15000000, mmCP_ME_CNTL }, - { PwrCmdWrite, 0x50000000, mmCP_MEC_CNTL }, - { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x0000000e, mmSH_MEM_APE1_BASE }, - { PwrCmdWrite, 0x0000020d, mmSH_MEM_APE1_LIMIT }, - { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, - { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_RB_VMID }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, - { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, - { PwrCmdWrite, 0x00000000, mmRLC_SRM_CNTL }, - { PwrCmdWrite, 0x00000002, mmRLC_SRM_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_ME_CNTL }, - { PwrCmdWrite, 0x15000000, mmCP_ME_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL }, - { PwrCmdWrite, 0x50000000, mmCP_MEC_CNTL }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x0840800a, mmCP_RB0_CNTL }, - { PwrCmdWrite, 0xf30fff0f, mmTCC_CTRL }, - { PwrCmdWrite, 0x00000002, mmTCC_EXE_DISABLE }, - { PwrCmdWrite, 0x000000ff, mmTCP_ADDR_CONFIG }, - { PwrCmdWrite, 0x540ff000, mmCP_CPC_IC_BASE_LO }, - { PwrCmdWrite, 0x000000b4, mmCP_CPC_IC_BASE_HI }, - { PwrCmdWrite, 0x00010000, mmCP_HYP_MEC1_UCODE_ADDR }, - { PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00221408, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00591260, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00621387, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00010000, mmCP_HYP_MEC2_UCODE_ADDR }, - { PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00221408, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00591260, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00621387, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x540fe800, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e020201, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e040204, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e060205, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54106f00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000400b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00004000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00804fac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x540fef00, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0xc0031502, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00001e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x540ff000, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000145, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080061, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24ccffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3cd08000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1cd0ffcf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x050c0019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x84c00000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000067, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000006a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000006d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000008f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000099, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800000a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800000af, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x388c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08880002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98800003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000002d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d808001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc0700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0d000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000005d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d00011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01b10, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x280c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x280c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x280c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca88004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc00006f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28180080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd4c0380, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdcc0388, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55dc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdcc038c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce0c0390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce0c0394, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4c0398, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4c039c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce8c03a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56a80020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce8c03a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcecc03a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcecc03ac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0c03b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0c03b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4c03b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4c03bc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8c03c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57b80020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8c03c4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfcc03c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57fc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfcc03cc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05dc002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc12009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d200a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc012009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25e01c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25e40300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25e800c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25ec003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e25c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31100006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4df0388, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d7038c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d5dc01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4e30390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d70394, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d62001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4e70398, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d7039c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d66401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4eb03a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d6a801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ef03a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703ac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d6ec01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4f303b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d73001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4f703b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703bc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d77401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4fb03c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703c4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d7b801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ff03c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703cc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d7fc01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d70380, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0e0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0085, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc006a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400051, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04180018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aac0027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04080002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000367, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9880fff3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04080010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80c0309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80c0319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9880fffc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d4001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x155c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e80180, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900091a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280196, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d4fe04, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800001b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000032b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000350, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000352, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000035f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000047c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000019f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d98001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0044, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9400036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840006d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11540015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1998003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af0007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15dc000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d65400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a38003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd5c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7df1c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800045, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411326a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc415326b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000056, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00059, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c8000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40005a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29988000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000073, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00005f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26f00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15100010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af07fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04343000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf413267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd1c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0160, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc810001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b4c0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f4f400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55180020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af4007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33740003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ae8003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413348, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x958000d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000315, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04303000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1714000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25540800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x459801b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d77400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c01e2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e5c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1334e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01334f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413350, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813351, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd881334d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153274, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cdcc011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05900008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00006a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0006b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d594002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc12e23, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd012e24, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc12e25, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b340057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b280213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980198, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20cc003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01e0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2d540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x078c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001239, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04f80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd5c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840007c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c018a6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e22, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800007c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c018a2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd4c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680fffc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540188f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc013cfff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x38d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdcc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01882, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000304, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x49980198, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x459801a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000329, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16ec001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1998003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce00000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a18003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24dc00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31e00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95801827, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14dc0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800006d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a0000ad, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af4003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca88005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24880001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f4b4009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313274, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d33400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1eecffdd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800003c3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa80030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a8004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e80042, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e8e800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de9c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce8c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd30011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11e80007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd300001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240059, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1660001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e320009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0328000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e72400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0430000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02ac000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d310002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa87600, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280222, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4280058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x22ec003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8380018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57b00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04343108, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2374007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32a80003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800003e7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980104, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x49980104, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800003f2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf41326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x254c0700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a641fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0726, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a640200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1237b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8813260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4280034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01755, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde830000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0174c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bb80040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100044, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19180024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x551c003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000043d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c8000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840006c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28200000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000043f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282000f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195c00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5e124dc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e624001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980158, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x49980158, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980170, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16200010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1154000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e80488, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f807f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e40077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ec0199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000048e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000494, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000685, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000686, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800006ac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ccc001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1264000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d79400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e7a400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52a8001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec0028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004cc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419324e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26e8003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d324d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d290004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f8f4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f52800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50e00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004d1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0dc002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f534002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004d7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3257, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e804e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004e7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000505, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640fff4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26edf000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05a80507, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000050c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000528, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000057d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800005c2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800005f3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1be00fe4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000066, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ed6c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113271, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193272, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d51401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253276, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400061, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2730000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7db1800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00062, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000063, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400065, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b680213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46ec0188, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26e01000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c131fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x192007ec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x69dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de20014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x561c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013344, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13345, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2010007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2010003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013344, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013345, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280042, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00124f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46ec0190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2154003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bd800e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f598004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1be800e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801327a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800005f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xda000068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540002d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1be000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc63124dc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fc14001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000697, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25100007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31100005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900008e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a9feff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d30b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00ac006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28880700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0006de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30d4000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41530b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19980028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800006c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8380023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa38011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd3800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202400d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000712, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e80714, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000071c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000720, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000747, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000071d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800007c4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000732, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000745, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000744, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a64008c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0fff1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000723, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41f02f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000743, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffde, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc8000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195800e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dd7fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1a001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46200200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04283247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af80057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af40213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6f400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc6990000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x329c325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x329c3269, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x329c3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01defff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d8009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000078a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fff2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03e7ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3f0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03e4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d30b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bf0003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000b80, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x203c003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46200008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31980002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19580066, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0120001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11980003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da18001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d24db, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580137b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00ee000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113269, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19080070, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x190c00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2518000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05a80809, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000080e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000080f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000898, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000946, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800009e1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04a80811, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000815, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000834, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3045, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c091, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000241, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02f0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4252087, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5668001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00021d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001a41, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43b02f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56f00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x950001fa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aec0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a40006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de6000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10e40008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2110003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10ff9e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0245301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0121fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29108eff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0127ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0131fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0100010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd2400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0180003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd1c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04a8089a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000089e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800008fa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31300022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x964012a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02620c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000903, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31240022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ec30011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32f80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x67180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bfc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd981325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000915, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c1325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0fff6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f818001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001606, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d838001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16240014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a2801f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00075e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f40014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33e80010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680ffec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04a80948, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000094c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000099b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x964011fe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dda801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e838011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001802, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x469c0390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4280011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0014df, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31280014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce8802ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800062, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31280034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04a809e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800009ec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a45, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e72401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04383000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b38007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4598001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4002eb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4002ec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4002ed, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4002ee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001715, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffbc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a55, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x233c0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49302ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5198001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193269, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53b8001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7db9801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01106, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c010fd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce4c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc80c0072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x58e801fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc01e2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e5c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x44cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55900020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x44cc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd812e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd012e02, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd412e03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1e64001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ab1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a0010ac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd880003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d403f7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41b0367, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d85800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280adc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000af1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000adf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ae7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd8d2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d803f7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11940014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29544001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29544003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000af4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd44d2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd44dc000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd8d2c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000b0a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd44d2c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28148004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4593240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0105e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef3400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14e80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a8000af, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a01fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3620005c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2464003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc6290ce7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16ac001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ac003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ee6c00d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00fff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000367, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640102e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c0037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a00035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0005d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16f8001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9780000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc035f0ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e764009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19b401f8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ae4003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000b7c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a4003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc01e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13fc0018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dbd800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d98ff15, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x592c00fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd80000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12e00016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x592c007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12e00015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1264001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1620000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12e4001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5924007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013257, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00fdb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9780f5ca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07740003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x269c003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e4004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f67000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f674002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab8c006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000bec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000b47, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a8004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc415325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18580037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x262001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d54001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd280200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd680208, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcda80210, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc6930200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc6970208, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc69b0210, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd900003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd940003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9400040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14fc0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24f800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d83c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24e000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x321c0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580ffee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c30, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9480000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800f29, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800f23, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800f1a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9600f502, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0f500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000f05, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16e4001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640f4f4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33740002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40f4f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00ac005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc8000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28884900, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ff3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400ee1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c40a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c40c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c40d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d0007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15580010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x255400ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c411, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c40f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c40e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c410, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e80033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ec0034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c414, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c415, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c413, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c030011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c038011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431c417, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435c416, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c419, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc418, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf413261, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013262, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13263, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813264, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc0030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d77000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51b80020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f97801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ca7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc0031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435c40b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4280032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000cf4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc032800b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d42011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800e6c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x596001fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce0c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x505c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e800c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x122c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d1f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d57, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0328009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04143000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e51001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d2d0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19640057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19580213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19600199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da6400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04142000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d80034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280d83, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d8a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000db1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000dbc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e010001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d75400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580f3d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x526c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2ec01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5ae0073a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580f3c6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc3a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fff5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01c405, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd441c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580f3b1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580f3a5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00da7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5aac007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12d80017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56a00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e82400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e58c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19d4003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20880188, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20240090, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ac0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ac0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0001a2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2220003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18fc0034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24e8000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80e71, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000edd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ea1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000eaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e7c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e87, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e8f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9e001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213262, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253261, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213264, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253263, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e82005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8180072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x59a001fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421c401, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c401, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ede, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db09001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db09011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5a10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5a50000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280eea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f11, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f2e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f1f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0f26f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7daec01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5af8073a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eba800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0f25c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c405, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0f24e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40f247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0f240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ef2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db09002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db09012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c034001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c038001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f88, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e52401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1334000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24e02000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f63400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f9d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51e40020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13380016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e00039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1220001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31140005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31140006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280fb7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28140002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fc2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fd1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e80039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52a8003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140004b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x159c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31a00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31a40001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e25800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0fff5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fff4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d100010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0340008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x208801a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000102f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1cccfe08, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00b33, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da2400f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da28002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1ac002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d2ac002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3ef40010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40f11d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde410000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde010000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c024001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100086, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5510003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001075, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d520002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cde0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e20001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001071, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00b01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc200000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc40003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a400e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12500009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x248c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x200c006d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x200c0228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18881fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d4072c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc00d1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3094000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x38d80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x311c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30940007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1620001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010c4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a00030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c0fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000aac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07a810d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000104c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x200c007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x192400fd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06681110, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19180070, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19100078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f40058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001117, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001118, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000112d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001130, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001133, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02a0200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e8e8009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x22a8003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x22a80074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2774001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13740014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eb6800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25ecffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55700020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15f40010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13740002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x275c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc1c01e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e62000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001165, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1a0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e0d000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e02401e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05d80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc2401e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da2000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9600ffe6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce00001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x22640435, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0528117e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x312c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001185, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a0400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d81c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de2c00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011a3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d654001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c020001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2730003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3b380006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3f38000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0430000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb10004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e57000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e578002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d67c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0be40001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d3a4002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e640010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07a811cf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00feb8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x954009a7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f0012f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f40612, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc00c1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cf7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39600004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0140004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18fc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011ee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a6c003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ac007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab00030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aac0fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001205, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a2800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30d00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640090f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19180038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab0c006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000127f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313257, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab0c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f67800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0012e1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x964008d7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9800036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300677, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012aa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a8002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7edec00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1858003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0cc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d407f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d5d4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d52000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d514002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d958001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd5c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ccc001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd980003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9800040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800051, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b74003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50700020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04e81324, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d71401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x596401fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b74008d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a640000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000132c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000133b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001344, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42530b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a68003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2024003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11980014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d19000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8240011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffe0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c007eb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0d001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x591c01fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45140210, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x595801fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11980009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a307fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x23304076, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4514020c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a2001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a204001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a64003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15dc000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dcdc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5dc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45140248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013257, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0434000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdb000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0337fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f220009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d01c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f01c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8240072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd240001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19682011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5a6c01fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eeac00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfa0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d40038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540073d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18c80066, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30880001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4220000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24e80007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24ec0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5310000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001465, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f02011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5aec01fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a8146a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1f0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f334002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e024001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000144a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fbfc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800014a9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0328007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c428001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c430001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a0800fd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x109c000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce080228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9880000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0ec75, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52a80020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc80260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80288, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf080290, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0802a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4802a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc802b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80802b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x178c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b8003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cf8c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8802c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc802c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8802d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8802d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25b8ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd2800c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5230309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e3a400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001539, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd880353, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b0353, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd14005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000154f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd080238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d200008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd900309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd910ce7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4190ce6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d918005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d918004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd810ce6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdd1054f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000156e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x090c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdcd050e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x110c0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41230a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41230b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41230c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41230d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc480329, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc48032a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc4802e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09940001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x44100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x69100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000157f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970290, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b0288, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49f0298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dcdc002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d924019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d26400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001579, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d010021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d914019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd480298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd8802a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10d40010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12180016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc51f0309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d95800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d62000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdd00309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce113320, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc01e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9400e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015aa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a302b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab02a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4c0319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d8002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea14005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015bc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d25000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fff4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd0d3330, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce0802b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd8802b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab02e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa807f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f02d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49702d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49f02c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d4e000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9600000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d964002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cde4002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de94001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd64002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015cd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d698002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd4802d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x129c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc50f0319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a0000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1198000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd953300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e0e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a8000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce953301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce100319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b70280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x536c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9780eb68, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001609, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30b40000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b70258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53780020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb3801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7faf8019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x67b40001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bb0260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fab8001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf880260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66f40001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7f4009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fff7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x269c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a00018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a00060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x269c0018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a40060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b70228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f514005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001644, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd080240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f130005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001688, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f130004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01051e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d051f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ed2c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c0fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01051f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5170309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195c07f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x196007f6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x6b740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001665, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a702a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab0298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f634014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8113320, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce480298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce8802a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5170319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b702b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x255c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f5f4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8113330, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4802b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11340001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195c07e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x196007ee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8353300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1e4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8353301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4802d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8100309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd4c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x64d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580005c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd2000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7df5c00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800016f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a7003e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a700064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800016df, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800016f2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18fc0064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00042, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf0258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53fc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e7e401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x667c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eebc00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x43300007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7db30011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd3000025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03ec005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfca200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x203c003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0017f5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18fc01e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00185b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40ffd5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0ea24, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d4001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d52400e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49f0258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a30250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d534002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dae4005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000174f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00178a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40fff3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab0268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7daa4005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32a0001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001765, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0017f2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b3034b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f13000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001855, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32a4001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd080260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce880268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ffc0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ec28001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e72400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680fff7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa4003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32680003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa400e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017e2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc027ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2e6400ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a4009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e403e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26680003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e40064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea64002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4292083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea68005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a400ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2024007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a70280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab0278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae8014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce480278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce880280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43b02eb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42302ec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa3801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x47b8020c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1220000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a206032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x513c001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e3e001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000180f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b3c0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd200000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd3800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc30001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc413248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3269, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33fc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bfc0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd441326a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x173c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3f0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001842, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x23fc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd441326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1fb8ffc6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xddc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001852, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49f02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41f02ed, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42302ee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2a0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x313c0bcc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x393c051f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d3c050e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x393c0560, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d3c054f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x393c1538, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d3c1537, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e8007c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a8189a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800018c5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800018f2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09240002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a24002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14cc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd8c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce0130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bb80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9600e8a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640e8a5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800018a9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dad800c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffd2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fff9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x442c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940fff1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26240007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940fff7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc023007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e4003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dee000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x261c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940fff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e00064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06281911, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001915, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800019af, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a2b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc48032b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc480333, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc48033b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc480343, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98800011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b3c0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e3e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a1c003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00065, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1e0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800062, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x43bc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fcbc001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc7df032b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1fc00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0101, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001994, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001982, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffcb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001995, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x41bc0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53fc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e7fc011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd3c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x653c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dbd8001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ff8f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d91800c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580005d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a70003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33240003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a7000e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a21, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f270009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x266400ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27240003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a0f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e730002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4252083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x267000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a22, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ff9f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001a31, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b180057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1a000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30f00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800056, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001aa2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a90, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001aa3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4664001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x244c00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc4c0200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc44f0200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d158010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x059cc000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccdd0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500e69a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d40021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0120840, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282c0040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001ae8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0121841, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282c001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940e66b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00047, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d003ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d47fea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d87ff4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40004e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd80004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c405, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x295c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11980002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4110000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0160800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0164010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400048, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c40a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901c40d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c410, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c40e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c40f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140096, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411c401, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11100002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c40c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0180034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c411, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841c414, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2468000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419c416, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x41980003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dda0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c40c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901c411, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c412, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce292e40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc120000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31144000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc3c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9780e601, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x188cfff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04e40002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b74, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x54106500, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e020204, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00a0505, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf8c007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb8900904, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb8911a04, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb8920304, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb8930b44, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921c0d0c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921c1c13, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921d0c12, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x811c1d1c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x811c111c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921cff1c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921dff10, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x81181d1c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e040218, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x54106900, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0x7e080200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e100204, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbefc00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00010000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24200087, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x262200ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000001f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20222282, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28182111, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x54116f00, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54116f00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb454105e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54117300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4541065, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54117700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4541069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000444, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000008a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54117b00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL }, - { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x54116f00, mmCP_MQD_BASE_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, - { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x54117300, mmCP_MQD_BASE_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, - { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x54117700, mmCP_MQD_BASE_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, - { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x54117b00, mmCP_MQD_BASE_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, - { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000104, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000204, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000304, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000404, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000504, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000604, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000704, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000105, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000205, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000305, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000405, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000505, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000605, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000705, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000106, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000206, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000306, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000406, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000506, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000606, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000706, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000107, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000207, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000307, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000407, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000507, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000607, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000707, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000008, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000108, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000208, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000308, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000408, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000508, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000608, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000708, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000009, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000109, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000209, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000309, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000409, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000509, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000609, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000709, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x01010101, mmCP_PQ_WPTR_POLL_CNTL1 }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdEnd, 0x00000000, 0x00000000 }, -}; - -#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h index 126b44d47a99..004a40e88bde 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -363,6 +363,12 @@ struct pp_hwmgr_func { int (*set_active_display_count)(struct pp_hwmgr *hwmgr, uint32_t count); int (*set_deep_sleep_dcefclk)(struct pp_hwmgr *hwmgr, uint32_t clock); int (*start_thermal_controller)(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *range); + int (*notify_cac_buffer_info)(struct pp_hwmgr *hwmgr, + uint32_t virtual_addr_low, + uint32_t virtual_addr_hi, + uint32_t mc_addr_low, + uint32_t mc_addr_hi, + uint32_t size); }; struct pp_table_func { diff --git a/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h b/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h index 0de443612312..6a53b7e74ccd 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h +++ b/drivers/gpu/drm/amd/powerplay/inc/polaris10_pwrvirus.h @@ -29,10058 +29,1764 @@ #define mmCP_HYP_MEC2_UCODE_ADDR 0xf81c #define mmCP_HYP_MEC2_UCODE_DATA 0xf81d -enum PWR_Command { - PwrCmdNull = 0, - PwrCmdWrite, - PwrCmdEnd, - PwrCmdMax -}; - -typedef enum PWR_Command PWR_Command; - struct PWR_Command_Table { - PWR_Command command; uint32_t data; uint32_t reg; }; typedef struct PWR_Command_Table PWR_Command_Table; +struct PWR_DFY_Section { + uint32_t dfy_cntl; + uint32_t dfy_addr_hi, dfy_addr_lo; + uint32_t dfy_size; + uint32_t dfy_data[]; +}; + +typedef struct PWR_DFY_Section PWR_DFY_Section; + +static const PWR_Command_Table pwr_virus_table_pre[] = { + { 0x00000000, mmRLC_CNTL }, + { 0x00000002, mmRLC_SRM_CNTL }, + { 0x15000000, mmCP_ME_CNTL }, + { 0x50000000, mmCP_MEC_CNTL }, + { 0x80000004, mmCP_DFY_CNTL }, + { 0x0840800a, mmCP_RB0_CNTL }, + { 0xf30fff0f, mmTCC_CTRL }, + { 0x00000002, mmTCC_EXE_DISABLE }, + { 0x000000ff, mmTCP_ADDR_CONFIG }, + { 0x540ff000, mmCP_CPC_IC_BASE_LO }, + { 0x000000b4, mmCP_CPC_IC_BASE_HI }, + { 0x00010000, mmCP_HYP_MEC1_UCODE_ADDR }, + { 0x00041b75, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000710e8, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000910dd, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000a1081, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000b016f, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000c0e3c, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000d10ec, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000e0188, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00101b5d, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00150a6c, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00170c5e, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x001d0c8c, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x001e0cfe, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00221408, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00370d7b, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00390dcb, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x003c142f, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x003f0b27, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00400e63, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00500f62, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00460fa7, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00490fa7, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x005811d4, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00680ad6, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00760b00, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00780b0c, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00790af7, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x007d1aba, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x007e1abe, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00591260, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x005a12fb, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00861ac7, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x008c1b01, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x008d1b34, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a014b9, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a1152e, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a216fb, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a41890, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a31906, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00a50b14, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00621387, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x005c0b27, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00160a75, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { 0x00010000, mmCP_HYP_MEC2_UCODE_ADDR }, + { 0x00041b75, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000710e8, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000910dd, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000a1081, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000b016f, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000c0e3c, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000d10ec, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000e0188, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00101b5d, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00150a6c, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00170c5e, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x001d0c8c, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x001e0cfe, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00221408, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00370d7b, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00390dcb, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x003c142f, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x003f0b27, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00400e63, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00500f62, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00460fa7, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00490fa7, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x005811d4, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00680ad6, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00760b00, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00780b0c, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00790af7, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x007d1aba, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x007e1abe, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00591260, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x005a12fb, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00861ac7, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x008c1b01, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x008d1b34, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a014b9, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a1152e, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a216fb, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a41890, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a31906, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00a50b14, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00621387, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x005c0b27, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00160a75, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { 0x00000000, 0xFFFFFFFF }, +}; + +static const PWR_DFY_Section pwr_virus_section1 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x540fe800, + .dfy_data = { + 0x7e000200, 0x7e020201, 0x7e040204, 0x7e060205, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0x0a080102, 0x0a0a0701, 0x0a080102, 0x0a0a0701, + 0x0a080500, 0x0a0a0303, 0x0a080500, 0x0a0a0303, 0xbf810000, 0x00000000, 0x00000000, 0x00000000, + 0x00000005, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54106f00, 0x000400b4, 0x00004000, 0x00804fac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 416 +}; + +static const PWR_DFY_Section pwr_virus_section2 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x540fef00, + .dfy_data = { + 0xc0031502, 0x00001e00, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 16 +}; -#define PWR_VIRUS_TABLE_SIZE 10031 +static const PWR_DFY_Section pwr_virus_section3 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x540ff000, + .dfy_data = { + 0xc424000b, 0x80000145, 0x94800001, 0x94c00001, 0x95000001, 0x95400001, 0x95800001, 0xdc810000, + 0xdcc10000, 0xdd010000, 0xdd410000, 0xdd810000, 0xc4080061, 0xd8400013, 0xd8000003, 0xc40c0001, + 0x24ccffff, 0x3cd08000, 0x9500fffd, 0x1cd0ffcf, 0x7d018001, 0xc4140004, 0x050c0019, 0xd8400008, + 0x84c00000, 0x80000023, 0x80000067, 0x8000006a, 0x8000006d, 0x80000079, 0x80000084, 0x8000008f, + 0x80000099, 0x800000a0, 0x800000af, 0xd8400053, 0xc4080007, 0x388c0001, 0x08880002, 0x04100003, + 0x94c00005, 0x98800003, 0x04100004, 0x8000002d, 0x04100005, 0x8c00003f, 0x8c000043, 0x28cc0000, + 0xccc00050, 0x8c000055, 0x28080001, 0xcc000004, 0x7d808001, 0xd8400013, 0xd88130b8, 0xcd400008, + 0xdc180000, 0xdc140000, 0xdc100000, 0xdc0c0000, 0xcc800005, 0xdc080000, 0x80000168, 0xc40c000e, + 0x28cc0008, 0xccc00013, 0x90000000, 0xcd013278, 0xc4113278, 0x95000001, 0x24cc0700, 0xd8400029, + 0xc4113255, 0xcd01324f, 0xc4113254, 0x1d10ffdf, 0xcd013254, 0x10cc0014, 0x1d10c017, 0x7d0d000a, + 0xd8400013, 0xd8400008, 0xcd0130b7, 0x14cc0010, 0x90000000, 0xd9c00036, 0x8000005d, 0xd8400013, + 0xc00c4000, 0xccc130b5, 0xc40c000e, 0x28cc0008, 0xccc00013, 0xc40c0021, 0x14d00011, 0x9500fffe, + 0xdc030000, 0xd800000c, 0xd800000d, 0xc40c005e, 0x94c01b10, 0xd8400013, 0x90000000, 0xc00e0080, + 0xccc130b5, 0x8000013b, 0xc00e0800, 0xccc130b5, 0x8000013b, 0xd8400053, 0x04100006, 0x8c00003f, + 0x8c000043, 0x28cc0000, 0xccc00050, 0x8c000055, 0x280c0008, 0xccc00052, 0xd8000021, 0x28180039, + 0x80000034, 0xd8400053, 0x04100007, 0x8c00003f, 0x8c000043, 0x28cc0001, 0xccc00050, 0x8c000055, + 0x280c0010, 0xccc00052, 0x28180039, 0x80000034, 0xd8400053, 0x04100008, 0x8c00003f, 0x8c000043, + 0x28cc0003, 0xccc00050, 0x8c000055, 0x280c0020, 0xccc00052, 0x28180039, 0x80000034, 0xdc030000, + 0xd8000069, 0x28080001, 0xc428000d, 0x7ca88004, 0xcc800079, 0x04280001, 0xcc00006f, 0x8000013b, + 0x80000034, 0x04100010, 0x8c00003f, 0x8c000043, 0xccc00078, 0x8c000055, 0x28180080, 0x80000034, + 0x04100001, 0xc40c000e, 0x28cc0008, 0xccc00013, 0xcd013278, 0xc4113278, 0x95000001, 0xc00c4000, + 0xc4113254, 0x1d10c017, 0xd8400013, 0xd8400008, 0xccc130b5, 0xcd0130b7, 0x8000013b, 0x95c00001, + 0x96000001, 0x96400001, 0x96800001, 0x96c00001, 0x97000001, 0x97400001, 0x97800001, 0x97c00001, + 0xdc810000, 0xc40c000c, 0xcd4c0380, 0xcdcc0388, 0x55dc0020, 0xcdcc038c, 0xce0c0390, 0x56200020, + 0xce0c0394, 0xce4c0398, 0x56640020, 0xce4c039c, 0xce8c03a0, 0x56a80020, 0xce8c03a4, 0xcecc03a8, + 0x56ec0020, 0xcecc03ac, 0xcf0c03b0, 0x57300020, 0xcf0c03b4, 0xcf4c03b8, 0x57740020, 0xcf4c03bc, + 0xcf8c03c0, 0x57b80020, 0xcf8c03c4, 0xcfcc03c8, 0x57fc0020, 0xcfcc03cc, 0xd9000033, 0xc41c0009, + 0x25dc0010, 0x95c0fffe, 0xd8400013, 0xc41c000c, 0x05dc002f, 0xcdc12009, 0xc41d200a, 0xd8400013, + 0xcc012009, 0xd9000034, 0x25e01c00, 0x12200013, 0x25e40300, 0x12640008, 0x25e800c0, 0x12a80002, + 0x25ec003f, 0x7e25c00a, 0x7eae400a, 0x7de5c00a, 0xddc10000, 0xc02ee000, 0xcec1c200, 0xc40c005f, + 0xccc00037, 0x24d000ff, 0x31100006, 0x9500007b, 0x8c000190, 0xdc1c0000, 0xd8400013, 0xcdc1c200, + 0xc40c000c, 0xc4df0388, 0xc4d7038c, 0x51540020, 0x7d5dc01a, 0xc4e30390, 0xc4d70394, 0x51540020, + 0x7d62001a, 0xc4e70398, 0xc4d7039c, 0x51540020, 0x7d66401a, 0xc4eb03a0, 0xc4d703a4, 0x51540020, + 0x7d6a801a, 0xc4ef03a8, 0xc4d703ac, 0x51540020, 0x7d6ec01a, 0xc4f303b0, 0xc4d703b4, 0x51540020, + 0x7d73001a, 0xc4f703b8, 0xc4d703bc, 0x51540020, 0x7d77401a, 0xc4fb03c0, 0xc4d703c4, 0x51540020, + 0x7d7b801a, 0xc4ff03c8, 0xc4d703cc, 0x51540020, 0x7d7fc01a, 0xdc080000, 0xcc800013, 0xc4d70380, + 0xc4080001, 0x1c88001c, 0xcd400008, 0xc40c0083, 0x94c00010, 0xdc0e0000, 0x94c0000e, 0xc40c0082, + 0x24d00001, 0x9900000b, 0x18cc01e3, 0x3cd00004, 0x95000008, 0xc40c0085, 0x18cc006a, 0x98c00005, + 0xc40c0082, 0x18cc01e3, 0x3cd00004, 0x9900fffa, 0xdc180000, 0xdc140000, 0xdc100000, 0xdc0c0000, + 0xcc800004, 0xdc080000, 0x90000000, 0xc4080001, 0x1c88001c, 0xcd400008, 0xdc180000, 0xdc140000, + 0xdc100000, 0xdc0c0000, 0xcc800004, 0xdc080000, 0x90000000, 0xd8400051, 0xc428000c, 0x04180018, + 0x32640002, 0x9a80001f, 0x9a40001e, 0xcd800013, 0xc4293265, 0x040c0000, 0x1aac0027, 0x2aa80080, + 0xce813265, 0x9ac00017, 0xd80002f1, 0x04080002, 0x08880001, 0xd8080250, 0xd8080258, 0xd8080230, + 0xd8080238, 0xd8080240, 0xd8080248, 0xd8080268, 0xd8080270, 0xd8080278, 0xd8080280, 0xd8080228, + 0xd8000367, 0x9880fff3, 0x04080010, 0x08880001, 0xd80c0309, 0xd80c0319, 0x04cc0001, 0x9880fffc, + 0x7c408001, 0x88000000, 0xc00e0100, 0xd8400013, 0xd8400008, 0xccc130b5, 0x8000016e, 0xc4180032, + 0x29980008, 0xcd800013, 0x95800001, 0x7c40c001, 0x18d0003f, 0x24d4001f, 0x24d80001, 0x155c0001, + 0x05e80180, 0x9900000b, 0x202c003d, 0xcd800010, 0xcec1325b, 0xc42d325b, 0x96c00001, 0x86800000, + 0x80000168, 0x80000aa7, 0x80000bfc, 0x800012e9, 0xc4200007, 0x0a200001, 0xce000010, 0x80001b70, + 0x7c40c001, 0x8c000190, 0xc410001b, 0xd8000032, 0xd8000031, 0x9900091a, 0x7c408001, 0x88000000, + 0x24d000ff, 0x05280196, 0x18d4fe04, 0x29540008, 0xcd400013, 0x86800000, 0x800001b4, 0x8000032b, + 0x80000350, 0x80000352, 0x8000035f, 0x80000701, 0x8000047c, 0x8000019f, 0x80000800, 0xc419325b, + 0x1d98001f, 0xcd81325b, 0x8c00003f, 0xc4140004, 0xd8400008, 0x04100002, 0x8c000043, 0x28cc0002, + 0xccc00050, 0xc43c0044, 0x27fc0003, 0x9bc00002, 0x97c00006, 0xc00c4000, 0xccc130b5, 0x8c000055, + 0xd8400013, 0xd88130b8, 0xcd400008, 0x90000000, 0xd8400008, 0xcd400013, 0x7d40c001, 0xd8400028, + 0xd8400029, 0xd9400036, 0xc4193256, 0xc41d3254, 0x15540008, 0xcd400009, 0xcd40005b, 0xcd40005e, + 0xcd40005d, 0xd840006d, 0xc421325a, 0xc42d3249, 0x11540015, 0x19a4003c, 0x1998003f, 0x1af0007d, + 0x11dc000b, 0x1264001f, 0x15dc000d, 0x7d65400a, 0x13300018, 0x1a38003f, 0x7dd5c00a, 0x7df1c00a, + 0xcd800045, 0xcdc00100, 0xc411326a, 0xc415326b, 0xc419326c, 0xc41d326d, 0xc425326e, 0xc4293279, + 0xce800077, 0xcd000056, 0xcd400057, 0xcd800058, 0xcdc00059, 0xc4193265, 0x259c8000, 0x99c00004, + 0xce40005a, 0x29988000, 0xcd813265, 0xc4113248, 0x2510000f, 0xcd000073, 0xc418000d, 0xc411326f, + 0x17300019, 0x97000009, 0x25140fff, 0x95400007, 0xd800003a, 0x8c001b6d, 0xc4153279, 0xcd400077, + 0xcd00005f, 0xd8000075, 0x26f00001, 0x15100010, 0x7d190004, 0xcd000035, 0x97000035, 0x1af07fe8, + 0xd8800013, 0xd8400010, 0xd8400008, 0xcf00000d, 0xcf00000a, 0x8c001427, 0x04340022, 0x07740001, + 0x04300010, 0xdf430000, 0x7c434001, 0x7c408001, 0xd4412e01, 0x0434001e, 0xdf430000, 0xd4400078, + 0xdf030000, 0xd4412e40, 0xd8400013, 0xcc41c030, 0xcc41c031, 0xc43dc031, 0xccc00013, 0x04343000, + 0xc4113246, 0xc41d3245, 0xcf413267, 0x51100020, 0x7dd1c01a, 0xc4353267, 0x45dc0160, 0xc810001f, + 0x1b4c0057, 0x1b700213, 0x1b740199, 0x7f4f400a, 0x7f73400a, 0x55180020, 0x2198003f, 0xd1c00025, + 0xcf400024, 0xcd000026, 0xcd800026, 0xd8400027, 0x9bc00001, 0x248dfffe, 0xd8800013, 0xccc12e00, + 0x7c434001, 0x7c434001, 0x8c00142b, 0xc43c000e, 0x1af4007d, 0x2bfc0008, 0x33740003, 0x26d80001, + 0xcfc00013, 0x1ae8003e, 0x9680000c, 0xc4253277, 0x26680001, 0x96800009, 0x2a640002, 0xce413277, + 0xd8400013, 0xc4253348, 0xce413348, 0xc4253348, 0x96400001, 0xcfc00013, 0x9b400003, 0x958000d8, + 0x80000315, 0xc4253277, 0x04303000, 0x26680001, 0xcf013267, 0xc4193246, 0xc41d3245, 0xc4313267, + 0x96800041, 0x51980020, 0x1b342010, 0x7d9d801a, 0x1714000c, 0x25540800, 0x1b30c012, 0x459801b0, + 0x7d77400a, 0x7f37000a, 0x2b300000, 0xcf00001c, 0xd180001e, 0xd8400021, 0x04240010, 0x199c01e2, + 0x7e5e4002, 0x3e5c0004, 0x3e540002, 0xc428000f, 0x9a80ffff, 0x95c00006, 0xc80c0011, 0xc8140011, + 0x54d00020, 0x55580020, 0x80000282, 0x95400015, 0xc80c0011, 0x0a640002, 0x041c0001, 0x45980008, + 0x54d00020, 0x96400004, 0xc8140011, 0x45980004, 0x041c0000, 0xcf00001c, 0xd180001e, 0xd8400021, + 0xc428000f, 0x9a80ffff, 0x99c00003, 0xc8180011, 0x80000282, 0xc8140011, 0x55580020, 0x80000282, + 0x45980004, 0xc80c0011, 0xcf00001c, 0xd180001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc8100011, + 0xc8140011, 0x55580020, 0xd8400013, 0xccc1334e, 0xcd01334f, 0xcd413350, 0xcd813351, 0xd881334d, + 0xcfc00013, 0xc4193273, 0xc41d3275, 0xc40d3271, 0xc4113270, 0xc4153274, 0x50cc0020, 0x7cd0c01a, + 0x7cdcc011, 0x05900008, 0xcd00006a, 0xcdc0006b, 0xc41d3272, 0x7d594002, 0x54d00020, 0xd8800013, + 0xccc12e23, 0xcd012e24, 0xcdc12e25, 0xcfc00013, 0xc4193246, 0xc41d3245, 0xc4313267, 0x15540002, + 0x51980020, 0x7d9d801a, 0xc81c001f, 0x1b340057, 0x1b280213, 0x1b300199, 0x45980198, 0x7f37000a, + 0x7f2b000a, 0x55e40020, 0xcf000024, 0xd1800025, 0xcdc00026, 0xce400026, 0xd8400027, 0xcd40000d, + 0xcd40000a, 0xc40d3249, 0x20cc003c, 0xccc13249, 0xc4113274, 0xdd430000, 0xc01e0001, 0x29dc0002, + 0x04280000, 0xd8000036, 0xcc400078, 0xcc400078, 0x2d540002, 0x95400022, 0x078c0000, 0x07d40000, + 0x8c00120d, 0x8c001239, 0x8c001232, 0x04f80000, 0x057c0000, 0xcdc00013, 0xc414000d, 0xc41c0019, + 0x7dd5c005, 0x25dc0001, 0xd840007c, 0xd8400074, 0xd8400069, 0xc40c005e, 0x94c018a6, 0xd4412e22, + 0xd800007c, 0xc40c005e, 0x94c018a2, 0x95c00007, 0xc40c0019, 0x7cd4c005, 0x24cc0001, 0x94c00008, + 0x9680fffc, 0x800002e3, 0xc40c0057, 0x7cd0c002, 0x94c00003, 0x9680fffd, 0x800002e3, 0xd8000069, + 0xcfc00013, 0xcd013273, 0xcd013275, 0xd8000074, 0xc414005e, 0x9540188f, 0xcfc00013, 0xc40d3249, + 0xc013cfff, 0x7cd0c009, 0xccc13249, 0x9680000b, 0xc40c0077, 0x38d00001, 0x99000006, 0x04cc0002, + 0xdcc30000, 0xc40c005e, 0x94c01882, 0xd4400078, 0xd800000d, 0x80000304, 0x7c41c001, 0x7c41c001, + 0xd840002f, 0xc41c0015, 0x95c0ffff, 0xd8400030, 0xc41c0016, 0x95c0ffff, 0xd8000030, 0xc41c0016, + 0x99c0ffff, 0xd800002f, 0xc41c0015, 0x99c0ffff, 0xc81c001f, 0x49980198, 0x55e40020, 0x459801a0, + 0xcf000024, 0xd1800025, 0xcdc00026, 0xce400026, 0xd8400027, 0x04302000, 0xcfc00013, 0xcf013267, + 0xc4313267, 0x96800004, 0x97000001, 0xd8000036, 0x80000329, 0xd8800013, 0xcc812e00, 0x04302000, + 0xcfc00013, 0xcf013267, 0xc4313267, 0x97000001, 0xc4193256, 0xc42d3249, 0x16ec001f, 0xd8000028, + 0xd800002b, 0x1998003e, 0xcec00031, 0xd8000036, 0xd8000010, 0x97800004, 0xd8400010, 0xce00000a, + 0x1a18003e, 0xcd800008, 0x90000000, 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0x04100000, + 0x7d43c001, 0xcd400013, 0xc4093249, 0x1888003e, 0x94800015, 0xd8400074, 0x8c000671, 0xcd400013, + 0x9a400006, 0xc419324c, 0x259c0001, 0x1598001f, 0x95c0000d, 0x9580000c, 0x99000003, 0xd8400036, + 0x04100001, 0xc40c0021, 0x14d80011, 0x24dc00ff, 0x31e00002, 0x31dc0003, 0x9580fff0, 0x9a000003, + 0x99c00002, 0xd9c00036, 0x94800004, 0xd8000074, 0xc418005e, 0x95801827, 0xcf800008, 0x90000000, + 0xd8800036, 0x90000000, 0xd8c00036, 0xc424000b, 0x32640002, 0x9a400004, 0xc4180014, 0x9580ffff, + 0xd840002f, 0xc40c0021, 0x14dc0011, 0x95c0fffe, 0xccc00037, 0x8c000190, 0x90000000, 0xd8400008, + 0xd800006d, 0xc41d3246, 0xc4193245, 0x51dc0020, 0x7d9d801a, 0xd8400028, 0xd8400029, 0xc420000b, + 0x32200002, 0x9a0000ad, 0x04200032, 0xd9000010, 0xde030000, 0xd8400033, 0x04080000, 0xc43c0009, + 0x27fc0002, 0x97c0fffe, 0xc42c0015, 0x96c0ffff, 0xd800002e, 0xc42d3249, 0x1af4003e, 0x9740004d, + 0xc428000d, 0xc4080060, 0x7ca88005, 0x24880001, 0x7f4b4009, 0x97400046, 0xc4313274, 0xc4100057, + 0x7d33400c, 0x97400009, 0x28240100, 0x7e6a4004, 0xce400079, 0x1eecffdd, 0xcec13249, 0xcf013273, + 0xcf013275, 0x800003c3, 0xc429326f, 0x1aa80030, 0x96800006, 0x28240001, 0xc428000d, 0x06a80008, + 0x7e6a8004, 0xce800035, 0xc41d3272, 0x25cc0001, 0x10cc0004, 0x19e80042, 0x25dc0006, 0x11dc0001, + 0x7e8e800a, 0x7de9c00a, 0xc40d3271, 0xc4293270, 0x50cc0020, 0x7ce8c01a, 0x7cd30011, 0x11e80007, + 0x2aa80000, 0xce80001c, 0xd300001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc4300011, 0x1b30003f, + 0x33300000, 0xc4240059, 0x1660001f, 0x7e320009, 0xc0328000, 0x7e72400a, 0x0430000c, 0x9a000002, + 0x04300008, 0xc02ac000, 0x7d310002, 0x17300002, 0x2aa87600, 0x7cd0c011, 0xcdc00024, 0xd0c00025, + 0xce800026, 0x04280222, 0xce800026, 0x96000002, 0xce400026, 0xd8400027, 0xc4280058, 0x22ec003d, + 0xcec13249, 0xcd013273, 0xce813275, 0xd800007b, 0xc8380018, 0x57b00020, 0x04343108, 0xc429325d, + 0x040c3000, 0x13740008, 0x2374007e, 0x32a80003, 0xccc13267, 0xc40d3267, 0x18ec0057, 0x18e40213, + 0x18cc0199, 0x7cecc00a, 0x7ce4c00a, 0x94800003, 0xd4400078, 0x800003e7, 0x04200022, 0xde030000, + 0xccc00024, 0xd1800025, 0xcf400026, 0xd4400026, 0xd8400027, 0x04200010, 0xde030000, 0xccc00024, + 0x45980104, 0xd1800025, 0xd4400026, 0xcf800026, 0xcf000026, 0xd8400027, 0x49980104, 0x9a80000a, + 0xc81c001f, 0x45980168, 0x55e00020, 0xccc00024, 0xd1800025, 0xcdc00026, 0xce000026, 0xd8400027, + 0x800003f2, 0x8c000448, 0xcd400013, 0x040c2000, 0xccc13267, 0xc40d3267, 0x94c00001, 0xc40d3249, + 0x18cc003e, 0xd8400030, 0xc42c0016, 0x96c0ffff, 0xd8000030, 0xc42c0016, 0x9ac0ffff, 0xd800002f, + 0xc42c0015, 0x9ac0ffff, 0xd8400034, 0xc4300025, 0xc4340024, 0xc4380081, 0xcf813279, 0xcf41326e, + 0xcf01326d, 0x94c0000d, 0x254c0700, 0xc424001e, 0x10cc0010, 0x1a641fe8, 0x28cc0726, 0x2a640200, + 0xd8400013, 0xccc1237b, 0x2264003f, 0xcd400013, 0xd8813260, 0xce41325b, 0xc4240033, 0xc4280034, + 0xd9000036, 0xd8000010, 0x8c001427, 0x96400006, 0xde430000, 0xce40000c, 0xc40c005e, 0x94c01755, + 0xd4400078, 0x9680000a, 0xce80000a, 0x06a80002, 0xd8400010, 0xde830000, 0xce80000d, 0xc40c005e, + 0x94c0174c, 0xd4400078, 0xd8000010, 0x8c00142b, 0xc4393265, 0x2bb80040, 0xd8400032, 0xcf813265, + 0xc4200012, 0x9a00ffff, 0xc4100044, 0x19180024, 0xc8100072, 0x551c003f, 0x99c00003, 0x95800010, + 0x8000043d, 0xc00c8000, 0xd840006c, 0x28200000, 0x8000043f, 0xc00c4000, 0x282000f0, 0xcd400013, + 0xd8400008, 0xc4113255, 0xcd01324f, 0xd8400013, 0xd88130b8, 0xccc130b5, 0xce000053, 0x90000000, + 0x195c00e8, 0xc4100004, 0x2555fff0, 0xc0360001, 0x042c0000, 0x29540001, 0xd8400008, 0x04240000, + 0x04280004, 0xc420000b, 0x32200002, 0x9a000009, 0xcd400013, 0xcec1c200, 0xc5e124dc, 0x0aa80001, + 0x7ef6c001, 0x7e624001, 0x96000001, 0x9a80fff9, 0xc02ee000, 0xcd400013, 0x2555fff0, 0xcec1c200, + 0x29540008, 0xc81c001f, 0xcd400013, 0x55e00020, 0xc42d3255, 0xc4353259, 0xd8013260, 0x45980158, + 0xccc00024, 0xd1800025, 0xcdc00026, 0xce000026, 0xd8400027, 0x49980158, 0x45980170, 0xc4200012, + 0x16200010, 0x9a00fffe, 0xccc00024, 0xd1800025, 0xc429324f, 0xce400026, 0xce800026, 0xcec00026, + 0xcf400026, 0xd8400027, 0xcd000008, 0x90000000, 0xc40d325b, 0x7d43c001, 0x195400e8, 0x1154000a, + 0x18dc00e8, 0x05e80488, 0x18d0006c, 0x18f807f0, 0x18e40077, 0x18ec0199, 0x7e6e400a, 0x86800000, + 0x8000048e, 0x80000494, 0x800004de, 0x80000685, 0x80000686, 0x800006ac, 0x1ccc001f, 0xccc1325b, + 0xc411325d, 0x251001ef, 0xcd01325d, 0x90000000, 0xc4293254, 0x1264000a, 0xc4300004, 0x7d79400a, + 0x7e7a400a, 0x52a8001e, 0x15180001, 0x7d69401a, 0x202c007d, 0xcec1325b, 0x95000008, 0x95800028, + 0xc42d3267, 0xc4193246, 0xc41d3245, 0x1aec0028, 0xc40d325c, 0x800004cc, 0xc42d3256, 0xc419324e, + 0x26e8003f, 0x1aec003e, 0x12f4000e, 0xc41d324d, 0xc40d324f, 0x7d75401a, 0x04100002, 0x7d290004, + 0x7f8f4001, 0x7f52800f, 0x51980020, 0x7d9d801a, 0x50e00002, 0x51980008, 0x9a800002, 0x800004d1, + 0x7d0dc002, 0x6665fc00, 0x7e5e401a, 0xcec00008, 0x7da1c011, 0xd140000b, 0xd1c00002, 0x2a644000, + 0xce400002, 0x7f534002, 0x6665fc00, 0x7e76401a, 0xd1800002, 0xce400002, 0x800004d7, 0xc42d325a, + 0xc4193258, 0x1aec003e, 0xc41d3257, 0xc4213259, 0x12f4000e, 0x7d75401a, 0x51980020, 0x52200002, + 0x7d9d801a, 0xcec00008, 0x7da1c011, 0xd140000b, 0xd1c00002, 0x2a644000, 0xce400002, 0x202c003d, + 0xcf000008, 0xcfc00013, 0xcec1325b, 0xc42d325b, 0x96c00001, 0x90000000, 0xc4193260, 0x259c0007, + 0x15980004, 0x05e804e3, 0x86800000, 0x800004e7, 0x800004f0, 0x80000505, 0x8000016a, 0xc4380004, + 0xcfc00013, 0xd8400008, 0xc435325d, 0xd801325b, 0x277401ef, 0xcf41325d, 0xcf800008, 0x90000000, + 0xc4380004, 0xd8400008, 0x8c000671, 0x9640fff4, 0x17e00008, 0xc418000d, 0xce000009, 0xd84131db, + 0xcf800008, 0xcd800009, 0xc430001e, 0xcfc00013, 0xc42d325b, 0x1b301ff8, 0x2b300400, 0x2330003f, + 0x26edf000, 0x7ef2c00a, 0xd8413260, 0xcec1325b, 0x90000000, 0x05a80507, 0x86800000, 0x8000050c, + 0x80000528, 0x8000057d, 0x800005c2, 0x800005f3, 0xc4380004, 0xd8400008, 0x8c000671, 0xcfc00013, + 0x9a400012, 0x1bd400e8, 0xc42c004a, 0xcd40005e, 0xc41c004d, 0xcec0005e, 0x99c0000c, 0xc4100019, + 0x7d150005, 0x25100001, 0x99000008, 0x8c00063b, 0xcfc00013, 0xc4113277, 0x2511fffd, 0xcd013277, + 0xd801326f, 0x80000624, 0x04240012, 0x1be00fe4, 0xce413260, 0xce000066, 0xcf800008, 0x90000000, + 0xd8400068, 0xc4380004, 0xd8400008, 0x8c000671, 0xcfc00013, 0x9a400013, 0x1bd400e8, 0xc42c004a, + 0xcd40005e, 0xc41c004d, 0xcec0005e, 0x99c0000d, 0xc4100019, 0x7d150005, 0x25100001, 0x99000009, + 0xd8400067, 0x8c00063b, 0xcfc00013, 0xc4113277, 0x2511fffd, 0xcd013277, 0xd801326f, 0x80000624, + 0x1bd400e8, 0xc42c0060, 0x7ed6c005, 0x26ec0001, 0xc4113271, 0xc4153270, 0xc4193272, 0xc41d3273, + 0x04280022, 0x51100020, 0x7d51401a, 0xc4113274, 0xc4213275, 0xc4253276, 0xc4313248, 0xd1400061, + 0x2730000f, 0x13300010, 0x7db1800a, 0xcd800060, 0x96c00002, 0x05dc0008, 0xcdc00062, 0x042c3000, + 0xcd000063, 0xce000064, 0xce400065, 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, 0xce813260, + 0x52ec0020, 0x7ef2c01a, 0xc820001f, 0x1b700057, 0x1b680213, 0x1b740199, 0x46ec0188, 0x7f73400a, + 0x7f6b400a, 0x56240020, 0xcf400024, 0xd2c00025, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, + 0xc418000d, 0x17e00008, 0xce000009, 0xcec13267, 0xc42d3267, 0x26e01000, 0x9a00fffe, 0xd8400013, + 0xd9c131fc, 0xcd800009, 0xcf800008, 0x96c00001, 0x90000000, 0xc4380004, 0xd8400008, 0xc4113277, + 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, 0x11dc0008, 0x29dc0001, 0x25140001, 0x191807e4, + 0x192007ec, 0x95400004, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x9580000e, 0x09980001, 0x041c0001, + 0x95800005, 0x09980001, 0x51dc0001, 0x69dc0001, 0x9980fffd, 0x7de20014, 0x561c0020, 0xd8400013, + 0xce013344, 0xcdc13345, 0xcfc00013, 0x95400022, 0x042c3000, 0xcec13267, 0xc42d3246, 0xc4313245, + 0xc4353267, 0xd8400013, 0xc425334d, 0x26640001, 0x9640fffe, 0xc419334e, 0xc41d334f, 0xc4213350, + 0xc4253351, 0x52ec0020, 0x1b680057, 0x7ef2c01a, 0x1b700213, 0x1b740199, 0x46ec01b0, 0x7f6b400a, + 0x7f73400a, 0xcfc00013, 0xcf400024, 0xd2c00025, 0xcd800026, 0xcdc00026, 0xce000026, 0xce400026, + 0x042c2000, 0xd8400027, 0xcec13267, 0xc42d3267, 0x96c00001, 0x04280032, 0xce813260, 0xd8800068, + 0xcf800008, 0x90000000, 0xc4380004, 0xd8400008, 0x2010007d, 0xcd01325b, 0xc411325b, 0x1910003e, + 0x9500fffe, 0x04100040, 0xcd00001b, 0xd8400021, 0xc410000f, 0x9900ffff, 0x04100060, 0xcd00001b, + 0xd8400021, 0xc410000f, 0x9900ffff, 0xcfc00013, 0x2010003d, 0xcd01325b, 0xc4113277, 0x25140001, + 0x191807e4, 0x9540000b, 0x2511fffd, 0xcd013277, 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, + 0x11dc0008, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x95800005, 0xd8400013, 0xd8013344, 0xd8013345, + 0xcfc00013, 0xc4180050, 0xc41c0052, 0x04280042, 0xcd813273, 0xcdc13275, 0xce813260, 0xd9000068, + 0xd8400067, 0xcf800008, 0x90000000, 0x07d40000, 0x8c00120d, 0x8c00124f, 0x8c001232, 0x057c0000, + 0x042c3000, 0xc4380004, 0xcfc00013, 0xd8400008, 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, + 0x52ec0020, 0x7ef2c01a, 0x1b680057, 0x1b700213, 0x1b740199, 0xc820001f, 0x46ec0190, 0x7f6b400a, + 0x7f73400a, 0x56240020, 0xcf400024, 0xd2c00025, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, + 0xcfc00013, 0xcec13267, 0xc4153249, 0x2154003d, 0xc41c0019, 0x1bd800e8, 0x7dd9c005, 0x25dc0001, + 0xc42c004a, 0xcd80005e, 0xc420004d, 0xcec0005e, 0x11dc0010, 0x7e1e000a, 0xcd413249, 0xce01326f, + 0x28340001, 0x05980008, 0x7f598004, 0xcd800035, 0x1be800e8, 0xc42c004a, 0xce80005e, 0xd801327a, + 0xd800005f, 0xd8000075, 0xd800007f, 0xc424004c, 0xce41326e, 0xcec0005e, 0x28240100, 0x7e6a4004, + 0xce400079, 0xc435325d, 0x277401ef, 0x04240020, 0xce41325e, 0xd801325b, 0xd8013260, 0xcf41325d, + 0xda000068, 0xcf800008, 0x90000000, 0xc4113277, 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, + 0x11dc0008, 0x29dc0001, 0x25140001, 0x9540002d, 0xd8400013, 0xcdc1334a, 0xcfc00013, 0x042c3000, + 0xcec13267, 0xc42d3246, 0xc4313245, 0xc4353267, 0xd8400013, 0xc425334d, 0x26640001, 0x9640fffe, + 0xc419334e, 0xc41d334f, 0xc4213350, 0xc4253351, 0x52ec0020, 0x1b680057, 0x7ef2c01a, 0x1b700213, + 0x1b740199, 0x46ec01b0, 0x7f6b400a, 0x7f73400a, 0xcfc00013, 0xcf400024, 0xd2c00025, 0xcd800026, + 0xcdc00026, 0xce000026, 0xce400026, 0x042c2000, 0xd8400027, 0xcec13267, 0xc42d3267, 0x96c00001, + 0xc41c000b, 0xc420000c, 0x11dc0002, 0x7de1c001, 0x11dc0008, 0xd8400013, 0xcdc1334a, 0xcfc00013, + 0x90000000, 0xc430000b, 0x33300002, 0x04240000, 0x9b000010, 0x1be000e8, 0x042c0000, 0xc0360001, + 0x04280004, 0xd8400013, 0xcec1c200, 0xc63124dc, 0x0aa80001, 0x7ef6c001, 0x7e724001, 0x97000001, + 0x9a80fff9, 0xc02ee000, 0xd8400013, 0xcec1c200, 0x90000000, 0x90000000, 0xc4253260, 0x7fc14001, + 0xc40d3249, 0x18cc003e, 0x98c00005, 0x194c1c03, 0xccc0003b, 0xc40c002d, 0x80000697, 0xc420004a, + 0x194c00e8, 0xccc0005e, 0xc40c004c, 0xc431326d, 0x27301fff, 0xce00005e, 0x7cf0c00d, 0x98c00003, + 0x8c0007e0, 0x95c00008, 0xc430001e, 0x1b301ff8, 0x2b300400, 0x2330003f, 0xcd400013, 0xcf01325b, + 0x90000000, 0xcd400013, 0xd801325b, 0xc411325d, 0x251001ef, 0xcd01325d, 0x25100007, 0x31100005, + 0x9900008e, 0xc40c0007, 0xd9000010, 0x8000075e, 0x202c007d, 0xcec1325b, 0xc4293265, 0xc4353254, + 0x26a9feff, 0xc4380004, 0xd8400008, 0x1374000b, 0xc40c000d, 0xd8000009, 0x1774000d, 0xd8400013, + 0xc41d30b8, 0xcfc00013, 0x95c00008, 0xc411325d, 0xd801325b, 0xccc00009, 0xcf800008, 0x251001ef, + 0xcd01325d, 0x90000000, 0xce813265, 0xcf400100, 0xc00ac006, 0xc00e0000, 0x28880700, 0x28cc0014, + 0x8c0006de, 0x14cc0010, 0x30d4000f, 0x04cc0001, 0x10cc0010, 0x28cc0014, 0x99400009, 0xd8400013, + 0xc41530b8, 0xcfc00013, 0xc4193265, 0x19980028, 0x99400003, 0x99800002, 0x800006c8, 0xcfc00013, + 0xc411325d, 0xd801325b, 0xcf800008, 0x251001ef, 0xcd01325d, 0x90000000, 0x15600008, 0xce000009, + 0xc8380023, 0xc4180081, 0x11a00002, 0x7fa38011, 0xc4100026, 0x05980008, 0x7d1a0002, 0x282c2002, + 0x3e280008, 0xcec00013, 0xc4300027, 0x042c0008, 0xd3800025, 0xcf000024, 0x202400d0, 0x7ca48001, + 0xcc800026, 0xccc00026, 0x28240006, 0xcc000026, 0x0a640001, 0x9a40fffe, 0x9a800004, 0x32280000, + 0x9a800002, 0x9a000000, 0xd8400027, 0x24d8003f, 0xd840003c, 0xcec0003a, 0xd8800013, 0xcd81a2a4, + 0x90000000, 0xc41d325d, 0x25dc0007, 0xc40d3249, 0x18cc003e, 0x94c0000a, 0xc420004a, 0x194c00e8, + 0xccc0005e, 0xc40c004c, 0xc431326d, 0x27301fff, 0xce00005e, 0x7cf0c00d, 0x80000712, 0x194c1c03, + 0xccc0003b, 0xc40c002d, 0x05e80714, 0x86800000, 0x8000071c, 0x80000720, 0x80000747, 0x8000071d, + 0x800007c4, 0x80000732, 0x80000745, 0x80000744, 0x90000000, 0x98c00006, 0x8000072e, 0x90000000, + 0x98c00003, 0x8c0007e0, 0x95c0000c, 0xcd400013, 0xc4253265, 0x2a64008c, 0xce413265, 0xc430001e, + 0x1b301fe8, 0x2b300400, 0x2330003f, 0xd8013260, 0xcf01325b, 0x90000000, 0xc40c0007, 0xd9000010, + 0x04240000, 0x8000075e, 0x98c0fff1, 0x8c0007e0, 0x95c00002, 0x80000723, 0xcd400013, 0xc41f02f1, + 0x95c00004, 0xd8013247, 0xd801325d, 0x80000743, 0xd8813247, 0xd801325d, 0xc4100004, 0xd8400008, + 0xd8400013, 0xd88130b8, 0xcd000008, 0x90000000, 0x04100001, 0x98c0ffde, 0x8000072e, 0x98c00003, + 0x8c0007e0, 0x95c00012, 0xc4340004, 0xd8400008, 0x15600008, 0xc418000d, 0xce000009, 0xd8400013, + 0xd84131db, 0xcf400008, 0xcd800009, 0xc430001e, 0x1b301ff8, 0x2b300400, 0x2330003f, 0xcd400013, + 0xd8413260, 0xcf01325b, 0x90000000, 0xc40c0007, 0xd9000010, 0x04240000, 0xcd400013, 0x041c3000, + 0xcdc13267, 0xc41d3267, 0xc41d3265, 0x25dc8000, 0x95c00007, 0xc41c004a, 0x195800e8, 0xcd80005e, + 0xc418004c, 0xcd81326e, 0xcdc0005e, 0xc41d3265, 0x25dd7fff, 0xcdc13265, 0xc41d3246, 0xc4193245, + 0xc42d3267, 0x51e00020, 0x7e1a001a, 0x46200200, 0x04283247, 0x04300033, 0x1af80057, 0x1af40213, + 0x042c000c, 0x7f7b400a, 0x7f6f400a, 0xcf400024, 0xd2000025, 0xcd800026, 0xcdc00026, 0xc6990000, + 0x329c325d, 0x99c00008, 0x329c3269, 0x99c00006, 0x329c3267, 0x95c00005, 0xc01defff, 0x7d9d8009, + 0x8000078a, 0x25980000, 0x0b300001, 0x06a80001, 0xcd800026, 0x9b00fff2, 0xd8400027, 0xc43c0012, + 0x9bc0ffff, 0xcd400013, 0xd801325b, 0xc431325a, 0xc03e7ff0, 0x7f3f0009, 0xcf01325a, 0xc4313249, + 0x1f30001f, 0xcf013249, 0xc03e4000, 0xcfc13254, 0xcd400013, 0xd8013254, 0xc431325d, 0xd801324f, + 0xd8013255, 0xd8013247, 0xd801325d, 0x1b300028, 0x8c00120d, 0x8c001219, 0x8c001232, 0xc4380004, + 0xd8400008, 0xd8400013, 0x9900000d, 0xd88130b8, 0x9700000b, 0xc43d30b5, 0x1bf0003a, 0x9b000b80, + 0x203c003a, 0xc430000e, 0x27300700, 0x13300014, 0x2b300001, 0xcf0130b7, 0xcfc130b5, 0x46200008, + 0xcf400024, 0xd2000025, 0xd8000026, 0xd8400027, 0x043c2000, 0xcd400013, 0xcfc13267, 0xc43d3267, + 0x9bc00001, 0xccc00010, 0xcf800008, 0x90000000, 0xc4080007, 0xd9000010, 0xc4193260, 0x259c0003, + 0x31dc0003, 0x95c00014, 0x040c3000, 0xd8400008, 0xccc13267, 0xc40d3267, 0x18ec0057, 0x18e40213, + 0x18cc0199, 0x7cecc00a, 0x7ce4c00a, 0xc4193246, 0xc41d3245, 0x51980020, 0x7d9d801a, 0x8c000448, + 0xcd400013, 0x040c2000, 0xccc13267, 0xc40d3267, 0x94c00001, 0xcc800010, 0xd801325d, 0x90000000, + 0xc418000b, 0x31980002, 0x041c0000, 0x9980001c, 0x19580066, 0x15600008, 0x040c0000, 0xc0120001, + 0x11980003, 0x04240004, 0x7da18001, 0xc4200007, 0xc4340004, 0xd9000010, 0xd8400008, 0xd8400013, + 0xccc1c200, 0xc41d24db, 0x7cd0c001, 0x0a640001, 0x7dd9c005, 0x25dc0001, 0x99c00002, 0x9a40fff8, + 0xc418005e, 0x9580137b, 0xc00ee000, 0xd8400013, 0xccc1c200, 0xce000010, 0xcf400008, 0x90000000, + 0xd840004f, 0xc4113269, 0x19080070, 0x190c00e8, 0x2510003f, 0x2518000f, 0xcd813268, 0x05a80809, + 0x86800000, 0x8000080e, 0x8000080f, 0x80000898, 0x80000946, 0x800009e1, 0x80000a5a, 0x04a80811, + 0x86800000, 0x80000815, 0x80000834, 0x8000085e, 0x8000085e, 0x04341001, 0xcf400013, 0xc4380004, + 0xd8400008, 0xc42d3045, 0xcec1c091, 0x31300021, 0x9700000b, 0xd84002f1, 0xd8400013, 0xc43130b8, + 0x27300001, 0xc4293059, 0x56a8001f, 0x7f2b000a, 0xcf800008, 0x9b000241, 0x8000084a, 0xcf400013, + 0xd8400008, 0xc43130b6, 0x9b000003, 0xc02f0001, 0xcec130b6, 0xc4252087, 0x5668001a, 0x26a80005, + 0x9a80fffd, 0xcf400013, 0xd80130b6, 0x8000084a, 0xc4380004, 0xd8400008, 0x04341001, 0xcf400013, + 0xc431ecaa, 0x27300080, 0x9b000010, 0xc02e0001, 0xcec130b6, 0xcf400013, 0xd80130b6, 0x31300021, + 0x9700000a, 0xd84002f1, 0xd8400013, 0xc43130b8, 0x27300001, 0xc4293059, 0x56a8001f, 0x7f2b000a, + 0xcf800008, 0x9b00021d, 0xdd410000, 0x040c0005, 0xd84802e9, 0x8c001a41, 0xc43b02f1, 0x9b800006, + 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0xcf800008, 0xcec80278, 0x56f00020, 0xcf080280, + 0x8c001608, 0xdc140000, 0xcd400013, 0xd8813247, 0xd80802e9, 0x8000085e, 0xcd400013, 0x31100011, + 0x950001fa, 0xc02e0001, 0x2aec0008, 0xc01c0020, 0xc0180001, 0xc00c0007, 0x11a40006, 0x7de6000a, + 0x10e40008, 0x7e26000a, 0x7e2e000a, 0xce000013, 0xc4113254, 0x1d10ffdf, 0x2110003e, 0xcd013254, + 0xd801324f, 0xd8013255, 0x1d10ff9e, 0xcd013254, 0xd8013247, 0xd801325d, 0xd801325e, 0xc0245301, + 0xce413249, 0xd801325f, 0xc425326c, 0xc0121fff, 0x29108eff, 0x7e524009, 0xce41326c, 0xc425325a, + 0xc0127ff0, 0x7e524009, 0xce41325a, 0xc425325b, 0xc0131fff, 0x7e524009, 0xce41325b, 0xd801326d, + 0xd801326e, 0xd8013279, 0x94c00003, 0x08cc0001, 0x80000866, 0xc00c0007, 0x95800003, 0x09980001, + 0x80000866, 0xc0100010, 0x7dd2400c, 0x9a400004, 0xc0180003, 0x7dd1c002, 0x80000866, 0x80000a5a, + 0x04a8089a, 0x86800000, 0x8000089e, 0x800008fa, 0x80000945, 0x80000945, 0x31300022, 0x97000007, + 0xc4380004, 0xd8400008, 0xd8400013, 0xc43130b8, 0x27300001, 0xcf800008, 0xcd400013, 0x04183000, + 0xcd813267, 0xc4113246, 0xc4193245, 0x51100020, 0x7d91801a, 0x459801e0, 0xc4313267, 0x2738000f, + 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, + 0xd180001e, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8300011, 0x97000036, 0x45980008, 0xd180001e, + 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8340011, 0x9740002f, 0xc43c0004, 0xd8400008, 0xd8400013, + 0x13b80001, 0xc79d3300, 0xc7a13301, 0x96000001, 0xd8393300, 0xc0260001, 0xce793301, 0xc424005e, + 0x964012a4, 0x7c028009, 0x9740001c, 0x27580001, 0x99800004, 0x57740001, 0x06a80400, 0x800008d2, + 0xc4180006, 0x9980ffff, 0x29640001, 0xce40001a, 0x242c0000, 0x06ec0400, 0x57740001, 0x27580001, + 0x9980fffd, 0xc02620c0, 0xce41c078, 0xce81c080, 0xcc01c081, 0xcf01c082, 0x57240020, 0xce41c083, + 0xc0260400, 0x7e6e400a, 0xce41c084, 0x7eae8001, 0x7f2f0011, 0x800008d2, 0xc4180006, 0x9980ffff, + 0xcdf93300, 0xce393301, 0xcfc00008, 0xcd400013, 0xc43c0004, 0xd8400008, 0x04182000, 0xcd813267, + 0xcfc00008, 0x80000903, 0x31240022, 0x96400008, 0x04100001, 0xc4380004, 0xd8400008, 0xd8400013, + 0xc43130b8, 0x27300001, 0xcf800008, 0xc4af0280, 0xc4b30278, 0x52ec0020, 0x7ef2c01a, 0x7ec30011, + 0x32f80000, 0x9b800011, 0x043c0020, 0x04280000, 0x67180001, 0x0bfc0001, 0x57300001, 0x95800006, + 0x8c001628, 0x9a400003, 0xd981325d, 0x80000915, 0xd9c1325d, 0x06a80001, 0x9bc0fff6, 0x7f818001, + 0x8c001606, 0x7d838001, 0x94800010, 0xcd400013, 0xc41d3259, 0xc421325a, 0x16240014, 0x12640014, + 0x1a2801f0, 0x12a80010, 0x2620ffff, 0x7e2a000a, 0x7de1c001, 0x7e5e400a, 0x9b800002, 0x2264003f, + 0xce41325a, 0xd8013259, 0xc40c0007, 0xd9000010, 0x8c00075e, 0xc4af0228, 0x043c0000, 0x66d80001, + 0x95800010, 0x04300002, 0x1330000d, 0x13f40014, 0x7f73400a, 0xcf400013, 0x04380040, 0xcf80001b, + 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380060, 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, + 0x07fc0001, 0x56ec0001, 0x33e80010, 0x9680ffec, 0x80000a5a, 0x80000a5a, 0x04a80948, 0x86800000, + 0x8000094c, 0x8000099b, 0x800009e0, 0x800009e0, 0xc43c0004, 0xd8400008, 0xcd400013, 0x04183000, + 0xcd813267, 0xc4113246, 0xc4193245, 0x51100020, 0x7d91801a, 0x459801e0, 0xc4313267, 0x2738000f, + 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, + 0xd180001e, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8300011, 0x97000033, 0x45980008, 0xd180001e, + 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc8340011, 0x9740002c, 0xd8400013, 0x13b80001, 0xc79d3300, + 0xc7a13301, 0x96000001, 0xd8393300, 0xc0260001, 0xce793301, 0xc424005e, 0x964011fe, 0x7c028009, + 0x9740001c, 0x27580001, 0x99800004, 0x57740001, 0x06a80400, 0x80000978, 0xc4180006, 0x9980ffff, + 0x29640001, 0xce40001a, 0x242c0000, 0x06ec0400, 0x57740001, 0x27580001, 0x9980fffd, 0xc0260010, + 0xce41c078, 0xcf01c080, 0x57240020, 0xce41c081, 0xce81c082, 0xcc01c083, 0xc0260800, 0x7e6e400a, + 0xce41c084, 0x7eae8001, 0x7f2f0011, 0x80000978, 0xc4180006, 0x9980ffff, 0xcdf93300, 0xce393301, + 0x04182000, 0xcd813267, 0xcfc00008, 0xcd400013, 0xc4193246, 0xc41d3245, 0x51980020, 0x7dda801a, + 0x7d41c001, 0x7e838011, 0xd84802e9, 0x8c001802, 0x469c0390, 0xc4313267, 0x04183000, 0xcd813267, + 0x1b342010, 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, + 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4200011, 0x45dc0004, 0xd1c0001e, + 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4240011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, + 0x9980ffff, 0xc4280011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc42c0011, + 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4300011, 0x45dc0004, 0xd1c0001e, + 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4340011, 0x45dc0004, 0xd1c0001e, 0xd8400021, 0xc418000f, + 0x9980ffff, 0xc4380011, 0xcd400013, 0x04182000, 0xcd813267, 0x043c0001, 0x8c0014df, 0x80000a5a, + 0x80000a5a, 0x31280014, 0xce8802ef, 0x9a800062, 0x31280034, 0x9a800060, 0x04a809e8, 0x86800000, + 0x800009ec, 0x80000a45, 0x80000a59, 0x80000a59, 0xcd400013, 0xc4113246, 0xc4193245, 0x51100020, + 0x7d91801a, 0x45980400, 0xc4b30258, 0xc4a70250, 0x53300020, 0x7e72401a, 0xc4313267, 0x1b342010, + 0x172c000c, 0x26ec0800, 0x1b30c012, 0x7ef7400a, 0x7f37000a, 0x2b300000, 0xcf00001c, 0x042c0020, + 0x66740001, 0x97400041, 0xcd400013, 0x04383000, 0xcf813267, 0xc4393267, 0x9b800001, 0xd180001e, + 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4300011, 0x1b38007e, 0x33b40003, 0x9b400003, 0x4598001c, + 0x9740002f, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc40c0011, 0x45980004, + 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4100011, 0x45980004, 0xd180001e, 0xd8400021, + 0xc438000f, 0x9b80ffff, 0xc4340011, 0xcf4002eb, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, + 0x9b80ffff, 0xc4340011, 0xcf4002ec, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, + 0xc4340011, 0xcf4002ed, 0x45980004, 0xd180001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4340011, + 0xcf4002ee, 0x45980004, 0xcd400013, 0x04382000, 0xcf813267, 0xd84802e9, 0x8c001715, 0xcd400013, + 0x04382000, 0xcf813267, 0x56640001, 0x0aec0001, 0x9ac0ffbc, 0xc4380004, 0xd8400008, 0x04341001, + 0xcf400013, 0x94800005, 0xc431ecaa, 0x27300080, 0x97000002, 0x80000a55, 0xc43130b6, 0x233c0032, + 0xcfc130b6, 0xcf400013, 0xcf0130b6, 0xc49302ef, 0x99000003, 0xcd400013, 0xd8413247, 0xcf800008, + 0x80000a5a, 0x80000a5a, 0xcd400013, 0x04180001, 0x5198001f, 0xcd813268, 0xc4193269, 0x2598000f, + 0x9980fffe, 0xd80002f1, 0xcd400013, 0xd8013268, 0xd800004f, 0x90000000, 0xcd400013, 0x04380001, + 0x53b8001f, 0x7db9801a, 0xcd813268, 0x80000a5e, 0xd8400029, 0xc40c005e, 0x94c01106, 0xd8800013, + 0xcc412e01, 0xcc412e02, 0xcc412e03, 0xcc412e00, 0x80000aa7, 0xd8400029, 0xc40c005e, 0x94c010fd, + 0x7c40c001, 0x50640020, 0x7ce4c01a, 0xd0c00072, 0xc80c0072, 0x58e801fc, 0x12a80009, 0x2aa80000, + 0xd0c0001e, 0xce80001c, 0xd8400021, 0xc424000f, 0x9a40ffff, 0x04240010, 0x18dc01e2, 0x7e5e4002, + 0x3e5c0003, 0x3e540002, 0x95c00006, 0xc8180011, 0xc8100011, 0xc8100011, 0x55140020, 0x80000aa2, + 0x9540000a, 0xc8180011, 0x44cc0008, 0x55900020, 0xd0c0001e, 0xd8400021, 0xc424000f, 0x9a40ffff, + 0xc4140011, 0x80000aa2, 0x44cc0004, 0xc4180011, 0xd0c0001e, 0xd8400021, 0xc424000f, 0x9a40ffff, + 0xc8100011, 0x55140020, 0xd8800013, 0xcd812e01, 0xcd012e02, 0xcd412e03, 0xcc412e00, 0xc428000e, + 0x2aa80008, 0xce800013, 0xc4253249, 0x2264003f, 0xce413249, 0xce800013, 0xc4253249, 0x96400001, + 0xd800002a, 0xc410001a, 0xc40c0021, 0xc4140028, 0x95000005, 0x1e64001f, 0xce800013, 0xce413249, + 0x80001b70, 0x14d00010, 0xc4180030, 0xc41c0007, 0x99000004, 0x99400009, 0x9980000c, 0x80000ab1, + 0xccc00037, 0x8c000190, 0xc420001c, 0xd8000032, 0x9a0010ac, 0x80000aa7, 0xd880003f, 0x95c00002, + 0xd8c0003f, 0x80001082, 0xd8800040, 0x95c00002, 0xd8c00040, 0x800010de, 0xc010ffff, 0x18d403f7, + 0x7d0cc009, 0xc41b0367, 0x7d958004, 0x7d85800a, 0xdc1e0000, 0x90000000, 0xc424000b, 0x32640002, + 0x7c40c001, 0x18d001fc, 0x05280adc, 0x86800000, 0x80000af1, 0x80000adf, 0x80000ae7, 0x8c000ace, + 0xd8c00013, 0x96400002, 0xd8400013, 0xcd8d2000, 0x99c00010, 0x7c408001, 0x88000000, 0x18d803f7, + 0xc010ffff, 0x7d0cc009, 0x04140000, 0x11940014, 0x29544001, 0x9a400002, 0x29544003, 0xcd400013, + 0x80000af4, 0xd8c00013, 0x96400002, 0xd8400013, 0xd44d2000, 0x7c408001, 0x88000000, 0xc424000b, + 0x32640002, 0x7c40c001, 0xd8c00013, 0x96400002, 0xd8400013, 0xd44dc000, 0x7c408001, 0x88000000, + 0x7c40c001, 0x18d0003c, 0x95000006, 0x8c000ace, 0xd8800013, 0xcd8d2c00, 0x99c00003, 0x80000b0a, + 0xd8800013, 0xd44d2c00, 0x7c408001, 0x88000000, 0x7c40c001, 0x28148004, 0x24d800ff, 0xccc00019, + 0xcd400013, 0xd4593240, 0x7c408001, 0x88000000, 0xd8400029, 0xc40c005e, 0x94c0105e, 0x7c410001, + 0x50540020, 0x7c418001, 0x2198003f, 0x199c0034, 0xc40c0007, 0x95c00028, 0xc428000e, 0x2aa80008, + 0xce800013, 0xc42d324f, 0xc4313255, 0x7ef3400c, 0x9b400021, 0xd800002a, 0x80001b70, 0xc40c0007, + 0x14e80001, 0x9a8000af, 0xd9000010, 0x041c0002, 0x042c01c8, 0x8c000d61, 0xccc00010, 0xd8400029, + 0xc40c005e, 0x94c01043, 0x7c410001, 0x50540020, 0x7c418001, 0x18a01fe8, 0x3620005c, 0x9a00000e, + 0x2464003f, 0xd8400013, 0xc6290ce7, 0x16ac001f, 0x96c00004, 0x26ac003f, 0x7ee6c00d, 0x96c00005, + 0x06200001, 0x2620000f, 0x9a00fff8, 0x8000016a, 0xce000367, 0xc424005e, 0x9640102e, 0xc428000e, + 0x199c0037, 0x19a00035, 0x2aa80008, 0xce800013, 0x95c0005d, 0xd800002a, 0xc42d3256, 0xc431325a, + 0x2330003f, 0x16f8001f, 0x9780000d, 0xc4253248, 0xc035f0ff, 0x7e764009, 0x19b401f8, 0x13740008, + 0x7e76400a, 0xce800013, 0xce413248, 0xcf01325a, 0xce800013, 0xc431325a, 0x97000001, 0x7d15001a, + 0xd1000072, 0xc8100072, 0x55140020, 0x199c0034, 0xd8400010, 0xd8400029, 0x9b800004, 0x1ae4003e, + 0xce400008, 0x80000b7c, 0xc4353254, 0x16a80008, 0x1aec003c, 0x19a4003f, 0x12a80015, 0x12ec001f, + 0x1374000b, 0x7eae800a, 0xc02e4000, 0x1774000d, 0x7eae800a, 0xce400008, 0x7f6b400a, 0x95c00005, + 0xc43d3248, 0x1bfc01e8, 0x13fc0018, 0x7dbd800a, 0x1d98ff15, 0x592c00fc, 0xcd80000a, 0x12e00016, + 0x7da1800a, 0x592c007e, 0x12e00015, 0x7da1800a, 0xd1000001, 0xcd800001, 0x11a0000c, 0x1264001e, + 0x1620000c, 0x7e26000a, 0x7e32000a, 0x12e4001b, 0x7e26000a, 0x5924007e, 0x12640017, 0x7e26000a, + 0x19a4003c, 0x12640018, 0x7e26000a, 0xd800002a, 0xce01325a, 0xcd013257, 0xcd413258, 0xc429325a, + 0xc40c005e, 0x94c00fdb, 0x96800001, 0x95c00003, 0x7c40c001, 0x7c410001, 0x9780f5ca, 0xcf400100, + 0xc40c0007, 0xd9000010, 0x8c00120d, 0x8c001219, 0x8c001232, 0xccc00010, 0x8c001b6d, 0x7c408001, + 0x88000000, 0xc42d324e, 0xc431324d, 0x52ec0020, 0x7ef2c01a, 0xc435324f, 0xc4293256, 0x52ec0008, + 0x07740003, 0x04240002, 0x269c003f, 0x7e5e4004, 0x7f67000f, 0x97000003, 0x7f674002, 0x0b740001, + 0x53740002, 0x7ef6c011, 0x1ab42010, 0x1ab8c006, 0x16a8000c, 0x26a80800, 0x2b740000, 0x7f7b400a, + 0x7f6b400a, 0xcf40001c, 0xd2c0001e, 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4180011, 0x9a000003, + 0x8c000bec, 0x80000b47, 0xc42c001d, 0xc4313256, 0x1b34060b, 0x1b300077, 0x7f370009, 0x13300017, + 0x04340100, 0x26ec00ff, 0xc03a8004, 0x7ef6c00a, 0x7f3b000a, 0x7ef2c00a, 0xcec1325b, 0x80000c16, + 0xc40c0032, 0xc410001d, 0x28cc0008, 0xccc00013, 0xc415325b, 0x7c418001, 0x7c418001, 0x18580037, + 0x251000ff, 0xc421325d, 0x262001ef, 0xce01325d, 0x99800004, 0x7d15400a, 0xcd41325b, 0x80000168, + 0x1d54001f, 0xcd41325b, 0x7c408001, 0x88000000, 0xc428000b, 0xc42c000c, 0x12a80001, 0x26a80004, + 0x7eae800a, 0xc40c0021, 0xc4340028, 0x14f00010, 0xc4380030, 0xc43c0007, 0xcd280200, 0xcd680208, + 0xcda80210, 0x9b00000c, 0x9b400014, 0x9b800017, 0xc428000b, 0xc42c000c, 0x12a80001, 0x26a80004, + 0x7eae800a, 0xc6930200, 0xc6970208, 0xc69b0210, 0x90000000, 0x17300001, 0x9b000005, 0xccc00037, + 0x8c000190, 0xd8000032, 0x90000000, 0xd8000028, 0xd800002b, 0x80000168, 0xd900003f, 0x97c00002, + 0xd940003f, 0x80001082, 0xd9000040, 0x97c00002, 0xd9400040, 0x800010de, 0xc40c0021, 0x14fc0011, + 0x24f800ff, 0x33b80001, 0x97c0fffc, 0x9b800007, 0xccc00037, 0x8c000190, 0xd8000032, 0xd8000028, + 0xd800002b, 0x80001b70, 0xc4380004, 0xd8400008, 0xd8400013, 0xd88130b8, 0x04100000, 0x04140000, + 0xc418000e, 0x29980008, 0x7d83c001, 0xcd800013, 0xc4093249, 0x1888003e, 0x94800020, 0xd8400074, + 0x8c000671, 0x9a400009, 0xc418000e, 0x29980008, 0xcd800013, 0xc419324c, 0x259c0001, 0x1598001f, + 0x95c00016, 0x95800015, 0x99000003, 0xd8400036, 0x04100001, 0xc40c0021, 0x14d80011, 0x24e000ff, + 0x321c0002, 0x32200001, 0x9580ffee, 0x99c00014, 0x96000004, 0xccc00037, 0x04140001, 0x80000c30, + 0x9480000a, 0xd8000074, 0xc418005e, 0x95800f29, 0xcf800008, 0x80000c16, 0x94800004, 0xd8000074, + 0xc418005e, 0x95800f23, 0xd9c00036, 0x99400002, 0xccc00037, 0xcf800008, 0x80000c16, 0x94800004, + 0xd8000074, 0xc418005e, 0x95800f1a, 0xccc00037, 0xd8800036, 0x80001b70, 0x041c0003, 0x042c01c8, + 0x8c000d61, 0xc4200007, 0xc40c0077, 0x94c00001, 0x7c418001, 0xc428000e, 0x9600f502, 0x0a200001, + 0x98c0f500, 0x2aa80008, 0xce000010, 0x9a000f05, 0xce800013, 0xc431325a, 0xc42d3256, 0x1f30001f, + 0x16e4001f, 0xcf01325a, 0xc431325a, 0x97000001, 0x9640f4f4, 0xc434000b, 0x33740002, 0x9b40f4f1, + 0xc4353254, 0x16a80008, 0x1aec003c, 0x12a80015, 0x12ec001f, 0x1374000b, 0x7eae800a, 0xc02e4000, + 0x1774000d, 0x7eae800a, 0x7f6b400a, 0xcf400100, 0x12780001, 0x2bb80001, 0xc00ac005, 0xc00e0002, + 0x28cc8000, 0x28884900, 0x28cc0014, 0x80000ff3, 0xc43c0007, 0x7c40c001, 0x17fc0001, 0xd8400013, + 0x9bc00004, 0xd8400029, 0xc424005e, 0x96400ee1, 0xcc41c40a, 0xcc41c40c, 0xcc41c40d, 0x7c414001, + 0x24d0007f, 0x15580010, 0x255400ff, 0xcd01c411, 0xcd81c40f, 0xcd41c40e, 0xcc41c410, 0x7c414001, + 0x7c418001, 0x04200000, 0x18e80033, 0x18ec0034, 0xcc41c414, 0xcc41c415, 0xcd81c413, 0xcd41c412, + 0x18dc0032, 0x7c030011, 0x7c038011, 0x95c00027, 0x96c00002, 0xc431c417, 0xc435c416, 0x96800004, + 0x96c00002, 0xc439c419, 0xc43dc418, 0xc41c000e, 0x29dc0008, 0xcdc00013, 0xcf413261, 0x96c00002, + 0xcf013262, 0x96800004, 0xcfc13263, 0x96c00002, 0xcf813264, 0x18dc0030, 0xc43c0007, 0x95c00017, + 0x17fc0001, 0x9ac00005, 0x7d77000c, 0x9bc00015, 0x9700000a, 0x80000cd6, 0x51b80020, 0x53300020, + 0x7f97801a, 0x7f37001a, 0x7f3b000c, 0x9bc0000d, 0x97800002, 0x80000cd6, 0x9a000018, 0xd8400013, + 0x28200001, 0x80000ca7, 0x18dc0031, 0x95c00003, 0xc435c40b, 0x9740fffd, 0xd800002a, 0x80001b70, + 0xc4280032, 0x2aa80008, 0xce800013, 0xc40d325b, 0x97000002, 0x800012c2, 0xc438001d, 0x1bb81ff0, + 0x7f8cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, 0xcd01325d, 0x80001b70, 0xc428000e, 0xc43c0007, + 0x2aa80008, 0xc438001d, 0xce800013, 0x13f4000c, 0x9bc00006, 0xc43d3256, 0x1bf0060b, 0x1bfc0077, + 0x7ff3c00a, 0x80000cf4, 0xc43d325a, 0x1bfc0677, 0x13fc0017, 0x04300100, 0x1bb81fe8, 0x7f73400a, + 0xc032800b, 0x7fb7800a, 0x7ff3c00a, 0x7ffbc00a, 0xcfc1325b, 0x80000c16, 0xc43c0007, 0x7c40c001, + 0x18d42011, 0x17fc0001, 0x18d001e8, 0x24cc007f, 0x7cd4c00a, 0x9bc00004, 0xd8400029, 0xc428005e, + 0x96800e6c, 0x7c414001, 0x50580020, 0x7d59401a, 0xd1400072, 0xc8140072, 0x596001fc, 0x12200009, + 0x7ce0c00a, 0x7c418001, 0x505c0020, 0x7d9d801a, 0x7c41c001, 0x50600020, 0x7de1c01a, 0x7c420001, + 0xccc0001b, 0xd140001d, 0xd180001f, 0xd1c00020, 0xd8400021, 0x95000010, 0x04300000, 0xc428000f, + 0x9a80ffff, 0xc8240010, 0x7e5e800c, 0x9bc00015, 0x9a80000c, 0x9b000024, 0x28300001, 0x122c0004, + 0x06ec0001, 0x0aec0001, 0x9ac0ffff, 0xd8400021, 0x80000d1f, 0xc428000f, 0x9a80ffff, 0xc8240010, + 0x566c0020, 0xc428000e, 0x2aa80008, 0xce800013, 0xce413261, 0xcec13262, 0xd800002a, 0x80001b70, + 0xc4340032, 0x2b740008, 0xcf400013, 0xc40d325b, 0x96800005, 0x566c0020, 0xce413261, 0xcec13262, + 0x800012c2, 0xc438001d, 0x1bb81fe8, 0x7f8cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, 0xcd01325d, + 0x80001b70, 0xc43c0007, 0xc438001d, 0xc428000e, 0x2aa80008, 0xce800013, 0x13f4000c, 0x9bc00006, + 0xc43d3256, 0x1bf0060b, 0x1bfc0077, 0x7ff3c00a, 0x80000d57, 0xc43d325a, 0x1bfc0677, 0x13fc0017, + 0x04300100, 0x1bb81fe8, 0x7f73400a, 0xc0328009, 0x7fb7800a, 0x7ff3c00a, 0x7ffbc00a, 0xcfc1325b, + 0x80000c16, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0xc4253246, 0xc4113245, 0x04143000, 0xcd413267, + 0x52640020, 0x7e51001a, 0xc4153267, 0x7d2d0011, 0x19640057, 0x19580213, 0x19600199, 0x7da6400a, + 0x7e26400a, 0xd1000025, 0xce400024, 0xcdc00026, 0xd8400027, 0x04142000, 0xcfc00013, 0xcd413267, + 0xc4153267, 0x99400001, 0x90000000, 0x7c40c001, 0x18d001e8, 0x18d40030, 0x18d80034, 0x05280d83, + 0x7c420001, 0x7c424001, 0x86800000, 0x80000d8a, 0x8000016a, 0x80000d95, 0x80000db1, 0x8000016a, + 0x80000d95, 0x80000dbc, 0x11540010, 0x7e010001, 0x8c00187c, 0x7d75400a, 0xcd400013, 0xd4610000, + 0x9580f3d8, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0xd8000016, 0x526c0020, 0x18e80058, + 0x7e2ec01a, 0xd2c00072, 0xc82c0072, 0x5ae0073a, 0x7ea2800a, 0x9940000a, 0xce800024, 0xd2c00025, + 0xd4400026, 0xd8400027, 0x9580f3c6, 0xc4380012, 0x9b80ffff, 0x7c408001, 0x88000000, 0xdc3a0000, + 0x0bb80001, 0xce800024, 0xd2c00025, 0xcc400026, 0xd8400027, 0x9b80fffb, 0x9980fff5, 0x7c408001, + 0x88000000, 0xc02a0001, 0x2aa80001, 0x16200002, 0xce800013, 0xce01c405, 0xd441c406, 0x9580f3b1, + 0xc439c409, 0x97800001, 0x7c408001, 0x88000000, 0xc424000b, 0x32640002, 0x9a40000b, 0x11540010, + 0x29540002, 0xcd400013, 0xd4610000, 0x9580f3a5, 0xd8400013, 0xc439c040, 0x97800001, 0x7c408001, + 0x88000000, 0xd4400078, 0x80000168, 0xd8400029, 0xc40c005e, 0x94c00da7, 0x7c40c001, 0x50500020, + 0x7cd0c01a, 0xd0c00072, 0xc8280072, 0x5aac007e, 0x12d80017, 0x7c41c001, 0x7d9d800a, 0x56a00020, + 0x2620ffff, 0x7da1800a, 0x51980020, 0x7e82400a, 0x7e58c01a, 0x19d4003d, 0x28182002, 0x99400030, + 0x8c00104f, 0xc430000d, 0xc4340035, 0xd800002a, 0xcd800013, 0xc8140023, 0xc4180081, 0x13300005, + 0xc011000f, 0xc4240004, 0x11a00002, 0x7c908009, 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, + 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x3e280008, 0x20880188, 0x54ec0020, 0x7cb4800a, 0xc4300027, + 0x04380008, 0xd1400025, 0xcf000024, 0x20240090, 0x7ca48001, 0xcc800026, 0xccc00026, 0xcec00026, + 0xcec00026, 0x28240004, 0xcc000026, 0x0a640001, 0x9a40fffe, 0x9a800005, 0x32280000, 0x9a800002, + 0x9a000000, 0x7c018001, 0xd8400027, 0xd8000016, 0xcf80003a, 0xd901a2a4, 0x80001037, 0xc418000e, + 0x29980008, 0xcd800013, 0xc421326c, 0x1624001f, 0x9a40fffe, 0xd841325f, 0xd8800033, 0xc43c0009, + 0x27fc0004, 0x97c0fffe, 0xd8000039, 0xd0c00038, 0xc43c0022, 0x9bc0ffff, 0xd8800034, 0xc429325f, + 0x26ac0001, 0x9ac0fffe, 0x26ac0002, 0x96c00003, 0xd800002a, 0x80001b70, 0xc43c0007, 0xc430001e, + 0xd8800033, 0x13f4000c, 0x1b301ff0, 0x2b300300, 0x2330003f, 0x7f37000a, 0x9680000b, 0xc43c0009, + 0x27fc0004, 0x97c0fffe, 0xd8400039, 0xd0c00038, 0xc43c0022, 0x9bc0ffff, 0xcf01325b, 0xd8800034, + 0x80000c16, 0xd8800034, 0x8c0001a2, 0x80001b70, 0xcc80003b, 0x24b00008, 0xc418000e, 0x1330000a, + 0x18ac0024, 0x2b304000, 0x7c40c001, 0xcec00008, 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, + 0x29980008, 0xcd800013, 0xc4113249, 0x1910003e, 0x99000002, 0xd840003d, 0x7c410001, 0xd4400078, + 0x51100020, 0xcf01326c, 0x7cd0c01a, 0xc421326c, 0x12a80014, 0x2220003f, 0x7e2a000a, 0xcd800013, + 0xce01326c, 0xd8800033, 0xc43c0009, 0x27fc0004, 0x97c0fffe, 0xd8000039, 0xd0c00038, 0xc43c0022, + 0x9bc0ffff, 0xd8800034, 0x80001190, 0x7c40c001, 0x18dc003d, 0x95c00004, 0x041c0001, 0x042c01c8, + 0x8c000d61, 0x18d40030, 0x18d001e8, 0x18fc0034, 0x24e8000f, 0x06a80e71, 0x7c418001, 0x7c41c001, + 0x86800000, 0x80000edd, 0x80000e91, 0x80000e91, 0x80000ea1, 0x80000eaa, 0x80000e7c, 0x80000e7f, + 0x80000e7f, 0x80000e87, 0x80000e8f, 0x8000016a, 0x51dc0020, 0x7d9e001a, 0x80000ee6, 0xc420000e, + 0x2a200008, 0xce000013, 0xc4213262, 0xc4253261, 0x52200020, 0x7e26001a, 0x80000ee6, 0xc420000e, + 0x2a200008, 0xce000013, 0xc4213264, 0xc4253263, 0x52200020, 0x7e26001a, 0x80000ee6, 0xc820001f, + 0x80000ee6, 0x18e82005, 0x51e00020, 0x2aa80000, 0x7da1801a, 0xd1800072, 0xc8180072, 0x59a001fc, + 0x12200009, 0x7ea2800a, 0xce80001c, 0xd180001e, 0xd8400021, 0xc428000f, 0x9a80ffff, 0xc8200011, + 0x80000ee6, 0x15980002, 0xd8400013, 0xcd81c400, 0xc421c401, 0x95400041, 0xc425c401, 0x52640020, + 0x7e26001a, 0x80000ee6, 0x31ac2580, 0x9ac00011, 0x31ac260c, 0x9ac0000f, 0x31ac0800, 0x9ac0000d, + 0x31ac0828, 0x9ac0000b, 0x31ac2440, 0x9ac00009, 0x31ac2390, 0x9ac00007, 0x31ac0093, 0x9ac00005, + 0x31ac31dc, 0x9ac00003, 0x31ac31e6, 0x96c00004, 0xc4340004, 0xd8400008, 0x80000ede, 0x39ac7c06, + 0x3db07c00, 0x9ac00003, 0x97000002, 0x80000ebc, 0x39acc337, 0x3db0c330, 0x9ac00003, 0x97000002, + 0x80000ebc, 0x39acc335, 0x3db0c336, 0x9ac00003, 0x97000002, 0x80000ebc, 0x39ac9002, 0x3db09001, + 0x9ac00003, 0x97000002, 0x80000ebc, 0x39ac9012, 0x3db09011, 0x9ac00003, 0x97000002, 0x80000ebc, + 0x39acec70, 0x3db0ec6f, 0x9ac00003, 0x97000002, 0x80000ebc, 0xc4340004, 0xd8400013, 0xc5a10000, + 0x95400005, 0x05980001, 0xc5a50000, 0x52640020, 0x7e26001a, 0xcf400008, 0x05280eea, 0x7c418001, + 0x7c41c001, 0x86800000, 0x80000ef1, 0x8000016a, 0x80000efe, 0x80000f11, 0x80000f2e, 0x80000efe, + 0x80000f1f, 0xc4340004, 0xd8400013, 0xce190000, 0x95400005, 0x05980001, 0x56200020, 0xce190000, + 0xcf400008, 0x97c0f26f, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0x51ec0020, 0x18e80058, + 0x7daec01a, 0xd2c00072, 0xc82c0072, 0x5af8073a, 0x7eba800a, 0xd2c00025, 0xce800024, 0xce000026, + 0x95400003, 0x56240020, 0xce400026, 0xd8400027, 0x97c0f25c, 0xc4380012, 0x9b80ffff, 0x7c408001, + 0x88000000, 0xc02a0001, 0x2aa80001, 0x15980002, 0xce800013, 0xcd81c405, 0xce01c406, 0x95400003, + 0x56240020, 0xce41c406, 0x97c0f24e, 0xc439c409, 0x97800001, 0x7c408001, 0x88000000, 0xc424000b, + 0x32640002, 0x9a40f247, 0xd8800013, 0xce190000, 0x95400004, 0x05980001, 0x56200020, 0xce190000, + 0x97c0f240, 0xd8400013, 0xc439c040, 0x97800001, 0x7c408001, 0x88000000, 0x31ac2580, 0x9ac00011, + 0x31ac260c, 0x9ac0000f, 0x31ac0800, 0x9ac0000d, 0x31ac0828, 0x9ac0000b, 0x31ac2440, 0x9ac00009, + 0x31ac2390, 0x9ac00007, 0x31ac0093, 0x9ac00005, 0x31ac31dc, 0x9ac00003, 0x31ac31e6, 0x96c00004, + 0xc4340004, 0xd8400008, 0x80000ef2, 0x39ac7c06, 0x3db07c00, 0x9ac00003, 0x97000002, 0x80000f40, + 0x39acc337, 0x3db0c330, 0x9ac00003, 0x97000002, 0x80000f40, 0x39acc335, 0x3db0c336, 0x9ac00003, + 0x97000002, 0x80000f40, 0x39acec70, 0x3db0ec6f, 0x9ac00003, 0x97000002, 0x80000f40, 0x39ac9002, + 0x3db09002, 0x9ac00003, 0x97000002, 0x80000f40, 0x39ac9012, 0x3db09012, 0x9ac00003, 0x97000002, + 0x80000f40, 0x80000ef1, 0xc40c0006, 0x98c0ffff, 0x7c40c001, 0x7c410001, 0x7c414001, 0x7c418001, + 0x7c41c001, 0x7c43c001, 0x95c00001, 0xc434000e, 0x2b740008, 0x2b780001, 0xcf400013, 0xd8c1325e, + 0xcf80001a, 0xd8400013, 0x7c034001, 0x7c038001, 0x18e0007d, 0x32240003, 0x9a400006, 0x32240000, + 0x9a400004, 0xcd01c080, 0xcd41c081, 0x80000f88, 0x51640020, 0x7e52401a, 0xd2400072, 0xc8280072, + 0xce81c080, 0x56ac0020, 0x26f0ffff, 0xcf01c081, 0x1af000fc, 0x1334000a, 0x24e02000, 0x7f63400a, + 0x18e00074, 0x32240003, 0x9a400006, 0x32240000, 0x9a400004, 0xcd81c082, 0xcdc1c083, 0x80000f9d, + 0x51e40020, 0x7e5a401a, 0xd2400072, 0xc8280072, 0xce81c082, 0x56ac0020, 0x26f0ffff, 0xcf01c083, + 0x1af000fc, 0x13380016, 0x18e00039, 0x12200019, 0x7fa3800a, 0x7fb7800a, 0x18e0007d, 0x1220001d, + 0x7fa3800a, 0x18e00074, 0x12200014, 0x7fa3800a, 0xcf81c078, 0xcfc1c084, 0x80000c16, 0x7c40c001, + 0x18dc003d, 0x95c00004, 0x041c0000, 0x042c01c8, 0x8c000d61, 0x18d001e8, 0x31140005, 0x99400003, + 0x31140006, 0x95400002, 0x8c00104f, 0x05280fb7, 0x28140002, 0xcd400013, 0x86800000, 0x80000fbe, + 0x80000fbe, 0x80000fc2, 0x80000fbe, 0x80000fd1, 0x80000ff2, 0x80000ff2, 0x24cc003f, 0xccc1a2a4, + 0x7c408001, 0x88000000, 0x7c414001, 0x18e80039, 0x52a8003b, 0x50580020, 0x24cc003f, 0x7d59401a, + 0xd1400072, 0xc8140072, 0x7d69401a, 0xc41c0017, 0x99c0ffff, 0xd140004b, 0xccc1a2a4, 0x7c408001, + 0x88000000, 0xc414000d, 0x04180001, 0x24cc003f, 0x7d958004, 0xcd800035, 0xccc1a2a4, 0xc43c000e, + 0x2bfc0008, 0xcfc00013, 0xc43d3249, 0x1bfc003e, 0x97c00002, 0xd8400074, 0xc4100019, 0x7d150005, + 0x25100001, 0x9500000b, 0x97c0fffc, 0xc4180021, 0x159c0011, 0x259800ff, 0x31a00003, 0x31a40001, + 0x7e25800a, 0x95c0fff5, 0x9580fff4, 0x80000fef, 0xc411326f, 0x1d100010, 0xcd01326f, 0x97c00002, + 0xd8000074, 0x80001b70, 0x04380000, 0xc430000d, 0xc8140023, 0xc4180081, 0x13300005, 0xc011000f, + 0xc4240004, 0x33b40003, 0x97400003, 0xc0340008, 0x80000ffe, 0xc4340035, 0x11a00002, 0x7c908009, + 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x282c2002, + 0x208801a8, 0x3e280008, 0x7cb4800a, 0xcec00013, 0xc4300027, 0x042c0008, 0xd1400025, 0xcf000024, + 0x20240030, 0x7ca48001, 0xcc800026, 0xccc00026, 0x9b800013, 0xcc400026, 0x7c414001, 0x28340000, + 0xcf400013, 0x507c0020, 0x7d7d401a, 0xd1400072, 0xc8140072, 0x557c0020, 0x28342002, 0xcf400013, + 0xcd400026, 0xcfc00026, 0xd4400026, 0x9a80000e, 0x32280000, 0x9a80000b, 0x8000102f, 0xcc000026, + 0xcc000026, 0xcc000026, 0xcc000026, 0xcc000026, 0x9a800005, 0x32280000, 0x9a800002, 0x9a000000, + 0x7c018001, 0xcc000026, 0xd8400027, 0x1cccfe08, 0xd8800013, 0xcec0003a, 0xccc1a2a4, 0xc43c000e, + 0x2bfc0008, 0xcfc00013, 0xc43d3249, 0x1bfc003e, 0x9bc00007, 0xc428000e, 0x16a80008, 0xce800009, + 0xc42c005e, 0x96c00b33, 0xd840003c, 0xc4200025, 0x7da2400f, 0x7da28002, 0x7e1ac002, 0x0aec0001, + 0x96400002, 0x7d2ac002, 0x3ef40010, 0x9b40f11d, 0x04380030, 0xcf81325e, 0x80000c16, 0xde410000, + 0xdcc10000, 0xdd010000, 0xdd410000, 0xdd810000, 0xddc10000, 0xde010000, 0xc40c000e, 0x7c024001, + 0x28cc0008, 0xccc00013, 0xc8100086, 0x5510003f, 0xc40d3249, 0x18cc003e, 0x98c00003, 0x99000011, + 0x80001075, 0x9900000c, 0xc40c0026, 0xc4100081, 0xc4140025, 0x7d15800f, 0x7d15c002, 0x7d520002, + 0x0a200001, 0x95800002, 0x7cde0002, 0x3e20001a, 0x9a000009, 0x040c0030, 0xccc1325e, 0x80001071, + 0xd9c00036, 0xd8400029, 0xc40c005e, 0x94c00b01, 0x04240001, 0xdc200000, 0xdc1c0000, 0xdc180000, + 0xdc140000, 0xdc100000, 0xdc0c0000, 0x96400004, 0xdc240000, 0xdc0c0000, 0x80000c16, 0xdc240000, + 0x90000000, 0xcc40003f, 0xd8c00010, 0xc4080029, 0xcc80003b, 0xc418000e, 0x18a800e5, 0x1d980008, + 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, 0x18a400e5, 0x12500009, 0x248c0008, 0x94c00006, + 0x200c006d, 0x7cd0c00a, 0xccc1326c, 0xc421326c, 0x96000001, 0xcd800013, 0x200c0228, 0x7cd0c00a, + 0xccc1326c, 0xc421326c, 0x96000001, 0xc40c002a, 0xc410002b, 0x18881fe8, 0x18d4072c, 0x18cc00d1, + 0x7cd4c00a, 0x3094000d, 0x38d80000, 0x311c0003, 0x99400006, 0x30940007, 0x1620001f, 0x9940001d, + 0x9a000023, 0x800010c4, 0x9580001a, 0x99c00019, 0xccc00041, 0x25140001, 0xc418002c, 0x9940000d, + 0x259c007f, 0x95c00013, 0x19a00030, 0xcdc0001b, 0xd8400021, 0xd8400022, 0xc430000f, 0x17300001, + 0x9b00fffe, 0x9a000012, 0xd8400023, 0x800010cb, 0x199c0fe8, 0xcdc0001b, 0xd8400021, 0xd8400023, + 0xc430000f, 0x17300001, 0x9b00fffe, 0x800010cb, 0xd8c00010, 0xd8000022, 0xd8000023, 0xc430005e, + 0x97000aac, 0x7c408001, 0x88000000, 0xc43c000e, 0xc434002e, 0x2bfc0008, 0x2020002c, 0xcfc00013, + 0xce01326c, 0x17780001, 0x27740001, 0x07a810d8, 0xcf400010, 0xc421326c, 0x96000001, 0x86800000, + 0x80000168, 0x80000aa7, 0x80000bfc, 0x800012e9, 0x8000104c, 0xcc400040, 0xd8800010, 0xc4180032, + 0x29980008, 0xcd800013, 0x200c007d, 0xccc1325b, 0xc411325b, 0x95000001, 0x7c408001, 0x88000000, + 0x28240007, 0xde430000, 0xd4400078, 0x80001190, 0xcc80003b, 0x24b00008, 0xc418000e, 0x1330000a, + 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, 0xc40d3249, 0x18cc003e, + 0x98c00002, 0xd840003d, 0x2b304000, 0xcf01326c, 0xc431326c, 0x7c40c001, 0x7c410001, 0x7c414001, + 0x192400fd, 0x50580020, 0x7d59401a, 0x7c41c001, 0x06681110, 0x7c420001, 0xcc400078, 0x18ac0024, + 0x19180070, 0x19100078, 0xcec00008, 0x18f40058, 0x5978073a, 0x7f7b400a, 0x97000001, 0x86800000, + 0x80001117, 0x80001118, 0x80001122, 0x8000112d, 0x80001130, 0x80001133, 0x8000016a, 0x8000117b, + 0x24ec0f00, 0x32ec0600, 0x96c00003, 0xc4300006, 0x9b00ffff, 0xd1400025, 0xcf400024, 0xcdc00026, + 0xd8400027, 0x8000117b, 0x24ec0f00, 0x32ec0600, 0x96c00003, 0xc4300006, 0x9b00ffff, 0xd1400025, + 0xcf400024, 0xcdc00026, 0xce000026, 0xd8400027, 0x8000117b, 0xc81c001f, 0x55e00020, 0x80001122, + 0xc81c0020, 0x55e00020, 0x80001122, 0x8c00116b, 0xd8400013, 0xc02a0200, 0x7e8e8009, 0x22a8003d, + 0x22a80074, 0x2774001c, 0x13740014, 0x7eb6800a, 0x25ecffff, 0x55700020, 0x15f40010, 0x13740002, + 0x275c001f, 0x95c00027, 0x7c018001, 0x7f41c001, 0x15dc0002, 0x39e00008, 0x25dc0007, 0x7dc1c01e, + 0x05dc0001, 0x96000004, 0x05e40008, 0x8c00116e, 0x80001168, 0x7dc2001e, 0x06200001, 0x05e40008, + 0x7e62000e, 0x9a000004, 0x7da58001, 0x8c00116e, 0x80001165, 0x7dc2001e, 0x06200001, 0x7e1a0001, + 0x05cc0008, 0x7e0d000e, 0x95000007, 0x7e02401e, 0x06640001, 0x06640008, 0x05d80008, 0x8c00116e, + 0x80001168, 0x7dc2401e, 0x06640001, 0x7da58001, 0x8c00116e, 0x05e00008, 0x7da2000c, 0x9600ffe6, + 0x17640002, 0x8c00116e, 0x80001190, 0xc4200006, 0x9a00ffff, 0x90000000, 0x8c00116b, 0xc420000e, + 0x2a200001, 0xce00001a, 0xce81c078, 0xcec1c080, 0xcc01c081, 0xcd41c082, 0xcf01c083, 0x12640002, + 0x22640435, 0xce41c084, 0x90000000, 0x0528117e, 0x312c0003, 0x86800000, 0x80001190, 0x80001185, + 0x80001182, 0x80001182, 0xc4300012, 0x9b00ffff, 0x9ac0000c, 0xc03a0400, 0xc4340004, 0xd8400013, + 0xd8400008, 0xc418000e, 0x15980008, 0x1198001c, 0x7d81c00a, 0xcdc130b7, 0xcf8130b5, 0xcf400008, + 0x04240008, 0xc418000e, 0xc41c0049, 0x19a000e8, 0x29a80008, 0x7de2c00c, 0xce800013, 0xc421325e, + 0x26200010, 0xc415326d, 0x9a000006, 0xc420007d, 0x96000004, 0x96c00003, 0xce40003e, 0x800011a3, + 0x7d654001, 0xcd41326d, 0x7c020001, 0x96000005, 0xc4100026, 0xc4240081, 0xc4140025, 0x800011b6, + 0xc4253279, 0xc415326d, 0xc431326c, 0x2730003f, 0x3b380006, 0x97800004, 0x3f38000b, 0x9b800004, + 0x800011b4, 0x04300006, 0x800011b4, 0x0430000b, 0x04380002, 0x7fb10004, 0x7e57000f, 0x7e578002, + 0x7d67c002, 0x0be40001, 0x97000002, 0x7d3a4002, 0x202c002c, 0xc421325e, 0x04280020, 0xcec1326c, + 0x26200010, 0x3e640010, 0x96000003, 0x96400002, 0xce81325e, 0xc4300028, 0xc434002e, 0x17780001, + 0x27740001, 0x07a811cf, 0x9b00feb8, 0xcf400010, 0xc414005e, 0x954009a7, 0x86800000, 0x80000168, + 0x80000aa7, 0x80000bfc, 0x800012e9, 0x80000168, 0x8c00120d, 0x7c40c001, 0xccc1c07c, 0xcc41c07d, + 0xcc41c08c, 0x7c410001, 0xcc41c079, 0xcd01c07e, 0x7c414001, 0x18f0012f, 0x18f40612, 0x18cc00c1, + 0x7f73400a, 0x7cf7400a, 0x39600004, 0x9a000002, 0xc0140004, 0x11600001, 0x18fc003e, 0x9740001c, + 0xcf400041, 0xc425c07f, 0x97c00003, 0x166c001f, 0x800011ee, 0x1a6c003e, 0x96c00006, 0x04200002, + 0x0a200001, 0x9a00ffff, 0xd8400013, 0x800011e8, 0xc428002c, 0x96800010, 0x26ac007f, 0xcec0001b, + 0xd8400021, 0x1ab00030, 0x1aac0fe8, 0xc434000f, 0x9b40ffff, 0x97000008, 0xcec0001b, 0xd8400021, + 0xc434000f, 0x9b40ffff, 0x80001205, 0x0a200001, 0x9a00ffff, 0xd8400013, 0xc425c07f, 0x166c001f, + 0x11600001, 0x9ac0fffa, 0x8c001232, 0x7c408001, 0x88000000, 0xd8000033, 0xc438000b, 0xc43c0009, + 0x27fc0001, 0x97c0fffe, 0xd8400013, 0xd841c07f, 0xc43dc07f, 0x1bfc0078, 0x7ffbc00c, 0x97c0fffd, + 0x90000000, 0xc03a2800, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04380040, + 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380060, 0xcf80001b, 0xd8400021, 0xc438000f, + 0x9b80ffff, 0x04380002, 0x0bb80001, 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, + 0x9bc0fffa, 0x90000000, 0xd8400013, 0xd801c07f, 0xd8400013, 0xc43dc07f, 0xcfc00078, 0xd8000034, + 0x90000000, 0xc03ae000, 0xcf81c200, 0xc03a0800, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, + 0xcc01c07e, 0x04380040, 0xcf80001b, 0xd8400021, 0xc438000f, 0x9b80ffff, 0x04380002, 0x0bb80001, + 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, 0x9bc0fffa, 0x90000000, 0xc03ae000, + 0xcf81c200, 0xc03a4000, 0xcf81c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04380002, + 0x0bb80001, 0x9b80ffff, 0xd8400013, 0xc43dc07f, 0x17fc001f, 0x04380010, 0x9bc0fffa, 0x90000000, + 0xc40c0007, 0x30d00002, 0x99000052, 0xd8400029, 0xc424005e, 0x9640090f, 0x7c410001, 0xc428000e, + 0x1514001f, 0x19180038, 0x2aa80008, 0x99400030, 0x30dc0001, 0xce800013, 0x99c0000a, 0xc42d324e, + 0xc431324d, 0x52ec0020, 0x7ef2c01a, 0xc435324f, 0xc4293256, 0x1ab0c006, 0x52ec0008, 0x8000127f, + 0xc42d3258, 0xc4313257, 0x52ec0020, 0x7ef2c01a, 0xc4353259, 0xc429325a, 0x1ab0c012, 0x07740001, + 0x04240002, 0x26a0003f, 0x7e624004, 0x7f67800f, 0x97800002, 0x04340000, 0x53740002, 0x7ef6c011, + 0x1ab42010, 0x16a8000c, 0x26a80800, 0x2b740000, 0x7f73400a, 0x7f6b400a, 0xcf40001c, 0xd2c0001e, + 0xd8400021, 0xc438000f, 0x9b80ffff, 0xc4100011, 0x1514001f, 0x99400006, 0x9980000a, 0x8c0012e1, + 0xc40c0007, 0x04100000, 0x80001267, 0xd800002a, 0xc424005e, 0x964008d7, 0xd9800036, 0x80000c16, + 0xc42c001d, 0x95c00005, 0xc431325a, 0x1b300677, 0x11dc000c, 0x800012aa, 0xc4313256, 0x1b34060b, + 0x1b300077, 0x7f37000a, 0x13300017, 0x04340100, 0x26ec00ff, 0xc03a8002, 0x7ef6c00a, 0x7edec00a, + 0x7f3b000a, 0x7ef2c00a, 0xcec1325b, 0x80000c16, 0xc4140032, 0xc410001d, 0x29540008, 0xcd400013, + 0xc40d325b, 0x1858003f, 0x251000ff, 0x99800007, 0x7d0cc00a, 0xccc1325b, 0xc411325d, 0x251001ef, + 0xcd01325d, 0x80000168, 0x18d0006c, 0x18d407f0, 0x9900000e, 0x04100002, 0xc4193256, 0xc41d324f, + 0x2598003f, 0x7d190004, 0x7d5d4001, 0x7d52000f, 0x9a000003, 0xcd41324f, 0x800012d8, 0x7d514002, + 0xcd41324f, 0x800012d8, 0xc4193259, 0xc41d325a, 0x7d958001, 0x7dd5c002, 0xcd813259, 0xcdc1325a, + 0xc411325d, 0x251001ef, 0xcd01325d, 0x1ccc001e, 0xccc1325b, 0xc40d325b, 0x94c00001, 0x7c408001, + 0x88000000, 0xc40c0021, 0xc4340028, 0x14f00010, 0xc4380030, 0xc43c0007, 0x9b000004, 0x9b40000c, + 0x9b80000f, 0x90000000, 0x17300001, 0x9b000005, 0xccc00037, 0x8c000190, 0xd8000032, 0x90000000, + 0xd8000028, 0xd800002b, 0x80000168, 0xd980003f, 0x97c00002, 0xd9c0003f, 0x80001082, 0xd9800040, + 0x97c00002, 0xd9c00040, 0x800010de, 0xc43c0007, 0x33f80003, 0x97800051, 0xcc80003b, 0x24b00008, + 0xc418000e, 0x1330000a, 0x18a800e5, 0x1d980008, 0x12a80008, 0x7da9800a, 0x29980008, 0xcd800013, + 0xc4353249, 0x1b74003e, 0x9b400002, 0xd840003d, 0x2b304000, 0xcf01326c, 0xc431326c, 0x97000001, + 0x7c434001, 0x1b4c00f8, 0x7c410001, 0x7c414001, 0x50700020, 0x04e81324, 0x18ac0024, 0x7c41c001, + 0x50600020, 0xcc400078, 0x30e40004, 0x9a400007, 0x7d71401a, 0x596401fc, 0x12640009, 0x1b74008d, + 0x7e76400a, 0x2a640000, 0xcec00008, 0x86800000, 0x8000016a, 0x8000016a, 0x8000016a, 0x8000016a, + 0x8000132c, 0x8000133b, 0x80001344, 0x8000016a, 0xc4340004, 0xd8400013, 0xd8400008, 0xc42530b5, + 0x1a68003a, 0x9a80fffe, 0x2024003a, 0xc418000e, 0x25980700, 0x11980014, 0x7d19000a, 0xcd0130b7, + 0xce4130b5, 0xcf400008, 0x80001190, 0xce40001c, 0xd140001e, 0xd8400021, 0xc428000f, 0x9a80ffff, + 0xc4240011, 0x7de6800f, 0x9a80ffea, 0x80001190, 0xce40001c, 0xd140001e, 0xd8400021, 0xc428000f, + 0x9a80ffff, 0xc8240011, 0x7de1c01a, 0x7de6800f, 0x9a80ffe0, 0x80001190, 0x8c00104f, 0x28182002, + 0xc430000d, 0xc4340035, 0xcd800013, 0xc8140023, 0xc4180081, 0x13300005, 0xc4240004, 0x11a00002, + 0x12640004, 0x7d614011, 0xc4100026, 0x05980008, 0x7ca4800a, 0x7d1a0002, 0x7cb0800a, 0x3e280008, + 0x7cb4800a, 0xc4300027, 0x042c0008, 0xd1400025, 0xcf000024, 0x20240030, 0x7ca48001, 0xcc800026, + 0x7c434001, 0x1b4c00f8, 0xcf400026, 0xcc400026, 0x28340000, 0xcf400013, 0x7c414001, 0x507c0020, + 0x30e40004, 0x9a400005, 0x7d7d401a, 0xd1400072, 0xc8140072, 0x557c0020, 0x28342002, 0xcf400013, + 0xcd400026, 0xcfc00026, 0xd4400026, 0xcc000026, 0x9a800005, 0x32280000, 0x9a800002, 0x9a000000, + 0x7c018001, 0xd8400027, 0xd8800013, 0x04380028, 0xcec0003a, 0xcf81a2a4, 0x80001037, 0xd8400029, + 0xc40c005e, 0x94c007eb, 0x7c40c001, 0x50500020, 0x7d0d001a, 0xd1000072, 0xc8100072, 0x591c01fc, + 0x11dc0009, 0x45140210, 0x595801fc, 0x11980009, 0x29dc0000, 0xcdc0001c, 0xd140001e, 0xd8400021, + 0xc418000f, 0x9980ffff, 0xc4200011, 0x1624001f, 0x96400069, 0xc40c000e, 0x28cc0008, 0xccc00013, + 0xce013249, 0x1a307fe8, 0xcf00000a, 0x23304076, 0xd1000001, 0xcf000001, 0xc41d3254, 0xc4253256, + 0x18cc00e8, 0x10cc0015, 0x4514020c, 0xd140001e, 0xd8400021, 0xc418000f, 0x9980ffff, 0xc4200011, + 0xce013248, 0x1a2001e8, 0x12200014, 0x2a204001, 0xce000013, 0x1a64003c, 0x1264001f, 0x11dc0009, + 0x15dc000b, 0x7dcdc00a, 0x7e5dc00a, 0xcdc00100, 0xd8800013, 0xd8400010, 0xd800002a, 0xd8400008, + 0xcf00000d, 0xcf00000a, 0x8c001427, 0x04340022, 0x07740001, 0x04300010, 0xdf430000, 0x7c434001, + 0x7c408001, 0xd4412e01, 0x0434001e, 0xdf430000, 0xd4400078, 0xdf030000, 0xd4412e40, 0xd8400013, + 0xcc41c030, 0xcc41c031, 0x248dfffe, 0xccc12e00, 0xd8800013, 0xcc812e00, 0x7c434001, 0x7c434001, + 0x8c00142b, 0xd8000010, 0xc40c000e, 0x28cc0008, 0xccc00013, 0x45140248, 0xd140001e, 0xd8400021, + 0xc418000f, 0x9980ffff, 0xc8200011, 0xce013257, 0x56200020, 0xce013258, 0x0434000c, 0xdb000024, + 0xd1400025, 0xd8000026, 0xd8000026, 0xd8400027, 0x45540008, 0xd140001e, 0xd8400021, 0xc418000f, + 0x9980ffff, 0xc8200011, 0xce013259, 0x56200020, 0xc0337fff, 0x7f220009, 0xce01325a, 0x55300020, + 0x7d01c001, 0x042c01d0, 0x8c000d61, 0x06ec0004, 0x7f01c001, 0x8c000d61, 0x041c0002, 0x042c01c8, + 0x8c000d61, 0xc4380012, 0x9b80ffff, 0xd800002a, 0x80000aa7, 0xd800002a, 0x7c408001, 0x88000000, + 0xd8400029, 0x7c40c001, 0x50500020, 0x8c001427, 0x7cd0c01a, 0xc4200007, 0xd0c00072, 0xc8240072, + 0xd240001e, 0x7c414001, 0x19682011, 0x5a6c01fc, 0x12ec0009, 0x7eeac00a, 0x2aec0000, 0xcec0001c, + 0xd8400021, 0xc430000f, 0x9b00ffff, 0xc4180011, 0x7c438001, 0x99800007, 0xdf830000, 0xcfa0000c, + 0x8c00142b, 0xd4400078, 0xd800002a, 0x80001b70, 0x8c00142b, 0xd800002a, 0x80001b70, 0xd8000012, + 0xc43c0008, 0x9bc0ffff, 0x90000000, 0xd8400012, 0xc43c0008, 0x97c0ffff, 0x90000000, 0xc4380007, + 0x7c40c001, 0x17b80001, 0x18d40038, 0x7c410001, 0x9b800004, 0xd8400029, 0xc414005e, 0x9540073d, + 0x18c80066, 0x7c414001, 0x30880001, 0x7c418001, 0x94800008, 0x8c00187c, 0xcf400013, 0xc42c0004, + 0xd8400008, 0xcd910000, 0xcec00008, 0x7d410001, 0x043c0000, 0x7c41c001, 0x7c420001, 0x04240001, + 0x06200001, 0x4220000c, 0x0a640001, 0xcc000078, 0x9a40fffe, 0x24e80007, 0x24ec0010, 0xd8400013, + 0x9ac00006, 0xc42c0004, 0xd8400008, 0xc5310000, 0xcec00008, 0x80001465, 0x51540020, 0x7d15001a, + 0xd1000072, 0xc82c0072, 0xd2c0001e, 0x18f02011, 0x5aec01fc, 0x12ec0009, 0x7ef2c00a, 0x2aec0000, + 0xcec0001c, 0xd8400021, 0xc42c000f, 0x9ac0ffff, 0xc4300011, 0x96800012, 0x12a80001, 0x0aa80001, + 0x06a8146a, 0x7f1f0009, 0x86800000, 0x7f1b400f, 0x80001478, 0x7f1b400e, 0x80001478, 0x7f1b400c, + 0x8000147a, 0x7f1b400d, 0x8000147a, 0x7f1b400f, 0x8000147a, 0x7f1b400e, 0x8000147a, 0x7f334002, + 0x97400014, 0x8000147b, 0x9b400012, 0x9b800005, 0x9bc0001f, 0x7e024001, 0x043c0001, 0x8000144a, + 0xc40c0032, 0xc438001d, 0x28cc0008, 0xccc00013, 0xc43d325b, 0x1bb81ff0, 0x7fbfc00a, 0xcfc1325b, + 0xc411325d, 0x251001ef, 0xcd01325d, 0x80001b70, 0x94800007, 0x8c00187c, 0xcf400013, 0xc42c0004, + 0xd8400008, 0xcd910000, 0xcec00008, 0x9b800003, 0xd800002a, 0x80001b70, 0xc40c0032, 0x28cc0008, + 0xccc00013, 0xc40d325b, 0x800012c2, 0xc40c000e, 0xc43c0007, 0xc438001d, 0x28cc0008, 0xccc00013, + 0x13f4000c, 0x9bc00006, 0xc43d3256, 0x1bf0060b, 0x1bfc0077, 0x7ff3c00a, 0x800014a9, 0xc43d325a, + 0x1bfc0677, 0x04300100, 0x1bb81ff0, 0x7f73400a, 0xc0328007, 0x7fb7800a, 0x13fc0017, 0x7ff3c00a, + 0x7ffbc00a, 0xcfc1325b, 0xc03a0002, 0xc4340004, 0xd8400013, 0xd8400008, 0xcf8130b5, 0xcf400008, + 0x80000c16, 0x043c0000, 0xc414000e, 0x29540008, 0xcd400013, 0xc4193246, 0xc41d3245, 0x51980020, + 0x7dd9c01a, 0x45dc0390, 0xc4313267, 0x04183000, 0xcd813267, 0x1b380057, 0x1b340213, 0x1b300199, + 0x7f7b400a, 0x7f73400a, 0xcf400024, 0xd1c00025, 0xcc800026, 0x7c420001, 0xce000026, 0x7c424001, + 0xce400026, 0x7c428001, 0xce800026, 0x7c42c001, 0xcec00026, 0x7c430001, 0xcf000026, 0x7c434001, + 0xcf400026, 0x7c438001, 0xcf800026, 0xd8400027, 0xcd400013, 0x04182000, 0xcd813267, 0xd840004f, + 0x1a0800fd, 0x109c000a, 0xc4193265, 0x7dd9c00a, 0xcdc13265, 0x2620ffff, 0xce080228, 0x9880000e, + 0xce480250, 0xce880258, 0xd8080230, 0xd8080238, 0xd8080240, 0xd8080248, 0xd8080268, 0xd8080270, + 0xd8080278, 0xd8080280, 0xd800004f, 0x97c0ec75, 0x90000000, 0x040c0000, 0x041c0010, 0x26180001, + 0x09dc0001, 0x16200001, 0x95800002, 0x04cc0001, 0x99c0fffb, 0xccc80230, 0xd8080238, 0xd8080240, + 0xd8080248, 0x040c0000, 0xce480250, 0xce880258, 0x52a80020, 0x7e6a401a, 0x041c0020, 0x66580001, + 0x09dc0001, 0x56640001, 0x95800002, 0x04cc0001, 0x99c0fffb, 0xccc80260, 0xd8080268, 0xd8080270, + 0xd8080278, 0xd8080280, 0x040c0000, 0xcec80288, 0xcf080290, 0xcec80298, 0xcf0802a0, 0x040c0000, + 0x041c0010, 0xcf4802a8, 0x27580001, 0x09dc0001, 0x17740001, 0x95800002, 0x04cc0001, 0x99c0fffb, + 0xccc802b0, 0xd80802b8, 0x178c000b, 0x27b8003f, 0x7cf8c001, 0xcf8802c0, 0xccc802c8, 0xcf8802d0, + 0xcf8802d8, 0xd800004f, 0x97c00002, 0x90000000, 0x7c408001, 0x88000000, 0xc40c000e, 0x28cc0008, + 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c418001, 0x25b8ffff, 0xc4930240, 0xc48f0238, 0x04cc0001, + 0x24cc000f, 0x7cd2800c, 0x9a80000b, 0xc5230309, 0x2620ffff, 0x7e3a400c, 0x9a400004, 0x05100001, + 0x2510000f, 0x80001539, 0xcd08034b, 0xd4400078, 0x80000168, 0xc48f0230, 0xc4930240, 0x98c00004, + 0xcd880353, 0x8c00163f, 0xc49b0353, 0xc4930238, 0xc48f0228, 0x05100001, 0x2510000f, 0x7cd14005, + 0x25540001, 0x99400004, 0x05100001, 0x2510000f, 0x8000154f, 0xc48f0230, 0x7c41c001, 0xcd080238, + 0xcd08034b, 0x08cc0001, 0x2598ffff, 0x3d200008, 0xccc80230, 0xcd900309, 0xd8100319, 0x04340801, + 0x2198003f, 0xcf400013, 0xcd910ce7, 0xc4190ce6, 0x7d918005, 0x25980001, 0x9580fffd, 0x7d918004, + 0xcd810ce6, 0x9a000003, 0xcdd1054f, 0x8000156e, 0x090c0008, 0xcdcd050e, 0x040c0000, 0x110c0014, + 0x28cc4001, 0xccc00013, 0xcc41230a, 0xcc41230b, 0xcc41230c, 0xcc41230d, 0xcc480329, 0xcc48032a, + 0xcc4802e0, 0xd8000055, 0xc48f02e0, 0x24d8003f, 0x09940001, 0x44100001, 0x9580002c, 0x95400005, + 0x09540001, 0x51100001, 0x69100001, 0x8000157f, 0x24cc003f, 0xc4970290, 0xc49b0288, 0x51540020, + 0x7d59401a, 0xc49b02a0, 0xc49f0298, 0x51980020, 0x7d9d801a, 0x041c0040, 0x04200000, 0x7dcdc002, + 0x7d924019, 0x7d26400c, 0x09dc0001, 0x9a400008, 0x51100001, 0x06200001, 0x99c0fffa, 0xc48f0230, + 0xc4930240, 0x8c00163f, 0x80001579, 0x7d010021, 0x7d914019, 0xc4930238, 0x55580020, 0xcd480298, + 0xcd8802a0, 0x10d40010, 0x12180016, 0xc51f0309, 0x7d95800a, 0x7d62000a, 0x7dd9c00a, 0xd8400013, + 0xcdd00309, 0xce113320, 0xc48f02e0, 0xc49b02b0, 0x18dc01e8, 0x7dd9400e, 0xc48f0230, 0xc4930240, + 0x95c0001d, 0x95400003, 0x8c00163f, 0x800015aa, 0xc48f0238, 0xc4a302b8, 0x12240004, 0x7e5e400a, + 0xc4ab02a8, 0x04100000, 0xce4c0319, 0x7d9d8002, 0x7ea14005, 0x25540001, 0x99400004, 0x06200001, + 0x2620000f, 0x800015bc, 0x09dc0001, 0x04240001, 0x7e624004, 0x06200001, 0x7d25000a, 0x2620000f, + 0x99c0fff4, 0xd8400013, 0xcd0d3330, 0xce0802b8, 0xcd8802b0, 0xc4ab02e0, 0x1aa807f0, 0xc48f02d0, + 0xc49702d8, 0xc49b02c8, 0xc49f02c0, 0x96800028, 0x7d4e000f, 0x9600000b, 0x7d964002, 0x7e6a000f, + 0x96000003, 0x7d694001, 0x800015e9, 0x7cde4002, 0x7e6a000f, 0x96000008, 0x7de94001, 0x800015e9, + 0x7cd64002, 0x7e6a000e, 0x96000003, 0x7d694001, 0x800015e9, 0xc48f0230, 0xc4930240, 0x8c00163f, + 0x800015cd, 0xc4930238, 0x7d698002, 0xcd4802d8, 0x129c0008, 0xc50f0319, 0x11a0000e, 0x11140001, + 0xc4340004, 0xd8400008, 0xd8400013, 0x7e1e000a, 0x1198000a, 0xcd953300, 0x7e0e000a, 0x12a8000a, + 0xce953301, 0xce100319, 0xcf400008, 0xc4b70280, 0xc4b30278, 0x7f73800a, 0x536c0020, 0x7ef2c01a, + 0x9780eb68, 0x8c001608, 0xd8080278, 0xd8080280, 0x7c408001, 0x88000000, 0x043c0003, 0x80001609, + 0x043c0001, 0x30b40000, 0x9b400011, 0xc4b70258, 0xc4b30250, 0x53780020, 0x7fb3801a, 0x7faf8019, + 0x04300020, 0x04280000, 0x67b40001, 0x0b300001, 0x57b80001, 0x97400002, 0x06a80001, 0x9b00fffb, + 0xc4bb0260, 0x7fab8001, 0xcf880260, 0x04300020, 0x04280000, 0x66f40001, 0x0b300001, 0x56ec0001, + 0x97400005, 0x8c001628, 0xc4353247, 0x7f7f4009, 0x9b40fffe, 0x06a80001, 0x9b00fff7, 0x90000000, + 0x269c0007, 0x11dc0008, 0x29dc0008, 0x26a00018, 0x12200003, 0x7de1c00a, 0x26a00060, 0x06200020, + 0x16200001, 0x7de1c00a, 0xcdc00013, 0x90000000, 0x269c0018, 0x26a00007, 0x26a40060, 0x11dc0006, + 0x12200006, 0x16640001, 0x29dc0008, 0x7de1c00a, 0x7de5c00a, 0xcdc00013, 0x90000000, 0xc4b70228, + 0x05100001, 0x04cc0001, 0x2510000f, 0xccc80230, 0x7f514005, 0x25540001, 0x99400004, 0x05100001, + 0x2510000f, 0x80001644, 0xc4b30248, 0xcd080240, 0x7f130005, 0x27300001, 0x9b000002, 0x8c001688, + 0x8c00120d, 0x8c001219, 0x8c001232, 0x04300001, 0x04340801, 0x7f130004, 0xcf400013, 0xcf01051e, + 0xc42d051f, 0x7ed2c005, 0x26ec0001, 0x96c0fffd, 0xcf01051f, 0xd8000055, 0xc5170309, 0x195c07f0, + 0x196007f6, 0x04340000, 0x95c00008, 0x09dc0001, 0x04340001, 0x95c00005, 0x09dc0001, 0x53740001, + 0x6b740001, 0x80001665, 0xc4a702a0, 0xc4ab0298, 0x52640020, 0x7e6a401a, 0x7f634014, 0x7e76401a, + 0xc4300004, 0xd8400008, 0xd8400013, 0x56680020, 0xd8113320, 0xce480298, 0xce8802a0, 0xc5170319, + 0xc4b702b0, 0x255c000f, 0x7f5f4001, 0xd8113330, 0xcf4802b0, 0x11340001, 0x195c07e8, 0x196007ee, + 0xd8353300, 0x7e1e4001, 0xd8353301, 0xce4802d0, 0xd8100309, 0xd8100319, 0xcf000008, 0x90000000, + 0xc4970258, 0xc48f0250, 0x51540020, 0x7cd4c01a, 0xc4af0280, 0xc4b30278, 0x52ec0020, 0x7ef2c01a, + 0x04140020, 0x04280000, 0x64d80001, 0x09540001, 0x54cc0001, 0x95800060, 0x8c001628, 0xc4193247, + 0x25980001, 0x9580005c, 0x7dc24001, 0xc41d3248, 0x25dc000f, 0x7dd2000c, 0x96000057, 0xc41d3255, + 0xc435324f, 0x7df5c00c, 0x99c00004, 0xc4193265, 0x25980040, 0x9580fffe, 0xc439325b, 0x1bb0003f, + 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, 0x9700000a, 0xc4393260, 0x1bb000e4, + 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x800016f1, 0xce400013, 0xc033ffff, + 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, 0x27b800ff, 0x9b80fffe, 0xd8c00033, + 0xc4300009, 0x27300008, 0x9700fffe, 0x1a7003e6, 0x27380003, 0x13b80004, 0x27300003, 0x13300003, + 0x7fb38001, 0x1a7000e8, 0x7fb38001, 0x13300001, 0x7fb38001, 0x07b80002, 0xd8400013, 0x1a700064, + 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, + 0x0b300003, 0x800016df, 0x17b00005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, 0x13300005, + 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, 0xd8c00034, 0xce400013, 0xc431325d, + 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffca, 0xd841325d, 0x2030007b, 0xcf01325b, + 0x800016f2, 0xd841325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0x06a80001, 0x9940ff9c, 0x8c001608, + 0xd8080278, 0xd8080280, 0x90000000, 0xd840004f, 0xc414000e, 0x29540008, 0xcd400013, 0xc43d3265, + 0x1bc800ea, 0xd80802e9, 0x7c40c001, 0x18fc0064, 0x9bc00042, 0xc4193246, 0xc41d3245, 0x51980020, + 0x7dd9801a, 0x45980400, 0xc4313267, 0x043c3000, 0xcfc13267, 0xc43d3267, 0x9bc00001, 0x1b380057, + 0x1b340213, 0x1b300199, 0x7f7b400a, 0x7f73400a, 0xcf400024, 0x14f4001d, 0xc4bf02e9, 0x9bc0001c, + 0x7c410001, 0x192807fa, 0xc4bf0258, 0xc4a70250, 0x53fc0020, 0x7e7e401a, 0x042c0000, 0x04300000, + 0x667c0001, 0x56640001, 0x06ec0001, 0x97c0fffd, 0x07300001, 0x0aec0001, 0x7eebc00c, 0x06ec0001, + 0x97c0fff8, 0x0b300001, 0x43300007, 0x53300002, 0x7db30011, 0xd3000025, 0xc03ec005, 0x2bfca200, + 0xcfc00026, 0xccc00026, 0xcd000026, 0x192807fa, 0xc01f007f, 0x7d1d0009, 0x2110007d, 0x8c001628, + 0x203c003f, 0xcfc13256, 0x8c0017f5, 0xcd013254, 0x18fc01e8, 0xcfc13248, 0x8c00185b, 0xd8413247, + 0x0b740001, 0x9b40ffd5, 0xd800004f, 0xc4bf02e9, 0x97c0ea24, 0x90000000, 0x14d4001d, 0xc4930260, + 0x7d52400e, 0xc49f0258, 0xc4a30250, 0x51dc0020, 0x7de1801a, 0x96400017, 0x7d534002, 0xc4af0270, + 0x7dae4005, 0x26640001, 0x32e0001f, 0x9a400006, 0x06ec0001, 0x96000002, 0x042c0000, 0xcec80270, + 0x8000174f, 0x0b740001, 0x8c00178a, 0x05100001, 0x9b40fff3, 0xc4af0280, 0xc4b30278, 0x52ec0020, + 0x7ef2c01a, 0x8c001608, 0xd8080278, 0xd8080280, 0xc4ab0268, 0x7daa4005, 0x26640001, 0x32a0001f, + 0x9a400005, 0x06a80001, 0x96000002, 0x24280000, 0x80001765, 0x7c410001, 0xc01f007f, 0x09540001, + 0x7d1d0009, 0x2110007d, 0x8c001628, 0xd8013256, 0x8c0017f2, 0xcd013254, 0xc4113248, 0x15100004, + 0x11100004, 0xc4b3034b, 0x7f13000a, 0xcf013248, 0xc4930260, 0x8c001855, 0x32a4001f, 0xd8413247, + 0xd800004f, 0x09100001, 0x06a80001, 0x96400002, 0x24280000, 0xcd080260, 0xce880268, 0x9940ffc0, + 0x7c408001, 0x88000000, 0x7ec28001, 0x8c001628, 0x32e0001f, 0xc4253247, 0x26640001, 0x9640005e, + 0xc4293265, 0xc4253255, 0xc431324f, 0x7e72400c, 0x26a80040, 0x9a400002, 0x9680fff7, 0xc429325b, + 0x1aa4003f, 0x96400049, 0x1aa400e8, 0x32680003, 0x9a800046, 0x32640002, 0x9640000a, 0xc4293260, + 0x1aa400e4, 0x32640004, 0x96400040, 0xc425325d, 0x26640010, 0x9a40fffe, 0x800017e2, 0xcdc00013, + 0xc027ffff, 0x2e6400ff, 0xc429325b, 0x7e6a4009, 0xce41325b, 0xc429325b, 0x26a800ff, 0x9a80fffe, + 0xd8c00033, 0xc4240009, 0x26640008, 0x9640fffe, 0x19e403e6, 0x26680003, 0x12a80004, 0x26640003, + 0x12640003, 0x7ea68001, 0x19e400e8, 0x7ea68001, 0x12640001, 0x7ea68001, 0x06a80002, 0xd8400013, + 0x19e40064, 0x32640002, 0x96400009, 0x16a40005, 0x06640003, 0xce412082, 0xcc01203f, 0xd8400013, + 0xcc01203f, 0x0a640003, 0x800017d0, 0x16a40005, 0xce412082, 0xcc01203f, 0xd8400013, 0xcc01203f, + 0x12640005, 0x7ea64002, 0xc4292083, 0x7ea68005, 0x26a80001, 0x9a80ffdf, 0xd8c00034, 0xcdc00013, + 0xc425325d, 0x26640010, 0x9a40fffe, 0xc429325b, 0x26a400ff, 0x9a40ffca, 0xd841325d, 0x2024007b, + 0xce41325b, 0x800017e3, 0xd841325d, 0xc4a70280, 0xc4ab0278, 0x52640020, 0x7e6a401a, 0x04280001, + 0x7eae8014, 0x7e6a401a, 0x56680020, 0xce480278, 0xce880280, 0x06ec0001, 0x96000002, 0x042c0000, + 0xcec80270, 0x90000000, 0x7c438001, 0x7c420001, 0x800017fe, 0xc4bf02e9, 0x9bc00006, 0x7c438001, + 0x7c420001, 0xcf800026, 0xce000026, 0x800017fe, 0xc43b02eb, 0xc42302ec, 0xcf813245, 0xce013246, + 0x52200020, 0x7fa3801a, 0x47b8020c, 0x15e00008, 0x1220000a, 0x2a206032, 0x513c001e, 0x7e3e001a, + 0xc4bf02e9, 0x9bc00005, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0x8000180f, 0xcd400013, 0xc4313267, + 0x1b3c0077, 0x1b300199, 0x7ff3000a, 0x1330000a, 0x2b300032, 0x043c3000, 0xcfc13267, 0xc43d3267, + 0xd200000b, 0xc4200007, 0xd3800002, 0xcf000002, 0xd8000040, 0x96000002, 0xd8400040, 0xd8400018, + 0x043c2000, 0xcfc13267, 0xd8000018, 0xd8800010, 0xcdc00013, 0x7dc30001, 0xdc1e0000, 0x04380032, + 0xcf80000e, 0x8c001427, 0xcc413248, 0xc43d3269, 0x27fc000f, 0x33fc0003, 0x97c00011, 0x043c001f, + 0xdfc30000, 0xd4413249, 0x7c43c001, 0x7c43c001, 0x043c0024, 0x0bfc0021, 0xdfc30000, 0xd441326a, + 0x173c0008, 0x1b300303, 0x7f3f0001, 0x043c0001, 0x7ff3c004, 0xcfc13084, 0x80001842, 0x043c0024, + 0xdfc30000, 0xd4413249, 0x7c43c001, 0x23fc003f, 0xcfc1326d, 0x0bb80026, 0xdf830000, 0xd441326e, + 0x7c438001, 0x7c438001, 0xc4393265, 0x1fb8ffc6, 0xddc30000, 0xcf813265, 0x9a000003, 0xcdc0000c, + 0x80001852, 0xcdc0000d, 0xce000010, 0x8c00142b, 0x90000000, 0x7c41c001, 0x7c420001, 0xcdc13252, + 0xce013253, 0x8c001628, 0x80001878, 0xc49f02e9, 0x99c00018, 0x7c41c001, 0x7c420001, 0xcdc13252, + 0xce013253, 0xc43c000e, 0x2bfc0008, 0xcfc00013, 0x043c3000, 0xcfc13267, 0xc43d3267, 0x97c0ffff, + 0xcdc00026, 0xce000026, 0xd8400027, 0xc41c0012, 0x99c0ffff, 0xc43c000e, 0x2bfc0008, 0xcfc00013, + 0x043c2000, 0xcfc13267, 0x8c001628, 0x80001878, 0xc41f02ed, 0xc42302ee, 0xcdc13252, 0xce013253, + 0x04200001, 0x7e2a0004, 0xce013084, 0x90000000, 0x28340001, 0x313c0bcc, 0x9bc00010, 0x393c051f, + 0x9bc00004, 0x3d3c050e, 0x9bc0000c, 0x97c0000c, 0x393c0560, 0x9bc00004, 0x3d3c054f, 0x9bc00007, + 0x97c00007, 0x393c1538, 0x9bc00005, 0x3d3c1537, 0x9bc00002, 0x97c00002, 0x2b740800, 0x90000000, + 0xc40c000e, 0x28cc0008, 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c40c001, 0x18e8007c, 0x7c42c001, + 0x06a8189a, 0x86800000, 0x8000189e, 0x800018c5, 0x800018f2, 0x8000016a, 0x7c414001, 0x18d0007e, + 0x50580020, 0x09200001, 0x7d59401a, 0xd1400072, 0xc8140072, 0x09240002, 0x7c418001, 0x7c41c001, + 0x99000011, 0xc4340004, 0xd8400013, 0xd8400008, 0xc42130b5, 0x1a24002c, 0x9a40fffe, 0x2020002c, + 0xc418000d, 0x1198001c, 0x10cc0004, 0x14cc0004, 0x7cd8c00a, 0xccc130b7, 0xce0130b5, 0xcf400008, + 0x80000168, 0xd1400025, 0x5978073a, 0x2bb80002, 0xcf800024, 0xcd800026, 0xcdc00026, 0xd8400027, + 0x9600e8a8, 0xc4300012, 0x9b00ffff, 0x9640e8a5, 0x800018a9, 0x04140000, 0xc55b0309, 0x3d5c0010, + 0x05540001, 0x2598ffff, 0x09780001, 0x7dad800c, 0x99c0ffd2, 0x9580fff9, 0xc4970258, 0xc4930250, + 0x51540020, 0x7d15001a, 0x04140020, 0x04280000, 0x442c0000, 0x65180001, 0x09540001, 0x55100001, + 0x9580000b, 0x8c001628, 0xc41d3248, 0x04300001, 0x7f2b0014, 0x25dc000f, 0x7df9c00c, 0x95c00004, + 0x7ef2c01a, 0xd8c13260, 0xd901325d, 0x06a80001, 0x9940fff1, 0x04140020, 0x04280000, 0x66d80001, + 0x09540001, 0x56ec0001, 0x95800005, 0x8c001628, 0xc421325d, 0x26240007, 0x9a40fffe, 0x06a80001, + 0x9940fff7, 0x8000189e, 0x04140020, 0x04280000, 0x09540001, 0x8c001628, 0xc41d3254, 0xc023007f, + 0x19e4003e, 0x7de1c009, 0x7dee000c, 0x96400008, 0x96000007, 0xd8c13260, 0xd901325d, 0xc421325d, + 0x261c0007, 0x99c0fffe, 0x8000189e, 0x06a80001, 0x9940fff0, 0x8000189e, 0xc40c000e, 0x28cc0008, + 0xccc00013, 0xc43d3265, 0x1bc800ea, 0x7c40c001, 0x18e00064, 0x06281911, 0x14f4001d, 0x24cc0003, + 0x86800000, 0x80001915, 0x800019af, 0x80001a2b, 0x8000016a, 0xcc48032b, 0xcc480333, 0xcc48033b, + 0xcc480343, 0x98800011, 0xc4213246, 0xc4253245, 0x52200020, 0x7e26401a, 0x46640400, 0xc4313267, + 0x04203000, 0xce013267, 0xc4213267, 0x9a000001, 0x1b3c0057, 0x1b200213, 0x1b300199, 0x7e3e000a, + 0x7e32000a, 0xce000024, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, 0xc4b30278, + 0x52ec0020, 0x7ef2c01a, 0x04180000, 0x04140020, 0x04280000, 0x7f438001, 0x8c001628, 0xc41d3247, + 0x25dc0001, 0x95c00068, 0xc4213254, 0x1a1c003e, 0x95c00065, 0xc01f007f, 0x7e1e0009, 0x97800062, + 0x0bb80001, 0x43bc0008, 0x7fcbc001, 0xc7df032b, 0x7e1fc00c, 0x97c0fffa, 0x043c0101, 0x94c00002, + 0x043c0102, 0xc439325b, 0x1bb0003f, 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, + 0x97000009, 0xc4393260, 0x1bb000e4, 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, + 0x80001994, 0x8c001628, 0xc033ffff, 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, + 0x27b800ff, 0x9b80fffe, 0xd8c00033, 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27380003, + 0x13b80004, 0x27300003, 0x13300003, 0x7fb38001, 0x19f000e8, 0x7fb38001, 0x13300001, 0x7fb38001, + 0x07b80002, 0xd8400013, 0x19f00064, 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, + 0xcc01203f, 0xd8400013, 0xcc01203f, 0x0b300003, 0x80001982, 0x17b00005, 0xcf012082, 0xcc01203f, + 0xd8400013, 0xcc01203f, 0x13300005, 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, + 0xd8c00034, 0xcdc00013, 0xc431325d, 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffcb, + 0xcfc1325d, 0x2030007b, 0xcf01325b, 0x80001995, 0xcfc1325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, + 0x98800009, 0x41bc0007, 0x53fc0002, 0x7e7fc011, 0xd3c00025, 0xd8000026, 0xd8400027, 0xc43c0012, + 0x9bc0ffff, 0x653c0001, 0x7dbd8001, 0x06a80001, 0x09540001, 0x55100001, 0x9940ff8f, 0xc43c000e, + 0x2bfc0008, 0xcfc00013, 0x043c2000, 0xcfc13267, 0xd8080278, 0xd8080280, 0x80000168, 0x7c410001, + 0x04140000, 0xc55b0309, 0x3d5c0010, 0x2598ffff, 0x05540001, 0x7d91800c, 0x95c00003, 0xd4400078, + 0x80000168, 0x9580fff8, 0x09780001, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, + 0xc4b30278, 0x52ec0020, 0x7ef2c01a, 0x04140020, 0x04280000, 0x65180001, 0x09540001, 0x55100001, + 0x9580005d, 0x8c001628, 0xc4253247, 0x26640001, 0x04200101, 0x96400058, 0x7dc24001, 0xc41d3248, + 0x25dc000f, 0x7df9c00c, 0x95c00053, 0x94c00002, 0x04200102, 0x7e41c001, 0xc425325b, 0x1a70003f, + 0x97000049, 0x1a7000e8, 0x33240003, 0x9a400046, 0x33300002, 0x9700000a, 0xc4253260, 0x1a7000e4, + 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x80001a21, 0xcdc00013, 0xc033ffff, + 0x2f3000ff, 0xc425325b, 0x7f270009, 0xcf01325b, 0xc425325b, 0x266400ff, 0x9a40fffe, 0xd8c00033, + 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27240003, 0x12640004, 0x27300003, 0x13300003, + 0x7e724001, 0x19f000e8, 0x7e724001, 0x13300001, 0x7e724001, 0x06640002, 0xd8400013, 0x19f00064, + 0x33300002, 0x97000009, 0x16700005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, + 0x0b300003, 0x80001a0f, 0x16700005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, 0x13300005, + 0x7e730002, 0xc4252083, 0x7e724005, 0x26640001, 0x9a40ffdf, 0xd8c00034, 0xcdc00013, 0xc431325d, + 0x27300010, 0x9b00fffe, 0xc425325b, 0x267000ff, 0x9b00ffca, 0xce01325d, 0x2030007b, 0xcf01325b, + 0x80001a22, 0xce01325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0x06a80001, 0x9940ff9f, 0xd4400078, + 0xd8080278, 0xd8080280, 0x80000168, 0x8c001a31, 0xd4400078, 0xd8080278, 0xd8080280, 0x7c408001, + 0x88000000, 0xc4213246, 0xc4253245, 0x52200020, 0x7e26401a, 0x46640400, 0xc4313267, 0x04203000, + 0xce013267, 0xc4213267, 0x9a000001, 0x1b180057, 0x1b200213, 0x1b300199, 0x7e1a000a, 0x7e32000a, + 0xce000024, 0xc4970258, 0xc4930250, 0x51540020, 0x7d15001a, 0xc4af0280, 0xc4b30278, 0x52ec0020, + 0x7ef2c01a, 0x04140020, 0x04280000, 0x65180001, 0x95800060, 0x8c001628, 0xc4193247, 0x25980001, + 0x04200101, 0x94c00005, 0x30f00005, 0x04200005, 0x9b000002, 0x04200102, 0x95800056, 0xc439325b, + 0x1bb0003f, 0x97000049, 0x1bb000e8, 0x33380003, 0x9b800046, 0x33300002, 0x9700000a, 0xc4393260, + 0x1bb000e4, 0x33300004, 0x97000040, 0xc431325d, 0x27300010, 0x9b00fffe, 0x80001aa2, 0xcdc00013, + 0xc033ffff, 0x2f3000ff, 0xc439325b, 0x7f3b0009, 0xcf01325b, 0xc439325b, 0x27b800ff, 0x9b80fffe, + 0xd8c00033, 0xc4300009, 0x27300008, 0x9700fffe, 0x19f003e6, 0x27380003, 0x13b80004, 0x27300003, + 0x13300003, 0x7fb38001, 0x19f000e8, 0x7fb38001, 0x13300001, 0x7fb38001, 0x07b80002, 0xd8400013, + 0x19f00064, 0x33300002, 0x97000009, 0x17b00005, 0x07300003, 0xcf012082, 0xcc01203f, 0xd8400013, + 0xcc01203f, 0x0b300003, 0x80001a90, 0x17b00005, 0xcf012082, 0xcc01203f, 0xd8400013, 0xcc01203f, + 0x13300005, 0x7fb30002, 0xc4392083, 0x7fb38005, 0x27b80001, 0x9b80ffdf, 0xd8c00034, 0xcdc00013, + 0xc431325d, 0x27300010, 0x9b00fffe, 0xc439325b, 0x27b000ff, 0x9b00ffca, 0xce01325d, 0x2030007b, + 0xcf00325b, 0x80001aa3, 0xce01325d, 0x04300001, 0x7f2b0014, 0x7ef2c01a, 0xc49b02e9, 0x99800005, + 0xd2400025, 0x4664001c, 0xd8000026, 0xd8400027, 0x06a80001, 0x09540001, 0x55100001, 0x9940ff9c, + 0xc49b02e9, 0x99800008, 0xc430000e, 0x2b300008, 0xcf000013, 0x04302000, 0xcf013267, 0xc4313267, + 0x97000001, 0x90000000, 0x244c00ff, 0xcc4c0200, 0x7c408001, 0x88000000, 0xc44f0200, 0xc410000b, + 0xc414000c, 0x7d158010, 0x059cc000, 0xd8400013, 0xccdd0000, 0x7c408001, 0x88000000, 0xc40c0037, + 0x94c0ffff, 0xcc000049, 0xc40c003a, 0x94c0ffff, 0x7c40c001, 0x24d00001, 0x9500e69a, 0x18d0003b, + 0x18d40021, 0x99400006, 0xd840004a, 0xc40c003c, 0x94c0ffff, 0x14cc0001, 0x94c00028, 0xd8000033, + 0xc438000b, 0xc43c0009, 0x27fc0001, 0x97c0fffe, 0xd8400013, 0xd841c07f, 0xc43dc07f, 0x1bfc0078, + 0x7ffbc00c, 0x97c0fffd, 0x99000004, 0xc0120840, 0x282c0040, 0x80001ae8, 0xc0121841, 0x282c001a, + 0xcd01c07c, 0xcc01c07d, 0xcc01c08c, 0xcc01c079, 0xcc01c07e, 0x04200004, 0xcec0001b, 0xd8400021, + 0x0a200001, 0x9a00ffff, 0xc425c07f, 0x166c001f, 0x04200004, 0x9ac0fffb, 0xc434000f, 0x9b40ffff, + 0xd801c07f, 0xd8400013, 0xc425c07f, 0xce400078, 0xd8000034, 0x9940e66b, 0xd800004a, 0x7c408001, + 0x88000000, 0xc40c0036, 0x24d00001, 0x9900fffe, 0x18cc0021, 0xccc00047, 0xcc000046, 0xc40c0039, + 0x94c0ffff, 0xc40c003d, 0x98c0ffff, 0x7c40c001, 0x24d003ff, 0x18d47fea, 0x18d87ff4, 0xcd00004c, + 0xcd40004e, 0xcd80004d, 0xd8400013, 0xcd41c405, 0xc02a0001, 0x2aa80001, 0xce800013, 0xcd01c406, + 0xcc01c406, 0xcc01c406, 0xc40c0006, 0x98c0ffff, 0xc414000e, 0x29540008, 0x295c0001, 0xcd400013, + 0xd8c1325e, 0xcdc0001a, 0x11980002, 0x4110000c, 0xc0160800, 0x7d15000a, 0xc0164010, 0xd8400013, + 0xcd41c078, 0xcc01c080, 0xcc01c081, 0xcd81c082, 0xcc01c083, 0xcd01c084, 0xc40c0006, 0x98c0ffff, + 0xd8400048, 0xc40c003b, 0x94c0ffff, 0x80000c16, 0xd8400013, 0xd801c40a, 0xd901c40d, 0xd801c410, + 0xd801c40e, 0xd801c40f, 0xc40c0040, 0x04140001, 0x09540001, 0x9940ffff, 0x04140096, 0xd8400013, + 0xccc1c400, 0xc411c401, 0x9500fffa, 0xc424003e, 0x04d00001, 0x11100002, 0xcd01c40c, 0xc0180034, + 0xcd81c411, 0xd841c414, 0x0a540001, 0xcd41c412, 0x2468000f, 0xc419c416, 0x41980003, 0xc41c003f, + 0x7dda0001, 0x12200002, 0x10cc0002, 0xccc1c40c, 0xd901c411, 0xce41c412, 0xd8800013, 0xce292e40, + 0xcc412e01, 0xcc412e02, 0xcc412e03, 0xcc412e00, 0x80000aa7, 0xc43c0007, 0xdc120000, 0x31144000, + 0x95400005, 0xdc030000, 0xd800002a, 0xcc3c000c, 0x80001b70, 0x33f80003, 0xd4400078, 0x9780e601, + 0x188cfff0, 0x04e40002, 0x80001190, 0x7c408001, 0x88000000, 0xc424005e, 0x96400006, 0x90000000, + 0xc424005e, 0x96400003, 0x7c408001, 0x88000000, 0x80001b74, 0x80000168, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0x92100004, 0x92110501, 0x92120206, 0x92130703, 0x92100400, 0x92110105, 0x92120602, 0x92130307, + 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 7440 +}; + +static const PWR_DFY_Section pwr_virus_section4 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x54106500, + .dfy_data = { + 0x7e000200, 0x7e020204, 0xc00a0505, 0x00000000, 0xbf8c007f, 0xb8900904, 0xb8911a04, 0xb8920304, + 0xb8930b44, 0x921c0d0c, 0x921c1c13, 0x921d0c12, 0x811c1d1c, 0x811c111c, 0x921cff1c, 0x00000400, + 0x921dff10, 0x00000100, 0x81181d1c, 0x7e040218, 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050002, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0701000, 0x80050102, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, 0xe0501000, 0x80050302, + 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 240 +}; + +static const PWR_DFY_Section pwr_virus_section5 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x54106900, + .dfy_data = { + 0x7e080200, 0x7e100204, 0xbefc00ff, 0x00010000, 0x24200087, 0x262200ff, 0x000001f0, 0x20222282, + 0x28182111, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, 0x0000040c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd81a0000, + 0x0000080c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, 0x1100000c, 0xd86c0000, + 0x1100000c, 0xbf810000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 384 +}; + +static const PWR_DFY_Section pwr_virus_section6 = { + .dfy_cntl = 0x80000004, + .dfy_addr_hi = 0x000000b4, + .dfy_addr_lo = 0x54116f00, + .dfy_data = { + 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4540fe8, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000041, 0x0000000c, 0x00000000, 0x07808000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54116f00, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, + 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, + 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb454105e, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x000000c0, 0x00000010, 0x00000000, 0x07808000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54117300, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, + 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, + 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4541065, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000500, 0x0000001c, 0x00000000, 0x07808000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54117700, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, + 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, + 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0xc0310800, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000040, 0x00000001, 0x00000001, 0x00000001, 0x00000000, 0xb4541069, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000444, 0x0000008a, 0x00000000, 0x07808000, 0xffffffff, + 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0xaaaaaaaa, 0x55555555, 0x55555555, 0x55555555, + 0x55555555, 0x00000000, 0x00000000, 0x540fee40, 0x000000b4, 0x00000010, 0x00000001, 0x00000004, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x54117b00, 0x000000b4, 0x00000000, 0x00000000, 0x00005301, 0x00000000, 0x00000000, 0x00000000, + 0xb4540fef, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x540fee20, 0x000000b4, 0x00000000, + 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + .dfy_size = 1024 +}; -static const PWR_Command_Table pwr_virus_table[PWR_VIRUS_TABLE_SIZE] = { - { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, - { PwrCmdWrite, 0x00000002, mmRLC_SRM_CNTL }, - { PwrCmdWrite, 0x15000000, mmCP_ME_CNTL }, - { PwrCmdWrite, 0x50000000, mmCP_MEC_CNTL }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x0840800a, mmCP_RB0_CNTL }, - { PwrCmdWrite, 0xf30fff0f, mmTCC_CTRL }, - { PwrCmdWrite, 0x00000002, mmTCC_EXE_DISABLE }, - { PwrCmdWrite, 0x000000ff, mmTCP_ADDR_CONFIG }, - { PwrCmdWrite, 0x540ff000, mmCP_CPC_IC_BASE_LO }, - { PwrCmdWrite, 0x000000b4, mmCP_CPC_IC_BASE_HI }, - { PwrCmdWrite, 0x00010000, mmCP_HYP_MEC1_UCODE_ADDR }, - { PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00221408, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00591260, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00621387, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, - { PwrCmdWrite, 0x00010000, mmCP_HYP_MEC2_UCODE_ADDR }, - { PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00221408, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00591260, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00621387, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x540fe800, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e020201, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e040204, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e060205, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54106f00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000400b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00004000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00804fac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x540fef00, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0xc0031502, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00001e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x540ff000, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000145, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080061, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24ccffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3cd08000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1cd0ffcf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x050c0019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x84c00000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000067, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000006a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000006d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000008f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000099, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800000a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800000af, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x388c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08880002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98800003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000002d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d808001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc0700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0d000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000005d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d00011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01b10, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x280c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x280c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x280c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca88004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc00006f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28180080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd4c0380, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdcc0388, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55dc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdcc038c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce0c0390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce0c0394, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4c0398, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4c039c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce8c03a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56a80020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce8c03a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcecc03a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcecc03ac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0c03b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0c03b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4c03b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4c03bc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8c03c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57b80020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8c03c4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfcc03c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57fc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfcc03cc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05dc002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc12009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d200a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc012009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25e01c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25e40300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25e800c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25ec003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e25c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31100006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4df0388, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d7038c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d5dc01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4e30390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d70394, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d62001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4e70398, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d7039c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d66401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4eb03a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d6a801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ef03a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703ac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d6ec01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4f303b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d73001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4f703b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703bc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d77401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4fb03c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703c4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d7b801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ff03c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d703cc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d7fc01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4d70380, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0e0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0085, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc006a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400051, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04180018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aac0027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04080002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000367, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9880fff3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04080010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80c0309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80c0319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9880fffc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d4001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x155c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e80180, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900091a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280196, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d4fe04, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800001b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000032b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000350, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000352, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000035f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000701, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000047c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000019f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d98001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0044, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9400036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840006d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11540015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1998003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af0007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15dc000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d65400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a38003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd5c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7df1c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800045, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411326a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc415326b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000056, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00059, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c8000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40005a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29988000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000073, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00005f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26f00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15100010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af07fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04343000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf413267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd1c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0160, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc810001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b4c0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f4f400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55180020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af4007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33740003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ae8003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413348, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x958000d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000315, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04303000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1714000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25540800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x459801b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d77400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c01e2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e5c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1334e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01334f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413350, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813351, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd881334d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153274, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cdcc011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05900008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00006a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0006b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d594002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc12e23, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd012e24, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc12e25, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b340057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b280213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980198, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20cc003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01e0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2d540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x078c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001239, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04f80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd5c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840007c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c018a6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e22, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800007c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c018a2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd4c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680fffc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540188f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc013cfff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x38d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdcc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01882, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000304, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x49980198, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x459801a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000329, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16ec001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1998003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce00000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a18003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24dc00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31e00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95801827, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14dc0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800006d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a0000ad, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04080000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af4003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca88005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24880001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f4b4009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313274, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d33400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1eecffdd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800003c3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa80030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a8004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e80042, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e8e800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de9c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce8c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd30011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11e80007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd300001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240059, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1660001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e320009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0328000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e72400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0430000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02ac000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d310002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa87600, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280222, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4280058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x22ec003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8380018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57b00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04343108, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2374007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32a80003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800003e7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980104, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x49980104, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800003f2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf41326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x254c0700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a641fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0726, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a640200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1237b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8813260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4280034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01755, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde830000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0174c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bb80040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100044, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19180024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x551c003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000043d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c8000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840006c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28200000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000043f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282000f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195c00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5e124dc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e624001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980158, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x49980158, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980170, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16200010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1154000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e80488, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f807f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e40077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ec0199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000048e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000494, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000685, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000686, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800006ac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ccc001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1264000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d79400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e7a400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52a8001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec0028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004cc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419324e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26e8003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d324d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d290004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f8f4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f52800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50e00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004d1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0dc002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f534002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004d7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3257, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e804e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004e7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800004f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000505, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640fff4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26edf000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05a80507, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000050c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000528, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000057d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800005c2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800005f3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1be00fe4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000066, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ed6c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113271, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193272, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d51401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253276, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400061, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2730000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7db1800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00062, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000063, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400065, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b680213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46ec0188, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26e01000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c131fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x192007ec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x69dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de20014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x561c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013344, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13345, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2010007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2010003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013344, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013345, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180050, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280042, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813273, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13275, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00124f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46ec0190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2154003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bd800e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f598004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1be800e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801327a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800005f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xda000068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540002d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1be000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc63124dc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fc14001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000697, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25100007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31100005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900008e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a9feff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d30b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00ac006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28880700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0006de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30d4000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41530b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19980028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800006c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8380023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa38011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd3800025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202400d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000712, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e80714, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000071c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000720, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000747, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000071d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800007c4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000732, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000745, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000744, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a64008c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0fff1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000723, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41f02f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000743, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffde, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc8000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195800e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dd7fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1a001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46200200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04283247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af80057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af40213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6f400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc6990000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x329c325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x329c3269, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x329c3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01defff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d8009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000078a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fff2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03e7ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3f0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03e4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d30b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bf0003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000b80, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x203c003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46200008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31980002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19580066, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0120001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11980003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da18001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d24db, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580137b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00ee000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113269, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19080070, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x190c00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2518000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05a80809, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000080e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000080f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000898, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000946, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800009e1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04a80811, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000815, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000834, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3045, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c091, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000241, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02f0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4252087, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5668001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00021d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001a41, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43b02f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56f00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x950001fa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aec0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a40006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de6000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10e40008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2110003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d10ff9e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0245301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801325f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0121fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29108eff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0127ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0131fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0100010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd2400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0180003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd1c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04a8089a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000089e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800008fa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31300022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x964012a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02620c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000903, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31240022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ec30011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32f80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x67180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bfc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd981325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000915, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c1325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0fff6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f818001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001606, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d838001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16240014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a2801f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00075e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f40014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33e80010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680ffec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04a80948, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000094c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000099b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x964011fe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0260800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dda801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e838011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001802, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x469c0390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4280011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0014df, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31280014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce8802ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800062, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31280034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04a809e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800009ec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a45, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e72401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04383000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b38007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4598001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4002eb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4002ec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4002ed, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4002ee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001715, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffbc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a55, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x233c0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0130b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49302ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5198001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193269, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53b8001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7db9801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000a5e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01106, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c010fd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce4c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc80c0072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x58e801fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc01e2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e5c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x44cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55900020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x44cc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd812e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd012e02, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd412e03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1e64001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ab1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a0010ac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd880003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d403f7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41b0367, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d85800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280adc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000af1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000adf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ae7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd8d2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d803f7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11940014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29544001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29544003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000af4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd44d2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd44dc000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd8d2c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000b0a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd44d2c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28148004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4593240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0105e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef3400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14e80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a8000af, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c01043, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a01fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3620005c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2464003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc6290ce7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16ac001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ac003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ee6c00d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00fff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000367, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640102e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c0037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a00035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0005d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16f8001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9780000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc035f0ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e764009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19b401f8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ae4003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000b7c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a4003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc01e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13fc0018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dbd800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d98ff15, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x592c00fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd80000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12e00016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x592c007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12e00015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1264001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1620000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12e4001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5924007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013257, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00fdb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9780f5ca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07740003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x269c003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e4004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f67000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f674002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab8c006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000bec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000b47, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a8004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc415325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18580037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x262001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d54001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd280200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd680208, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcda80210, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc6930200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc6970208, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc69b0210, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd900003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd940003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9400040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14fc0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24f800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d83c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24e000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x321c0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580ffee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c30, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9480000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800f29, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800f23, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800f1a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9600f502, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0f500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000f05, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16e4001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640f4f4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33740002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40f4f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00ac005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00e0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc8000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28884900, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ff3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400ee1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c40a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c40c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c40d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d0007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15580010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x255400ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c411, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c40f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c40e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c410, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e80033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ec0034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c414, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c415, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c413, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c030011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c038011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431c417, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435c416, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c419, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc418, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf413261, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013262, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13263, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813264, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc0030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d77000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51b80020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f97801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ca7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc0031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435c40b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4280032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000cf4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc032800b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d42011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800e6c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x596001fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ce0c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x505c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e800c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x122c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d1f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d57, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0328009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04143000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e51001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d2d0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19640057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19580213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19600199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da6400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04142000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d80034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280d83, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d8a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000db1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000dbc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e010001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d75400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580f3d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x526c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2ec01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5ae0073a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580f3c6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc3a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980fff5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01c405, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd441c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580f3b1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580f3a5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00da7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5aac007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12d80017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56a00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e82400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e58c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19d4003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20880188, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20240090, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ac0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ac0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b301ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0001a2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2220003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18fc0034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24e8000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80e71, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000edd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ea1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000eaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e7c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e87, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000e8f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9e001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213262, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253261, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213264, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253263, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e82005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da1801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1800072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8180072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x59a001fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421c401, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c401, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ede, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db09001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db09011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5a10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5a50000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280eea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f11, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f2e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f1f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0f26f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7daec01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5af8073a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eba800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0f25c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c405, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0f24e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40f247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0f240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ef2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db09002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3db09012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c034001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c038001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f88, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e52401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1334000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24e02000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f63400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000f9d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51e40020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13380016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e00039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1220001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31140005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31140006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05280fb7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28140002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fc2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fd1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e80039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52a8003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140004b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x159c0011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31a00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31a40001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e25800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0fff5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fff4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d100010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01326f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0340008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000ffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x208801a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000102f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1cccfe08, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00b33, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da2400f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da28002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1ac002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d2ac002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3ef40010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40f11d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde410000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde010000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c024001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100086, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5510003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001075, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d520002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cde0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e20001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001071, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00b01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc200000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc40003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4080029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a400e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12500009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x248c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x200c006d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x200c0228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18881fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d4072c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc00d1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3094000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x38d80000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x311c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30940007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1620001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010c4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x259c007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a00030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x199c0fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000aac, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07a810d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000104c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x200c007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28240007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x192400fd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06681110, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19180070, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19100078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f40058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001117, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001118, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000112d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001130, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001133, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc81c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02a0200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e8e8009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x22a8003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x22a80074, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2774001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13740014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eb6800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25ecffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55700020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15f40010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13740002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x275c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15dc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc1c01e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e62000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001165, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1a0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e0d000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95000007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e02401e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05d80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc2401e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da2000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9600ffe6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce00001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x22640435, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0528117e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x312c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001185, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a0400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d81c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19a000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de2c00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc420007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011a3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d654001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c020001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011b6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253279, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2730003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3b380006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3f38000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0430000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb10004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e57000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e578002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d67c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0be40001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d3a4002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x202c002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e640010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce81325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07a811cf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00feb8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x954009a7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f0012f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f40612, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc00c1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cf7400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x39600004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0140004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18fc003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011ee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a6c003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800011e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ac007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab00030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aac0fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001205, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a2800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a0800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a4000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30d00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000052, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640090f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19180038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab0c006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000127f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d3258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313257, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab0c012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f67800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0012e1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x964008d7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9800036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300677, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012aa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a8002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7edec00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4140032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1858003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0cc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d407f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d5d4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d52000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d514002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d958001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd5c002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc1325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1ccc001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd980003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9800040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd9c00040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800051, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b74003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50700020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04e81324, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d71401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x596401fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b74008d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a640000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000132c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000133b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001344, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42530b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a68003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2024003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11980014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d19000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8240011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffe0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf81a2a4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c007eb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d0d001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x591c01fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45140210, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x595801fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11980009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a307fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x23304076, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc00e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0015, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4514020c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a2001e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a204001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a64003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15dc000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dcdc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5dc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45140248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013257, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0434000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdb000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013259, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0337fff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f220009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d01c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f01c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8240072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd240001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19682011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5a6c01fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eeac00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfa0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4380007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d40038, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9540073d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18c80066, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30880001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4220000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24e80007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24ec0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5310000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001465, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18f02011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5aec01fc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a8146a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1f0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f334002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000147b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e024001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000144a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fbfc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94800007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800014a9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0328007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03a0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45dc0390, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c428001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c430001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a0800fd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x109c000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce080228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9880000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0ec75, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52a80020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc80260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80288, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf080290, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf0802a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4802a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc802b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80802b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x178c000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b8003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cf8c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8802c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc802c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8802d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf8802d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25b8ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd2800c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5230309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e3a400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001539, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd880353, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b0353, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd14005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000154f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd080238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d200008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd900309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd910ce7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4190ce6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d918005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d918004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd810ce6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdd1054f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000156e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x090c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdcd050e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x110c0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41230a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41230b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41230c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc41230d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc480329, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc48032a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc4802e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09940001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x44100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x69100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000157f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970290, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b0288, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49f0298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x041c0040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dcdc002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d924019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d26400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001579, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d010021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d914019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd480298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd8802a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10d40010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12180016, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc51f0309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d95800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d62000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdd00309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce113320, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18dc01e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9400e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c0001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015aa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a302b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12240004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab02a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4c0319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d9d8002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea14005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015bc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d25000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fff4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd0d3330, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce0802b8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd8802b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab02e0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa807f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f02d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49702d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02c8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49f02c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96800028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d4e000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9600000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d964002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cde4002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de94001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd64002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800015cd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d698002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd4802d8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x129c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc50f0319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11a0000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1198000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd953300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e0e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a8000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce953301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce100319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b70280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73800a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x536c0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9780eb68, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001609, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30b40000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b400011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b70258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53780020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb3801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7faf8019, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x67b40001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x57b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bb0260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fab8001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf880260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66f40001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4353247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7f4009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fff7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x269c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a00018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a00060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x269c0018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a40060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11dc0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b70228, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f514005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001644, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd080240, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f130005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001688, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f130004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01051e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42d051f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ed2c005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96c0fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01051f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5170309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195c07f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x196007f6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04340001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x6b740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001665, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a702a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab0298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f634014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8113320, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce480298, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce8802a0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc5170319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b702b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x255c000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f5f4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8113330, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf4802b0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11340001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x195c07e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x196007ee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8353300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1e4001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8353301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce4802d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8100309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc48f0250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd4c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x64d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580005c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd2000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7df5c00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800016f1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a7003e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a700064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800016df, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800016f2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18fc0064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00042, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dd9801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf0258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53fc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e7e401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x667c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eebc00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x43300007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7db30011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd3000025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc03ec005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfca200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x203c003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0017f5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18fc01e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00185b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40ffd5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0ea24, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14d4001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d52400e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49f0258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a30250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400017, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d534002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dae4005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000174f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00178a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40fff3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab0268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7daa4005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32a0001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001765, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8013256, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c0017f2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b3034b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f13000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001855, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32a4001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd080260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce880268, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ffc0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ec28001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253255, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431324f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e72400c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9680fff7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa4003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32680003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a800046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4293260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1aa400e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017e2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc027ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2e6400ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a4009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4240009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e403e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26680003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12a80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e400e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e40064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a640003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017d0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea64002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4292083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ea68005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a80ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26a400ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2024007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017e3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4a70280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4ab0278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7eae8014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce480278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce880280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43b02eb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42302ec, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fa3801a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x47b8020c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x15e00008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1220000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2a206032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x513c001e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e3e001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000180f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b3c0077, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd200000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd3800002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc30001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04380032, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf80000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc413248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3269, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33fc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bfc0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd441326a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x173c0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300303, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3f0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ff3c004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001842, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x23fc003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1326d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd441326e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1fb8ffc6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xddc30000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001852, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49f02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c00018, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c0012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41f02ed, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42302ee, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e2a0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x313c0bcc, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x393c051f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d3c050e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x393c0560, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d3c054f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x393c1538, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d3c1537, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b740800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e8007c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a8189a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800018c5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800018f2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0007e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09240002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc42130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a24002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14cc0004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7cd8c00a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc130b7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce0130b5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bb80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf800024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9600e8a8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9640e8a5, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800018a9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dad800c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0ffd2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fff9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x442c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940fff1, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26240007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940fff7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc023007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19e4003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7de1c009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dee000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96000007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x261c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940fff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18e00064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06281911, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24cc0003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001915, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x800019af, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a2b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc48032b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc480333, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc48033b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc480343, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98800011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b3c0057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e3e000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04180000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f438001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00068, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213254, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a1c003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00065, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1e0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97800062, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x43bc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fcbc001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc7df032b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1fc00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0101, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c0102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001994, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001982, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffcb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001995, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98800009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x41bc0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x53fc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e7fc011, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd3c00025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x653c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dbd8001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ff8f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d91800c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580fff8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9580005d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400058, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95c00053, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e41c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a70003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33240003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a400046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1a7000e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a21, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f270009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x266400ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27240003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06640002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a0f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e730002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4252083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e724005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a40ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x267000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a22, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ff9f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001a31, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b180057, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e1a000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x30f00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95800056, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001aa2, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001a90, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf00325b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001aa3, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd2400025, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4664001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99800008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2b300008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf000013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x244c00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc4c0200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc44f0200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc410000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d158010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x059cc000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccdd0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0037, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000049, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c003a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500e69a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d0003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d40021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd840004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c003c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x14cc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c00028, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0120840, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282c0040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001ae8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0121841, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x282c001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c07c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9ac0fffb, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940e66b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800004a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0036, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9900fffe, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18cc0021, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc00047, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc000046, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0039, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c003d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24d003ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d47fea, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x18d87ff4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd00004c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd40004e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd80004d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c405, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x295c0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcdc0001a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11980002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x4110000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0160800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7d15000a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0164010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c080, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c084, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400048, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c003b, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c40a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901c40d, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c410, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c40e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd801c40f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc40c0040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9940ffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04140096, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc411c401, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9500fffa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424003e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04d00001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x11100002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd01c40c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0180034, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd81c411, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd841c414, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0a540001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x2468000f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc419c416, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x41980003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc41c003f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7dda0001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x12200002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x10cc0002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xccc1c40c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd901c411, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce41c412, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xce292e40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc120000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x31144000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xcc3c000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x9780e601, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x188cfff0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x04e40002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x96400003, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80001b74, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x54106500, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e020204, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc00a0505, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf8c007f, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb8900904, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb8911a04, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb8920304, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb8930b44, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921c0d0c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921c1c13, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921d0c12, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x811c1d1c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x811c111c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921cff1c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000400, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x921dff10, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000100, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x81181d1c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e040218, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x54106900, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0x7e080200, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x7e100204, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbefc00ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00010000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x24200087, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x262200ff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000001f0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x20222282, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x28182111, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, - { PwrCmdWrite, 0x54116f00, mmCP_DFY_ADDR_LO }, - { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fe8, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000041, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000000c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54116f00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb454105e, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000c0, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54117300, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4541065, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000500, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000001c, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54117700, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4541069, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000444, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x0000008a, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x54117b00, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, - { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL }, - { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x54116f00, mmCP_MQD_BASE_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, - { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x54117300, mmCP_MQD_BASE_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, - { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x54117700, mmCP_MQD_BASE_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, - { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x54117b00, mmCP_MQD_BASE_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, - { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, - { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, - { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, - { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, - { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, - { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, - { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000104, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000204, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000304, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000404, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000504, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000604, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000704, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000105, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000205, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000305, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000405, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000505, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000605, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000705, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000106, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000206, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000306, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000406, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000506, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000606, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000706, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000107, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000207, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000307, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000407, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000507, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000607, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000707, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000008, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000108, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000208, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000308, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000408, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000508, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000608, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000708, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000009, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000109, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000209, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000309, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000409, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000509, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000609, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000709, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, - { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, - { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, - { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, - { PwrCmdWrite, 0x01010101, mmCP_PQ_WPTR_POLL_CNTL1 }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, - { PwrCmdEnd, 0x00000000, 0x00000000 }, +static const PWR_Command_Table pwr_virus_table_post[] = { + { 0x00000000, mmCP_MEC_CNTL }, + { 0x00000000, mmCP_MEC_CNTL }, + { 0x00000004, mmSRBM_GFX_CNTL }, + { 0x54116f00, mmCP_MQD_BASE_ADDR }, + { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { 0xb4540fef, mmCP_HQD_PQ_BASE }, + { 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { 0x00010000, mmCP_HQD_VMID }, + { 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { 0x00000005, mmSRBM_GFX_CNTL }, + { 0x54117300, mmCP_MQD_BASE_ADDR }, + { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { 0xb4540fef, mmCP_HQD_PQ_BASE }, + { 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { 0x00010000, mmCP_HQD_VMID }, + { 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { 0x00000006, mmSRBM_GFX_CNTL }, + { 0x54117700, mmCP_MQD_BASE_ADDR }, + { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { 0xb4540fef, mmCP_HQD_PQ_BASE }, + { 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { 0x00010000, mmCP_HQD_VMID }, + { 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { 0x00000007, mmSRBM_GFX_CNTL }, + { 0x54117b00, mmCP_MQD_BASE_ADDR }, + { 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { 0xb4540fef, mmCP_HQD_PQ_BASE }, + { 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { 0x00010000, mmCP_HQD_VMID }, + { 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { 0x00000004, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000104, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000204, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000304, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000404, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000504, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000604, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000704, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000005, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000105, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000205, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000305, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000405, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000505, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000605, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000705, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000006, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000106, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000206, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000306, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000406, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000506, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000606, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000706, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000007, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000107, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000207, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000307, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000407, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000507, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000607, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000707, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000008, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000108, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000208, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000308, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000408, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000508, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000608, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000708, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000009, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000109, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000209, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000309, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000409, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000509, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000609, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000709, mmSRBM_GFX_CNTL }, + { 0x00000000, mmCP_HQD_ACTIVE }, + { 0x00000000, mmCP_HQD_PQ_RPTR }, + { 0x00000000, mmCP_HQD_PQ_WPTR }, + { 0x00000001, mmCP_HQD_ACTIVE }, + { 0x00000004, mmSRBM_GFX_CNTL }, + { 0x01010101, mmCP_PQ_WPTR_POLL_CNTL1 }, + { 0x00000000, mmGRBM_STATUS }, + { 0x00000000, mmGRBM_STATUS }, + { 0x00000000, mmGRBM_STATUS }, + { 0x00000000, 0xFFFFFFFF }, }; diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h index 25fb1460a194..7d1eec5d2e7a 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h @@ -25,10 +25,7 @@ #include "hwmgr.h" -#define PP_VALID 0x1F1F1F1F - struct pp_instance { - uint32_t pp_valid; uint32_t chip_family; uint32_t chip_id; bool pm_en; diff --git a/drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h index 901c960cfe21..2b3497135bbd 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/rv_ppsmc.h @@ -70,7 +70,12 @@ #define PPSMC_MSG_SetPhyclkVoltageByFreq 0x26 #define PPSMC_MSG_SetDppclkVoltageByFreq 0x27 #define PPSMC_MSG_SetSoftMinVcn 0x28 -#define PPSMC_Message_Count 0x29 +#define PPSMC_MSG_GetGfxclkFrequency 0x2A +#define PPSMC_MSG_GetFclkFrequency 0x2B +#define PPSMC_MSG_GetMinGfxclkFrequency 0x2C +#define PPSMC_MSG_GetMaxGfxclkFrequency 0x2D +#define PPSMC_MSG_SoftReset 0x2E +#define PPSMC_Message_Count 0x2F typedef uint16_t PPSMC_Result; diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h index 7c9aba81cd6a..b1b27b2128f6 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h @@ -75,6 +75,11 @@ enum SMU_MEMBER { VceBootLevel, SamuBootLevel, LowSclkInterruptThreshold, + DRAM_LOG_ADDR_H, + DRAM_LOG_ADDR_L, + DRAM_LOG_PHY_ADDR_H, + DRAM_LOG_PHY_ADDR_L, + DRAM_LOG_BUFF_SIZE, }; diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h index cb070ebc7de1..247c97397a27 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h @@ -124,12 +124,15 @@ typedef uint16_t PPSMC_Result; #define PPSMC_MSG_NumOfDisplays 0x56 #define PPSMC_MSG_ReadSerialNumTop32 0x58 #define PPSMC_MSG_ReadSerialNumBottom32 0x59 +#define PPSMC_MSG_SetSystemVirtualDramAddrHigh 0x5A +#define PPSMC_MSG_SetSystemVirtualDramAddrLow 0x5B #define PPSMC_MSG_RunAcgBtc 0x5C #define PPSMC_MSG_RunAcgInClosedLoop 0x5D #define PPSMC_MSG_RunAcgInOpenLoop 0x5E #define PPSMC_MSG_InitializeAcg 0x5F #define PPSMC_MSG_GetCurrPkgPwr 0x61 -#define PPSMC_Message_Count 0x62 +#define PPSMC_MSG_UpdatePkgPwrPidAlpha 0x68 +#define PPSMC_Message_Count 0x69 typedef int PPSMC_Msg; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile index a423c0a85129..b24b0f203a51 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile +++ b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile @@ -2,9 +2,9 @@ # Makefile for the 'smu manager' sub-component of powerplay. # It provides the smu management services for the driver. -SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o fiji_smc.o \ - polaris10_smumgr.o iceland_smumgr.o polaris10_smc.o tonga_smc.o \ - smu7_smumgr.o iceland_smc.o vega10_smumgr.o rv_smumgr.o ci_smc.o ci_smumgr.o +SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o \ + polaris10_smumgr.o iceland_smumgr.o \ + smu7_smumgr.o vega10_smumgr.o rv_smumgr.o ci_smumgr.o AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR)) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.c deleted file mode 100644 index 9ee14315dce7..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.c +++ /dev/null @@ -1,2753 +0,0 @@ -/* - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/fb.h> -#include "linux/delay.h" -#include <linux/types.h> - -#include "smumgr.h" -#include "pp_debug.h" -#include "ci_smc.h" -#include "ci_smumgr.h" -#include "ppsmc.h" -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "atombios.h" -#include "pppcielanes.h" - -#include "smu/smu_7_0_1_d.h" -#include "smu/smu_7_0_1_sh_mask.h" - -#include "dce/dce_8_0_d.h" -#include "dce/dce_8_0_sh_mask.h" - -#include "bif/bif_4_1_d.h" -#include "bif/bif_4_1_sh_mask.h" - -#include "gca/gfx_7_2_d.h" -#include "gca/gfx_7_2_sh_mask.h" - -#include "gmc/gmc_7_1_d.h" -#include "gmc/gmc_7_1_sh_mask.h" - -#include "processpptables.h" - -#define MC_CG_ARB_FREQ_F0 0x0a -#define MC_CG_ARB_FREQ_F1 0x0b -#define MC_CG_ARB_FREQ_F2 0x0c -#define MC_CG_ARB_FREQ_F3 0x0d - -#define SMC_RAM_END 0x40000 - -#define VOLTAGE_SCALE 4 -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 -#define CISLAND_MINIMUM_ENGINE_CLOCK 800 -#define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5 - -static const struct ci_pt_defaults defaults_hawaii_xt = { - 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000, - { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, - { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } -}; - -static const struct ci_pt_defaults defaults_hawaii_pro = { - 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062, - { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, - { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } -}; - -static const struct ci_pt_defaults defaults_bonaire_xt = { - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, - { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, - { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } -}; - - -static const struct ci_pt_defaults defaults_saturn_xt = { - 1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x70000, - { 0x8C, 0x247, 0x249, 0xA6, 0x80, 0x81, 0x8B, 0x89, 0x86, 0xC9, 0xCA, 0xC9, 0x4D, 0x4D, 0x4D }, - { 0x187, 0x187, 0x187, 0x1C7, 0x1C7, 0x1C7, 0x210, 0x210, 0x210, 0x266, 0x266, 0x266, 0x2C9, 0x2C9, 0x2C9 } -}; - - -static int ci_set_smc_sram_address(struct pp_hwmgr *hwmgr, - uint32_t smc_addr, uint32_t limit) -{ - if ((0 != (3 & smc_addr)) - || ((smc_addr + 3) >= limit)) { - pr_err("smc_addr invalid \n"); - return -EINVAL; - } - - cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, smc_addr); - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); - return 0; -} - -static int ci_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, - const uint8_t *src, uint32_t byte_count, uint32_t limit) -{ - int result; - uint32_t data = 0; - uint32_t original_data; - uint32_t addr = 0; - uint32_t extra_shift; - - if ((3 & smc_start_address) - || ((smc_start_address + byte_count) >= limit)) { - pr_err("smc_start_address invalid \n"); - return -EINVAL; - } - - addr = smc_start_address; - - while (byte_count >= 4) { - /* Bytes are written into the SMC address space with the MSB first. */ - data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; - - result = ci_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); - - src += 4; - byte_count -= 4; - addr += 4; - } - - if (0 != byte_count) { - - data = 0; - - result = ci_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - - original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); - - extra_shift = 8 * (4 - byte_count); - - while (byte_count > 0) { - /* Bytes are written into the SMC addres space with the MSB first. */ - data = (0x100 * data) + *src++; - byte_count--; - } - - data <<= extra_shift; - - data |= (original_data & ~((~0UL) << extra_shift)); - - result = ci_set_smc_sram_address(hwmgr, addr, limit); - - if (0 != result) - return result; - - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); - } - - return 0; -} - - -static int ci_program_jump_on_start(struct pp_hwmgr *hwmgr) -{ - static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 }; - - ci_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1); - - return 0; -} - -bool ci_is_smc_ram_running(struct pp_hwmgr *hwmgr) -{ - return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) - && (0x20100 <= cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, ixSMC_PC_C))); -} - -static int ci_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, - uint32_t *value, uint32_t limit) -{ - int result; - - result = ci_set_smc_sram_address(hwmgr, smc_addr, limit); - - if (result) - return result; - - *value = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); - return 0; -} - -int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) -{ - int ret; - - if (!ci_is_smc_ram_running(hwmgr)) - return -EINVAL; - - cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); - - PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); - - ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); - - if (ret != 1) - pr_info("\n failed to send message %x ret is %d\n", msg, ret); - - return 0; -} - -int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter) -{ - cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); - return ci_send_msg_to_smc(hwmgr, msg); -} - -static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct cgs_system_info sys_info = {0}; - uint32_t dev_id; - - sys_info.size = sizeof(struct cgs_system_info); - sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; - cgs_query_system_info(hwmgr->device, &sys_info); - dev_id = (uint32_t)sys_info.value; - - switch (dev_id) { - case 0x67BA: - case 0x66B1: - smu_data->power_tune_defaults = &defaults_hawaii_pro; - break; - case 0x67B8: - case 0x66B0: - smu_data->power_tune_defaults = &defaults_hawaii_xt; - break; - case 0x6640: - case 0x6641: - case 0x6646: - case 0x6647: - smu_data->power_tune_defaults = &defaults_saturn_xt; - break; - case 0x6649: - case 0x6650: - case 0x6651: - case 0x6658: - case 0x665C: - case 0x665D: - case 0x67A0: - case 0x67A1: - case 0x67A2: - case 0x67A8: - case 0x67A9: - case 0x67AA: - case 0x67B9: - case 0x67BE: - default: - smu_data->power_tune_defaults = &defaults_bonaire_xt; - break; - } -} - -static int ci_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, - uint32_t clock, uint32_t *vol) -{ - uint32_t i = 0; - - if (allowed_clock_voltage_table->count == 0) - return -EINVAL; - - for (i = 0; i < allowed_clock_voltage_table->count; i++) { - if (allowed_clock_voltage_table->entries[i].clk >= clock) { - *vol = allowed_clock_voltage_table->entries[i].v; - return 0; - } - } - - *vol = allowed_clock_voltage_table->entries[i - 1].v; - return 0; -} - -static int ci_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU7_Discrete_GraphicsLevel *sclk) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t ref_clock; - uint32_t ref_divider; - uint32_t fbdiv; - int result; - - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ - ref_clock = atomctrl_get_reference_clock(hwmgr); - ref_divider = 1 + dividers.uc_pll_ref_div; - - /* low 14 bits is fraction and high 12 bits is divider */ - fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; - - /* SPLL_FUNC_CNTL setup */ - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_REF_DIV, dividers.uc_pll_ref_div); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_PDIV_A, dividers.uc_pll_post_div); - - /* SPLL_FUNC_CNTL_3 setup*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, - SPLL_FB_DIV, fbdiv); - - /* set to use fractional accumulation*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, - SPLL_DITHEN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { - struct pp_atomctrl_internal_ss_info ss_info; - uint32_t vco_freq = clock * dividers.uc_pll_post_div; - - if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, - vco_freq, &ss_info)) { - uint32_t clk_s = ref_clock * 5 / - (ref_divider * ss_info.speed_spectrum_rate); - uint32_t clk_v = 4 * ss_info.speed_spectrum_percentage * - fbdiv / (clk_s * 10000); - - cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, - CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); - cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, - CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); - cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, - CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); - } - } - - sclk->SclkFrequency = clock; - sclk->CgSpllFuncCntl3 = spll_func_cntl_3; - sclk->CgSpllFuncCntl4 = spll_func_cntl_4; - sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; - sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; - sclk->SclkDid = (uint8_t)dividers.pll_post_divider; - - return 0; -} - -static void ci_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, - const struct phm_phase_shedding_limits_table *pl, - uint32_t sclk, uint32_t *p_shed) -{ - unsigned int i; - - /* use the minimum phase shedding */ - *p_shed = 1; - - for (i = 0; i < pl->count; i++) { - if (sclk < pl->entries[i].Sclk) { - *p_shed = i; - break; - } - } -} - -static uint8_t ci_get_sleep_divider_id_from_clock(uint32_t clock, - uint32_t clock_insr) -{ - uint8_t i; - uint32_t temp; - uint32_t min = min_t(uint32_t, clock_insr, CISLAND_MINIMUM_ENGINE_CLOCK); - - if (clock < min) { - pr_info("Engine clock can't satisfy stutter requirement!\n"); - return 0; - } - for (i = CISLAND_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { - temp = clock >> i; - - if (temp >= min || i == 0) - break; - } - return i; -} - -static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t clock, uint16_t sclk_al_threshold, - struct SMU7_Discrete_GraphicsLevel *level) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - - result = ci_calculate_sclk_params(hwmgr, clock, level); - - /* populate graphics levels */ - result = ci_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddc_dependency_on_sclk, clock, - (uint32_t *)(&level->MinVddc)); - if (result) { - pr_err("vdd_dep_on_sclk table is NULL\n"); - return result; - } - - level->SclkFrequency = clock; - level->MinVddcPhases = 1; - - if (data->vddc_phase_shed_control) - ci_populate_phase_value_based_on_sclk(hwmgr, - hwmgr->dyn_state.vddc_phase_shed_limits_table, - clock, - &level->MinVddcPhases); - - level->ActivityLevel = sclk_al_threshold; - level->CcPwrDynRm = 0; - level->CcPwrDynRm1 = 0; - level->EnabledForActivity = 0; - /* this level can be used for throttling.*/ - level->EnabledForThrottle = 1; - level->UpH = 0; - level->DownH = 0; - level->VoltageDownH = 0; - level->PowerThrottle = 0; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) - level->DeepSleepDivId = - ci_get_sleep_divider_id_from_clock(clock, - CISLAND_MINIMUM_ENGINE_CLOCK); - - /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ - level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - if (0 == result) { - level->MinVddc = PP_HOST_TO_SMC_UL(level->MinVddc * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_UL(level->MinVddcPhases); - CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); - } - - return result; -} - -int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result = 0; - uint32_t array = smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) * - SMU7_MAX_LEVELS_GRAPHICS; - struct SMU7_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t i; - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - result = ci_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - (uint16_t)smu_data->activity_target[i], - &levels[i]); - if (result) - return result; - if (i > 1) - smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; - if (i == (dpm_table->sclk_table.count - 1)) - smu_data->smc_state_table.GraphicsLevel[i].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - } - - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; - - smu_data->smc_state_table.GraphicsDpmLevelCount = (u8)dpm_table->sclk_table.count; - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - result = ci_copy_bytes_to_smc(hwmgr, array, - (u8 *)levels, array_size, - SMC_RAM_END); - - return result; - -} - -static int ci_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; - smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int ci_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; - - tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->tdc_vddc_throttle_release_limit_perc; - smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; - - return 0; -} - -static int ci_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (ci_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else - smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; - - return 0; -} - -static int ci_populate_fuzzy_fan(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - uint16_t tmp; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) - || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) - tmp = hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity; - else - tmp = hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = CONVERT_FROM_HOST_TO_SMC_US(tmp); - - return 0; -} - -static int ci_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) -{ - int i; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; - uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; - uint8_t *hi2_vid = smu_data->power_tune_table.BapmVddCVidHiSidd2; - - PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, - "The CAC Leakage table does not exist!", return -EINVAL); - PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, - "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); - PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, - "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); - - for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { - lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); - hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); - hi2_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc3); - } else { - lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc); - hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Leakage); - } - } - - return 0; -} - -static int ci_populate_vddc_vid(struct pp_hwmgr *hwmgr) -{ - int i; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint8_t *vid = smu_data->power_tune_table.VddCVid; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, - "There should never be more than 8 entries for VddcVid!!!", - return -EINVAL); - - for (i = 0; i < (int)data->vddc_voltage_table.count; i++) - vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); - - return 0; -} - -static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - u8 *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; - u8 *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; - int i, min, max; - - min = max = hi_vid[0]; - for (i = 0; i < 8; i++) { - if (0 != hi_vid[i]) { - if (min > hi_vid[i]) - min = hi_vid[i]; - if (max < hi_vid[i]) - max = hi_vid[i]; - } - - if (0 != lo_vid[i]) { - if (min > lo_vid[i]) - min = lo_vid[i]; - if (max < lo_vid[i]) - max = lo_vid[i]; - } - } - - if ((min == 0) || (max == 0)) - return -EINVAL; - smu_data->power_tune_table.GnbLPMLMaxVid = (u8)max; - smu_data->power_tune_table.GnbLPMLMinVid = (u8)min; - - return 0; -} - -static int ci_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; - - HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(HiSidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(LoSidd); - - return 0; -} - -static int ci_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - int ret = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) { - pr_err("Attempt to get pm_fuse_table_offset Failed!\n"); - return -EINVAL; - } - - /* DW0 - DW3 */ - ret = ci_populate_bapm_vddc_vid_sidd(hwmgr); - /* DW4 - DW5 */ - ret |= ci_populate_vddc_vid(hwmgr); - /* DW6 */ - ret |= ci_populate_svi_load_line(hwmgr); - /* DW7 */ - ret |= ci_populate_tdc_limit(hwmgr); - /* DW8 */ - ret |= ci_populate_dw8(hwmgr, pm_fuse_table_offset); - - ret |= ci_populate_fuzzy_fan(hwmgr, pm_fuse_table_offset); - - ret |= ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(hwmgr); - - ret |= ci_populate_bapm_vddc_base_leakage_sidd(hwmgr); - if (ret) - return ret; - - ret = ci_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - sizeof(struct SMU7_Discrete_PmFuses), SMC_RAM_END); - } - return ret; -} - -static int ci_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU7_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); - struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; - struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; - const uint16_t *def1, *def2; - int i, j, k; - - dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); - dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); - - dpm_table->DTETjOffset = 0; - dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; - - if (ppm) { - dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; - dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; - } else { - dpm_table->PPM_PkgPwrLimit = 0; - dpm_table->PPM_TemperatureLimit = 0; - } - - CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); - CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); - - dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); - def1 = defaults->bapmti_r; - def2 = defaults->bapmti_rc; - - for (i = 0; i < SMU7_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU7_DTE_SOURCES; j++) { - for (k = 0; k < SMU7_DTE_SINKS; k++) { - dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); - dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); - def1++; - def2++; - } - } - } - - return 0; -} - -static int ci_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, - pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, - uint16_t *lo) -{ - uint16_t v_index; - bool vol_found = false; - *hi = tab->value * VOLTAGE_SCALE; - *lo = tab->value * VOLTAGE_SCALE; - - PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, - "The SCLK/VDDC Dependency Table does not exist.\n", - return -EINVAL); - - if (NULL == hwmgr->dyn_state.cac_leakage_table) { - pr_warn("CAC Leakage Table does not exist, using vddc.\n"); - return 0; - } - - for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { - if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { - vol_found = true; - if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { - *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); - } else { - pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); - *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); - } - break; - } - } - - if (!vol_found) { - for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { - if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { - vol_found = true; - if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { - *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; - } else { - pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); - *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); - } - break; - } - } - - if (!vol_found) - pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); - } - - return 0; -} - -static int ci_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, - pp_atomctrl_voltage_table_entry *tab, - SMU7_Discrete_VoltageLevel *smc_voltage_tab) -{ - int result; - - result = ci_get_std_voltage_value_sidd(hwmgr, tab, - &smc_voltage_tab->StdVoltageHiSidd, - &smc_voltage_tab->StdVoltageLoSidd); - if (result) { - smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; - smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; - } - - smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); - CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageLoSidd); - - return 0; -} - -static int ci_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - unsigned int count; - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->VddcLevelCount = data->vddc_voltage_table.count; - for (count = 0; count < table->VddcLevelCount; count++) { - result = ci_populate_smc_voltage_table(hwmgr, - &(data->vddc_voltage_table.entries[count]), - &(table->VddcLevel[count])); - PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); - - /* GPIO voltage control */ - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) - table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low; - else - table->VddcLevel[count].Smio = 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); - - return 0; -} - -static int ci_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - int result; - - table->VddciLevelCount = data->vddci_voltage_table.count; - - for (count = 0; count < table->VddciLevelCount; count++) { - result = ci_populate_smc_voltage_table(hwmgr, - &(data->vddci_voltage_table.entries[count]), - &(table->VddciLevel[count])); - PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low; - else - table->VddciLevel[count].Smio |= 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); - - return 0; -} - -static int ci_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - int result; - - table->MvddLevelCount = data->mvdd_voltage_table.count; - - for (count = 0; count < table->MvddLevelCount; count++) { - result = ci_populate_smc_voltage_table(hwmgr, - &(data->mvdd_voltage_table.entries[count]), - &table->MvddLevel[count]); - PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) - table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low; - else - table->MvddLevel[count].Smio |= 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); - - return 0; -} - - -static int ci_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result; - - result = ci_populate_smc_vddc_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate VDDC voltage table to SMC", return -EINVAL); - - result = ci_populate_smc_vdd_ci_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate VDDCI voltage table to SMC", return -EINVAL); - - result = ci_populate_smc_mvdd_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate MVDD voltage table to SMC", return -EINVAL); - - return 0; -} - -static int ci_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU7_Discrete_Ulv *state) -{ - uint32_t voltage_response_time, ulv_voltage; - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); - PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); - - if (ulv_voltage == 0) { - data->ulv_supported = false; - return 0; - } - - if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { - /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ - if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) - state->VddcOffset = 0; - else - /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ - state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); - } else { - /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ - if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) - state->VddcOffsetVid = 0; - else /* used in SVI2 Mode */ - state->VddcOffsetVid = (uint8_t)( - (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) - * VOLTAGE_VID_OFFSET_SCALE2 - / VOLTAGE_VID_OFFSET_SCALE1); - } - state->VddcPhase = 1; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int ci_populate_ulv_state(struct pp_hwmgr *hwmgr, - SMU7_Discrete_Ulv *ulv_level) -{ - return ci_populate_ulv_level(hwmgr, ulv_level); -} - -static int ci_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint32_t i; - -/* Index dpm_table->pcie_speed_table.count is reserved for PCIE boot level.*/ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = - (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = 1; - table->LinkLevel[i].DownT = PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpT = PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - -static int ci_calculate_mclk_params( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU7_Discrete_MemoryLevel *mclk, - bool strobe_mode, - bool dllStateOn - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; - uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; - uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; - uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; - uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; - uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; - uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; - - pp_atomctrl_memory_clock_param mpll_param; - int result; - - result = atomctrl_get_memory_pll_dividers_si(hwmgr, - memory_clock, &mpll_param, strobe_mode); - PP_ASSERT_WITH_CODE(0 == result, - "Error retrieving Memory Clock Parameters from VBIOS.", return result); - - mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); - - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); - - mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, - MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); - - if (data->is_memory_gddr5) { - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { - pp_atomctrl_internal_ss_info ss_info; - uint32_t freq_nom; - uint32_t tmp; - uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); - - /* for GDDR5 for all modes and DDR3 */ - if (1 == mpll_param.qdr) - freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); - else - freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); - - /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ - tmp = (freq_nom / reference_clock); - tmp = tmp * tmp; - - if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { - uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; - uint32_t clkv = - (uint32_t)((((131 * ss_info.speed_spectrum_percentage * - ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); - - mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); - mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); - } - } - - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); - - - mclk->MclkFrequency = memory_clock; - mclk->MpllFuncCntl = mpll_func_cntl; - mclk->MpllFuncCntl_1 = mpll_func_cntl_1; - mclk->MpllFuncCntl_2 = mpll_func_cntl_2; - mclk->MpllAdFuncCntl = mpll_ad_func_cntl; - mclk->MpllDqFuncCntl = mpll_dq_func_cntl; - mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; - mclk->DllCntl = dll_cntl; - mclk->MpllSs1 = mpll_ss1; - mclk->MpllSs2 = mpll_ss2; - - return 0; -} - -static uint8_t ci_get_mclk_frequency_ratio(uint32_t memory_clock, - bool strobe_mode) -{ - uint8_t mc_para_index; - - if (strobe_mode) { - if (memory_clock < 12500) - mc_para_index = 0x00; - else if (memory_clock > 47500) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); - } else { - if (memory_clock < 65000) - mc_para_index = 0x00; - else if (memory_clock > 135000) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); - } - - return mc_para_index; -} - -static uint8_t ci_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) -{ - uint8_t mc_para_index; - - if (memory_clock < 10000) - mc_para_index = 0; - else if (memory_clock >= 80000) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); - - return mc_para_index; -} - -static int ci_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, - uint32_t memory_clock, uint32_t *p_shed) -{ - unsigned int i; - - *p_shed = 1; - - for (i = 0; i < pl->count; i++) { - if (memory_clock < pl->entries[i].Mclk) { - *p_shed = i; - break; - } - } - - return 0; -} - -static int ci_populate_single_memory_level( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU7_Discrete_MemoryLevel *memory_level - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int result = 0; - bool dll_state_on; - struct cgs_display_info info = {0}; - uint32_t mclk_edc_wr_enable_threshold = 40000; - uint32_t mclk_edc_enable_threshold = 40000; - uint32_t mclk_strobe_mode_threshold = 40000; - - if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { - result = ci_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); - } - - if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { - result = ci_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddci_dependency_on_mclk, - memory_clock, - &memory_level->MinVddci); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); - } - - if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) { - result = ci_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.mvdd_dependency_on_mclk, - memory_clock, - &memory_level->MinMvdd); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddci voltage value from memory MVDD voltage dependency table", return result); - } - - memory_level->MinVddcPhases = 1; - - if (data->vddc_phase_shed_control) { - ci_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, - memory_clock, &memory_level->MinVddcPhases); - } - - memory_level->EnabledForThrottle = 1; - memory_level->EnabledForActivity = 1; - memory_level->UpH = 0; - memory_level->DownH = 100; - memory_level->VoltageDownH = 0; - - /* Indicates maximum activity level for this performance level.*/ - memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target; - memory_level->StutterEnable = 0; - memory_level->StrobeEnable = 0; - memory_level->EdcReadEnable = 0; - memory_level->EdcWriteEnable = 0; - memory_level->RttEnable = 0; - - /* default set to low watermark. Highest level will be set to high later.*/ - memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - cgs_get_active_displays_info(hwmgr->device, &info); - data->display_timing.num_existing_displays = info.display_count; - - /* stutter mode not support on ci */ - - /* decide strobe mode*/ - memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && - (memory_clock <= mclk_strobe_mode_threshold); - - /* decide EDC mode and memory clock ratio*/ - if (data->is_memory_gddr5) { - memory_level->StrobeRatio = ci_get_mclk_frequency_ratio(memory_clock, - memory_level->StrobeEnable); - - if ((mclk_edc_enable_threshold != 0) && - (memory_clock > mclk_edc_enable_threshold)) { - memory_level->EdcReadEnable = 1; - } - - if ((mclk_edc_wr_enable_threshold != 0) && - (memory_clock > mclk_edc_wr_enable_threshold)) { - memory_level->EdcWriteEnable = 1; - } - - if (memory_level->StrobeEnable) { - if (ci_get_mclk_frequency_ratio(memory_clock, 1) >= - ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - else - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; - } else - dll_state_on = data->dll_default_on; - } else { - memory_level->StrobeRatio = - ci_get_ddr3_mclk_frequency_ratio(memory_clock); - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - } - - result = ci_calculate_mclk_params(hwmgr, - memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); - - if (0 == result) { - memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); - memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); - memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); - /* MCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); - /* Indicates maximum activity level for this performance level.*/ - CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); - } - - return result; -} - -int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result; - struct cgs_system_info sys_info = {0}; - uint32_t dev_id; - - uint32_t level_array_address = smu_data->dpm_table_start + offsetof(SMU7_Discrete_DpmTable, MemoryLevel); - uint32_t level_array_size = sizeof(SMU7_Discrete_MemoryLevel) * SMU7_MAX_LEVELS_MEMORY; - SMU7_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", return -EINVAL); - result = ci_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.MemoryLevel[i])); - if (0 != result) - return result; - } - - smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; - - sys_info.size = sizeof(struct cgs_system_info); - sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; - cgs_query_system_info(hwmgr->device, &sys_info); - dev_id = (uint32_t)sys_info.value; - - if ((dpm_table->mclk_table.count >= 2) - && ((dev_id == 0x67B0) || (dev_id == 0x67B1))) { - smu_data->smc_state_table.MemoryLevel[1].MinVddci = - smu_data->smc_state_table.MemoryLevel[0].MinVddci; - smu_data->smc_state_table.MemoryLevel[1].MinMvdd = - smu_data->smc_state_table.MemoryLevel[0].MinMvdd; - } - smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; - data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - - result = ci_copy_bytes_to_smc(hwmgr, - level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -static int ci_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, - SMU7_Discrete_VoltageLevel *voltage) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { - if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { - /* Always round to higher voltage. */ - voltage->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - - PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, - "MVDD Voltage is outside the supported range.", return -EINVAL); - - } else { - return -EINVAL; - } - - return 0; -} - -static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = 0; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - - SMU7_Discrete_VoltageLevel voltage_level; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - - - /* The ACPI state should not do DPM on DC (or ever).*/ - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - if (data->acpi_vddc) - table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); - else - table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); - - table->ACPILevel.MinVddcPhases = data->vddc_phase_shed_control ? 0 : 1; - /* assign zero for now*/ - table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, - table->ACPILevel.SclkFrequency, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", return result); - - /* divider ID for required SCLK*/ - table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; - table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - table->ACPILevel.DeepSleepDivId = 0; - - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); - spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, - CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); - - table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; - table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; - table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - /* For various features to be enabled/disabled while this level is active.*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - /* SCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - - /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ - table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; - table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; - else { - if (data->acpi_vddci != 0) - table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); - } - - if (0 == ci_populate_mvdd_value(hwmgr, 0, &voltage_level)) - table->MemoryACPILevel.MinMvdd = - PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinMvdd = 0; - - /* Force reset on DLL*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); - - /* Disable DLL in ACPIState*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); - - /* Enable DLL bypass signal*/ - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK0_BYPASS, 0); - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK1_BYPASS, 0); - - table->MemoryACPILevel.DllCntl = - PP_HOST_TO_SMC_UL(dll_cntl); - table->MemoryACPILevel.MclkPwrmgtCntl = - PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); - table->MemoryACPILevel.MpllAdFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); - table->MemoryACPILevel.MpllDqFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl_1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); - table->MemoryACPILevel.MpllFuncCntl_2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); - table->MemoryACPILevel.MpllSs1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); - table->MemoryACPILevel.MpllSs2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpH = 0; - table->MemoryACPILevel.DownH = 100; - table->MemoryACPILevel.VoltageDownH = 0; - /* Indicates maximum activity level for this performance level.*/ - table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); - - table->MemoryACPILevel.StutterEnable = 0; - table->MemoryACPILevel.StrobeEnable = 0; - table->MemoryACPILevel.EdcReadEnable = 0; - table->MemoryACPILevel.EdcWriteEnable = 0; - table->MemoryACPILevel.RttEnable = 0; - - return result; -} - -static int ci_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = 0; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_uvd_clock_voltage_dependency_table *uvd_table = - hwmgr->dyn_state.uvd_clock_voltage_dependency_table; - - table->UvdLevelCount = (uint8_t)(uvd_table->count); - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].VclkFrequency = - uvd_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = - uvd_table->entries[count].dclk; - table->UvdLevel[count].MinVddc = - uvd_table->entries[count].v * VOLTAGE_SCALE; - table->UvdLevel[count].MinVddcPhases = 1; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].VclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Vclk clock", return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Dclk clock", return result); - - table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(table->UvdLevel[count].MinVddc); - } - - return result; -} - -static int ci_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_vce_clock_voltage_dependency_table *vce_table = - hwmgr->dyn_state.vce_clock_voltage_dependency_table; - - table->VceLevelCount = (uint8_t)(vce_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = vce_table->entries[count].evclk; - table->VceLevel[count].MinVoltage = - vce_table->entries[count].v * VOLTAGE_SCALE; - table->VceLevel[count].MinPhases = 1; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_US(table->VceLevel[count].MinVoltage); - } - return result; -} - -static int ci_populate_smc_acp_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_acp_clock_voltage_dependency_table *acp_table = - hwmgr->dyn_state.acp_clock_voltage_dependency_table; - - table->AcpLevelCount = (uint8_t)(acp_table->count); - table->AcpBootLevel = 0; - - for (count = 0; count < table->AcpLevelCount; count++) { - table->AcpLevel[count].Frequency = acp_table->entries[count].acpclk; - table->AcpLevel[count].MinVoltage = acp_table->entries[count].v; - table->AcpLevel[count].MinPhases = 1; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->AcpLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for engine clock", return result); - - table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_US(table->AcpLevel[count].MinVoltage); - } - return result; -} - -static int ci_populate_smc_samu_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_samu_clock_voltage_dependency_table *samu_table = - hwmgr->dyn_state.samu_clock_voltage_dependency_table; - - table->SamuBootLevel = 0; - table->SamuLevelCount = (uint8_t)(samu_table->count); - - for (count = 0; count < table->SamuLevelCount; count++) { - table->SamuLevel[count].Frequency = samu_table->entries[count].samclk; - table->SamuLevel[count].MinVoltage = samu_table->entries[count].v * VOLTAGE_SCALE; - table->SamuLevel[count].MinPhases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->SamuLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for samu clock", return result); - - table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_US(table->SamuLevel[count].MinVoltage); - } - return result; -} - -static int ci_populate_memory_timing_parameters( - struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint32_t memory_clock, - struct SMU7_Discrete_MCArbDramTimingTableEntry *arb_regs - ) -{ - uint32_t dramTiming; - uint32_t dramTiming2; - uint32_t burstTime; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - engine_clock, memory_clock); - - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); - arb_regs->McArbBurstTime = (uint8_t)burstTime; - - return 0; -} - -static int ci_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - int result = 0; - SMU7_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - - memset(&arb_regs, 0x00, sizeof(SMU7_Discrete_MCArbDramTimingTable)); - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { - result = ci_populate_memory_timing_parameters - (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, - data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - - if (0 != result) - break; - } - } - - if (0 == result) { - result = ci_copy_bytes_to_smc( - hwmgr, - smu_data->arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU7_Discrete_MCArbDramTimingTable), - SMC_RAM_END - ); - } - - return result; -} - -static int ci_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table*/ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); - - if (0 != result) { - smu_data->smc_state_table.GraphicsBootLevel = 0; - pr_err("VBIOS did not find boot engine clock value \ - in dependency table. Using Graphics DPM level 0!"); - result = 0; - } - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); - - if (0 != result) { - smu_data->smc_state_table.MemoryBootLevel = 0; - pr_err("VBIOS did not find boot engine clock value \ - in dependency table. Using Memory DPM level 0!"); - result = 0; - } - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value; - table->BootVddci = data->vbios_boot_state.vddci_bootup_value; - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; - - return result; -} - -static int ci_populate_mc_reg_address(struct pp_hwmgr *hwmgr, - SMU7_Discrete_MCRegisters *mc_reg_table) -{ - const struct ci_smumgr *smu_data = (struct ci_smumgr *)hwmgr->smu_backend; - - uint32_t i, j; - - for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { - if (smu_data->mc_reg_table.validflag & 1<<j) { - PP_ASSERT_WITH_CODE(i < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE, - "Index of mc_reg_table->address[] array out of boundary", return -EINVAL); - mc_reg_table->address[i].s0 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); - mc_reg_table->address[i].s1 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); - i++; - } - } - - mc_reg_table->last = (uint8_t)i; - - return 0; -} - -static void ci_convert_mc_registers( - const struct ci_mc_reg_entry *entry, - SMU7_Discrete_MCRegisterSet *data, - uint32_t num_entries, uint32_t valid_flag) -{ - uint32_t i, j; - - for (i = 0, j = 0; j < num_entries; j++) { - if (valid_flag & 1<<j) { - data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); - i++; - } - } -} - -static int ci_convert_mc_reg_table_entry_to_smc( - struct pp_hwmgr *hwmgr, - const uint32_t memory_clock, - SMU7_Discrete_MCRegisterSet *mc_reg_table_data - ) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint32_t i = 0; - - for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { - if (memory_clock <= - smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { - break; - } - } - - if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) - --i; - - ci_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], - mc_reg_table_data, smu_data->mc_reg_table.last, - smu_data->mc_reg_table.validflag); - - return 0; -} - -static int ci_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, - SMU7_Discrete_MCRegisters *mc_regs) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int res; - uint32_t i; - - for (i = 0; i < data->dpm_table.mclk_table.count; i++) { - res = ci_convert_mc_reg_table_entry_to_smc( - hwmgr, - data->dpm_table.mclk_table.dpm_levels[i].value, - &mc_regs->data[i] - ); - - if (0 != res) - result = res; - } - - return result; -} - -static int ci_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t address; - int32_t result; - - if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) - return 0; - - - memset(&smu_data->mc_regs, 0, sizeof(SMU7_Discrete_MCRegisters)); - - result = ci_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); - - if (result != 0) - return result; - - address = smu_data->mc_reg_table_start + (uint32_t)offsetof(SMU7_Discrete_MCRegisters, data[0]); - - return ci_copy_bytes_to_smc(hwmgr, address, - (uint8_t *)&smu_data->mc_regs.data[0], - sizeof(SMU7_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, - SMC_RAM_END); -} - -static int ci_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - memset(&smu_data->mc_regs, 0x00, sizeof(SMU7_Discrete_MCRegisters)); - result = ci_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize MCRegTable for the MC register addresses!", return result;); - - result = ci_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize MCRegTable for driver state!", return result;); - - return ci_copy_bytes_to_smc(hwmgr, smu_data->mc_reg_table_start, - (uint8_t *)&smu_data->mc_regs, sizeof(SMU7_Discrete_MCRegisters), SMC_RAM_END); -} - -static int ci_populate_smc_initial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - uint8_t count, level; - - count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); - - for (level = 0; level < count; level++) { - if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk - >= data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); - - for (level = 0; level < count; level++) { - if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk - >= data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - -static int ci_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, - SMU7_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) - table->SVI2Enable = 1; - else - table->SVI2Enable = 0; - return 0; -} - -static int ci_start_smc(struct pp_hwmgr *hwmgr) -{ - /* set smc instruct start point at 0x0 */ - ci_program_jump_on_start(hwmgr); - - /* enable smc clock */ - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); - - PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, - INTERRUPTS_ENABLED, 1); - - return 0; -} - -int ci_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - SMU7_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct pp_atomctrl_gpio_pin_assignment gpio_pin; - u32 i; - - ci_initialize_power_tune_defaults(hwmgr); - memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); - - if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) - ci_populate_smc_voltage_tables(hwmgr, table); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - if (data->ulv_supported) { - result = ci_populate_ulv_state(hwmgr, &(table->Ulv)); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ULV state!", return result); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, 0x40035); - } - - result = ci_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Graphics Level!", return result); - - result = ci_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Memory Level!", return result); - - result = ci_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Link Level!", return result); - - result = ci_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACPI Level!", return result); - - result = ci_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize VCE Level!", return result); - - result = ci_populate_smc_acp_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACP Level!", return result); - - result = ci_populate_smc_samu_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize SAMU Level!", return result); - - /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ - /* need to populate the ARB settings for the initial state. */ - result = ci_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to Write ARB settings for the initial state.", return result); - - result = ci_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize UVD Level!", return result); - - table->UvdBootLevel = 0; - table->VceBootLevel = 0; - table->AcpBootLevel = 0; - table->SamuBootLevel = 0; - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - result = ci_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot Level!", return result); - - result = ci_populate_smc_initial_state(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); - - result = ci_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); - - table->UVDInterval = 1; - table->VCEInterval = 1; - table->ACPInterval = 1; - table->SAMUInterval = 1; - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - - table->TemperatureLimitHigh = - (data->thermal_temp_setting.temperature_high * - SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - table->TemperatureLimitLow = - (data->thermal_temp_setting.temperature_low * - SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->VddcVddciDelta = 4000; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - - PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - - table->PCIeBootLinkLevel = (uint8_t)data->dpm_table.pcie_speed_table.count; - table->PCIeGenInterval = 1; - - ci_populate_smc_svi2_config(hwmgr, table); - - for (i = 0; i < SMU7_MAX_ENTRIES_SMIO; i++) - CONVERT_FROM_HOST_TO_SMC_UL(table->Smio[i]); - - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { - table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - table->VddcVddciDelta = PP_HOST_TO_SMC_US(table->VddcVddciDelta); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); - table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); - table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = ci_copy_bytes_to_smc(hwmgr, smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU7_Discrete_DpmTable)-3 * sizeof(SMU7_PIDController), - SMC_RAM_END); - - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload dpm data to SMC memory!", return result;); - - result = ci_populate_initial_mc_reg_table(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to populate initialize MC Reg table!", return result); - - result = ci_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate PM fuses to SMC memory!", return result); - - ci_start_smc(hwmgr); - - return 0; -} - -int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); - SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) - return 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (0 == ci_data->fan_table_start) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); - - if (0 == duty100) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = smu7_get_xclk(hwmgr); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); - - res = ci_copy_bytes_to_smc(hwmgr, ci_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); - - return 0; -} - -static int ci_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return ci_program_memory_timing_parameters(hwmgr); - - return 0; -} - -int ci_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (hwmgr->gfx_arbiter.sclk_threshold != - data->low_sclk_interrupt_threshold)) { - data->low_sclk_interrupt_threshold = - hwmgr->gfx_arbiter.sclk_threshold; - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = ci_copy_bytes_to_smc( - hwmgr, - smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, - LowSclkInterruptT), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - - result = ci_update_and_upload_mc_reg_table(hwmgr); - - PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); - - result = ci_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - - return result; -} - -uint32_t ci_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU7_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU7_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU7_SoftRegisters, AverageGraphicsA); - case PreVBlankGap: - return offsetof(SMU7_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU7_SoftRegisters, VBlankTimeout); - } - case SMU_Discrete_DpmTable: - switch (member) { - case LowSclkInterruptThreshold: - return offsetof(SMU7_Discrete_DpmTable, LowSclkInterruptT); - } - } - pr_debug("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -uint32_t ci_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU7_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU7_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU7_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU7_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU7_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDCI: - return SMU7_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU7_MAX_LEVELS_MVDD; - } - - pr_debug("can't get the mac of %x\n", value); - return 0; -} - -static int ci_load_smc_ucode(struct pp_hwmgr *hwmgr) -{ - uint32_t byte_count, start_addr; - uint8_t *src; - uint32_t data; - - struct cgs_firmware_info info = {0}; - - cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info); - - hwmgr->is_kicker = info.is_kicker; - byte_count = info.image_size; - src = (uint8_t *)info.kptr; - start_addr = info.ucode_start_address; - - if (byte_count > SMC_RAM_END) { - pr_err("SMC address is beyond the SMC RAM area.\n"); - return -EINVAL; - } - - cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr); - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); - - for (; byte_count >= 4; byte_count -= 4) { - data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; - cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); - src += 4; - } - PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); - - if (0 != byte_count) { - pr_err("SMC size must be dividable by 4\n"); - return -EINVAL; - } - - return 0; -} - -static int ci_upload_firmware(struct pp_hwmgr *hwmgr) -{ - if (ci_is_smc_ram_running(hwmgr)) { - pr_info("smc is running, no need to load smc firmware\n"); - return 0; - } - PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, - boot_seq_done, 1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_MISC_CNTL, - pre_fetcher_en, 1); - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); - return ci_load_smc_ucode(hwmgr); -} - -int ci_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); - - uint32_t tmp = 0; - int result; - bool error = false; - - if (ci_upload_firmware(hwmgr)) - return -EINVAL; - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) - ci_data->dpm_table_start = tmp; - - error |= (0 != result); - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (0 == result) { - data->soft_regs_start = tmp; - ci_data->soft_regs_start = tmp; - } - - error |= (0 != result); - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (0 == result) - ci_data->mc_reg_table_start = tmp; - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (0 == result) - ci_data->fan_table_start = tmp; - - error |= (0 != result); - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (0 == result) - ci_data->arb_table_start = tmp; - - error |= (0 != result); - - result = ci_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU7_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (0 == result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (0 != result); - - return error ? 1 : 0; -} - -static uint8_t ci_get_memory_modile_index(struct pp_hwmgr *hwmgr) -{ - return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); -} - -static bool ci_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) -{ - bool result = true; - - switch (in_reg) { - case mmMC_SEQ_RAS_TIMING: - *out_reg = mmMC_SEQ_RAS_TIMING_LP; - break; - - case mmMC_SEQ_DLL_STBY: - *out_reg = mmMC_SEQ_DLL_STBY_LP; - break; - - case mmMC_SEQ_G5PDX_CMD0: - *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; - break; - - case mmMC_SEQ_G5PDX_CMD1: - *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; - break; - - case mmMC_SEQ_G5PDX_CTRL: - *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; - break; - - case mmMC_SEQ_CAS_TIMING: - *out_reg = mmMC_SEQ_CAS_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING: - *out_reg = mmMC_SEQ_MISC_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING2: - *out_reg = mmMC_SEQ_MISC_TIMING2_LP; - break; - - case mmMC_SEQ_PMG_DVS_CMD: - *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; - break; - - case mmMC_SEQ_PMG_DVS_CTL: - *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; - break; - - case mmMC_SEQ_RD_CTL_D0: - *out_reg = mmMC_SEQ_RD_CTL_D0_LP; - break; - - case mmMC_SEQ_RD_CTL_D1: - *out_reg = mmMC_SEQ_RD_CTL_D1_LP; - break; - - case mmMC_SEQ_WR_CTL_D0: - *out_reg = mmMC_SEQ_WR_CTL_D0_LP; - break; - - case mmMC_SEQ_WR_CTL_D1: - *out_reg = mmMC_SEQ_WR_CTL_D1_LP; - break; - - case mmMC_PMG_CMD_EMRS: - *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; - break; - - case mmMC_PMG_CMD_MRS: - *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; - break; - - case mmMC_PMG_CMD_MRS1: - *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; - break; - - case mmMC_SEQ_PMG_TIMING: - *out_reg = mmMC_SEQ_PMG_TIMING_LP; - break; - - case mmMC_PMG_CMD_MRS2: - *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; - break; - - case mmMC_SEQ_WR_CTL_2: - *out_reg = mmMC_SEQ_WR_CTL_2_LP; - break; - - default: - result = false; - break; - } - - return result; -} - -static int ci_set_s0_mc_reg_index(struct ci_mc_reg_table *table) -{ - uint32_t i; - uint16_t address; - - for (i = 0; i < table->last; i++) { - table->mc_reg_address[i].s0 = - ci_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) - ? address : table->mc_reg_address[i].s1; - } - return 0; -} - -static int ci_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, - struct ci_mc_reg_table *ni_table) -{ - uint8_t i, j; - - PP_ASSERT_WITH_CODE((table->last <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), - "Invalid VramInfo table.", return -EINVAL); - - for (i = 0; i < table->last; i++) - ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; - - ni_table->last = table->last; - - for (i = 0; i < table->num_entries; i++) { - ni_table->mc_reg_table_entry[i].mclk_max = - table->mc_reg_table_entry[i].mclk_max; - for (j = 0; j < table->last; j++) { - ni_table->mc_reg_table_entry[i].mc_data[j] = - table->mc_reg_table_entry[i].mc_data[j]; - } - } - - ni_table->num_entries = table->num_entries; - - return 0; -} - -static int ci_set_mc_special_registers(struct pp_hwmgr *hwmgr, - struct ci_mc_reg_table *table) -{ - uint8_t i, j, k; - uint32_t temp_reg; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - for (i = 0, j = table->last; i < table->last; i++) { - PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - switch (table->mc_reg_address[i].s1) { - - case mmMC_SEQ_MISC1: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - ((temp_reg & 0xffff0000)) | - ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); - } - j++; - PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - - if (!data->is_memory_gddr5) - table->mc_reg_table_entry[k].mc_data[j] |= 0x100; - } - j++; - PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - if (!data->is_memory_gddr5 && j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE) { - table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; - table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; - } - j++; - PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - } - - break; - - case mmMC_SEQ_RESERVE_M: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - } - j++; - PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - break; - - default: - break; - } - - } - - table->last = j; - - return 0; -} - -static int ci_set_valid_flag(struct ci_mc_reg_table *table) -{ - uint8_t i, j; - - for (i = 0; i < table->last; i++) { - for (j = 1; j < table->num_entries; j++) { - if (table->mc_reg_table_entry[j-1].mc_data[i] != - table->mc_reg_table_entry[j].mc_data[i]) { - table->validflag |= (1 << i); - break; - } - } - } - - return 0; -} - -int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); - pp_atomctrl_mc_reg_table *table; - struct ci_mc_reg_table *ni_table = &smu_data->mc_reg_table; - uint8_t module_index = ci_get_memory_modile_index(hwmgr); - - table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); - - if (NULL == table) - return -ENOMEM; - - /* Program additional LP registers that are no longer programmed by VBIOS */ - cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); - - memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table)); - - result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); - - if (0 == result) - result = ci_copy_vbios_smc_reg_table(table, ni_table); - - if (0 == result) { - ci_set_s0_mc_reg_index(ni_table); - result = ci_set_mc_special_registers(hwmgr, ni_table); - } - - if (0 == result) - ci_set_valid_flag(ni_table); - - kfree(table); - - return result; -} - -bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return ci_is_smc_ram_running(hwmgr); -} - -int ci_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request) -{ - struct ci_smumgr *smu_data = (struct ci_smumgr *) - (hwmgr->smu_backend); - struct SMU7_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t array = smu_data->dpm_table_start + - offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) * - SMU7_MAX_LEVELS_GRAPHICS; - uint32_t i; - - for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { - levels[i].ActivityLevel = - cpu_to_be16(request->activity_threshold); - levels[i].EnabledForActivity = 1; - levels[i].UpH = request->up_hyst; - levels[i].DownH = request->down_hyst; - } - - return ci_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - array_size, SMC_RAM_END); -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c index f265f42a7ed3..4d672cd15785 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/ci_smumgr.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2017 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -24,11 +24,2743 @@ #include <linux/slab.h> #include <linux/fb.h> #include "linux/delay.h" +#include <linux/types.h> #include "smumgr.h" +#include "pp_debug.h" #include "ci_smumgr.h" +#include "ppsmc.h" +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" #include "cgs_common.h" -#include "ci_smc.h" +#include "atombios.h" +#include "pppcielanes.h" + +#include "smu/smu_7_0_1_d.h" +#include "smu/smu_7_0_1_sh_mask.h" + +#include "dce/dce_8_0_d.h" +#include "dce/dce_8_0_sh_mask.h" + +#include "bif/bif_4_1_d.h" +#include "bif/bif_4_1_sh_mask.h" + +#include "gca/gfx_7_2_d.h" +#include "gca/gfx_7_2_sh_mask.h" + +#include "gmc/gmc_7_1_d.h" +#include "gmc/gmc_7_1_sh_mask.h" + +#include "processpptables.h" + +#define MC_CG_ARB_FREQ_F0 0x0a +#define MC_CG_ARB_FREQ_F1 0x0b +#define MC_CG_ARB_FREQ_F2 0x0c +#define MC_CG_ARB_FREQ_F3 0x0d + +#define SMC_RAM_END 0x40000 + +#define VOLTAGE_SCALE 4 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 +#define CISLAND_MINIMUM_ENGINE_CLOCK 800 +#define CISLAND_MAX_DEEPSLEEP_DIVIDER_ID 5 + +static const struct ci_pt_defaults defaults_hawaii_xt = { + 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0xB0000, + { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, + { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } +}; + +static const struct ci_pt_defaults defaults_hawaii_pro = { + 1, 0xF, 0xFD, 0x19, 5, 0x14, 0, 0x65062, + { 0x2E, 0x00, 0x00, 0x88, 0x00, 0x00, 0x72, 0x60, 0x51, 0xA7, 0x79, 0x6B, 0x90, 0xBD, 0x79 }, + { 0x217, 0x217, 0x217, 0x242, 0x242, 0x242, 0x269, 0x269, 0x269, 0x2A1, 0x2A1, 0x2A1, 0x2C9, 0x2C9, 0x2C9 } +}; + +static const struct ci_pt_defaults defaults_bonaire_xt = { + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, + { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, + { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } +}; + + +static const struct ci_pt_defaults defaults_saturn_xt = { + 1, 0xF, 0xFD, 0x19, 5, 55, 0, 0x70000, + { 0x8C, 0x247, 0x249, 0xA6, 0x80, 0x81, 0x8B, 0x89, 0x86, 0xC9, 0xCA, 0xC9, 0x4D, 0x4D, 0x4D }, + { 0x187, 0x187, 0x187, 0x1C7, 0x1C7, 0x1C7, 0x210, 0x210, 0x210, 0x266, 0x266, 0x266, 0x2C9, 0x2C9, 0x2C9 } +}; + + +static int ci_set_smc_sram_address(struct pp_hwmgr *hwmgr, + uint32_t smc_addr, uint32_t limit) +{ + if ((0 != (3 & smc_addr)) + || ((smc_addr + 3) >= limit)) { + pr_err("smc_addr invalid \n"); + return -EINVAL; + } + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, smc_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + return 0; +} + +static int ci_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, + const uint8_t *src, uint32_t byte_count, uint32_t limit) +{ + int result; + uint32_t data = 0; + uint32_t original_data; + uint32_t addr = 0; + uint32_t extra_shift; + + if ((3 & smc_start_address) + || ((smc_start_address + byte_count) >= limit)) { + pr_err("smc_start_address invalid \n"); + return -EINVAL; + } + + addr = smc_start_address; + + while (byte_count >= 4) { + /* Bytes are written into the SMC address space with the MSB first. */ + data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + + src += 4; + byte_count -= 4; + addr += 4; + } + + if (0 != byte_count) { + + data = 0; + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + + original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); + + extra_shift = 8 * (4 - byte_count); + + while (byte_count > 0) { + /* Bytes are written into the SMC addres space with the MSB first. */ + data = (0x100 * data) + *src++; + byte_count--; + } + + data <<= extra_shift; + + data |= (original_data & ~((~0UL) << extra_shift)); + + result = ci_set_smc_sram_address(hwmgr, addr, limit); + + if (0 != result) + return result; + + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + } + + return 0; +} + + +static int ci_program_jump_on_start(struct pp_hwmgr *hwmgr) +{ + static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 }; + + ci_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1); + + return 0; +} + +bool ci_is_smc_ram_running(struct pp_hwmgr *hwmgr) +{ + return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) + && (0x20100 <= cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixSMC_PC_C))); +} + +static int ci_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, + uint32_t *value, uint32_t limit) +{ + int result; + + result = ci_set_smc_sram_address(hwmgr, smc_addr, limit); + + if (result) + return result; + + *value = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_0); + return 0; +} + +static int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) +{ + int ret; + + if (!ci_is_smc_ram_running(hwmgr)) + return -EINVAL; + + cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg); + + PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0); + + ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP); + + if (ret != 1) + pr_info("\n failed to send message %x ret is %d\n", msg, ret); + + return 0; +} + +static int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, + uint16_t msg, uint32_t parameter) +{ + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter); + return ci_send_msg_to_smc(hwmgr, msg); +} + +static void ci_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct cgs_system_info sys_info = {0}; + uint32_t dev_id; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; + cgs_query_system_info(hwmgr->device, &sys_info); + dev_id = (uint32_t)sys_info.value; + + switch (dev_id) { + case 0x67BA: + case 0x66B1: + smu_data->power_tune_defaults = &defaults_hawaii_pro; + break; + case 0x67B8: + case 0x66B0: + smu_data->power_tune_defaults = &defaults_hawaii_xt; + break; + case 0x6640: + case 0x6641: + case 0x6646: + case 0x6647: + smu_data->power_tune_defaults = &defaults_saturn_xt; + break; + case 0x6649: + case 0x6650: + case 0x6651: + case 0x6658: + case 0x665C: + case 0x665D: + case 0x67A0: + case 0x67A1: + case 0x67A2: + case 0x67A8: + case 0x67A9: + case 0x67AA: + case 0x67B9: + case 0x67BE: + default: + smu_data->power_tune_defaults = &defaults_bonaire_xt; + break; + } +} + +static int ci_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, + uint32_t clock, uint32_t *vol) +{ + uint32_t i = 0; + + if (allowed_clock_voltage_table->count == 0) + return -EINVAL; + + for (i = 0; i < allowed_clock_voltage_table->count; i++) { + if (allowed_clock_voltage_table->entries[i].clk >= clock) { + *vol = allowed_clock_voltage_table->entries[i].v; + return 0; + } + } + + *vol = allowed_clock_voltage_table->entries[i - 1].v; + return 0; +} + +static int ci_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU7_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t ref_clock; + uint32_t ref_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ + ref_clock = atomctrl_get_reference_clock(hwmgr); + ref_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider */ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup */ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + struct pp_atomctrl_internal_ss_info ss_info; + uint32_t vco_freq = clock * dividers.uc_pll_post_div; + + if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, + vco_freq, &ss_info)) { + uint32_t clk_s = ref_clock * 5 / + (ref_divider * ss_info.speed_spectrum_rate); + uint32_t clk_v = 4 * ss_info.speed_spectrum_percentage * + fbdiv / (clk_s * 10000); + + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, + CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); + } + } + + sclk->SclkFrequency = clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static void ci_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, + const struct phm_phase_shedding_limits_table *pl, + uint32_t sclk, uint32_t *p_shed) +{ + unsigned int i; + + /* use the minimum phase shedding */ + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (sclk < pl->entries[i].Sclk) { + *p_shed = i; + break; + } + } +} + +static uint8_t ci_get_sleep_divider_id_from_clock(uint32_t clock, + uint32_t clock_insr) +{ + uint8_t i; + uint32_t temp; + uint32_t min = min_t(uint32_t, clock_insr, CISLAND_MINIMUM_ENGINE_CLOCK); + + if (clock < min) { + pr_info("Engine clock can't satisfy stutter requirement!\n"); + return 0; + } + for (i = CISLAND_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { + temp = clock >> i; + + if (temp >= min || i == 0) + break; + } + return i; +} + +static int ci_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint16_t sclk_al_threshold, + struct SMU7_Discrete_GraphicsLevel *level) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + + result = ci_calculate_sclk_params(hwmgr, clock, level); + + /* populate graphics levels */ + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_sclk, clock, + (uint32_t *)(&level->MinVddc)); + if (result) { + pr_err("vdd_dep_on_sclk table is NULL\n"); + return result; + } + + level->SclkFrequency = clock; + level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) + ci_populate_phase_value_based_on_sclk(hwmgr, + hwmgr->dyn_state.vddc_phase_shed_limits_table, + clock, + &level->MinVddcPhases); + + level->ActivityLevel = sclk_al_threshold; + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + /* this level can be used for throttling.*/ + level->EnabledForThrottle = 1; + level->UpH = 0; + level->DownH = 0; + level->VoltageDownH = 0; + level->PowerThrottle = 0; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) + level->DeepSleepDivId = + ci_get_sleep_divider_id_from_clock(clock, + CISLAND_MINIMUM_ENGINE_CLOCK); + + /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ + level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + if (0 == result) { + level->MinVddc = PP_HOST_TO_SMC_UL(level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVddcPhases); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + } + + return result; +} + +static int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result = 0; + uint32_t array = smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) * + SMU7_MAX_LEVELS_GRAPHICS; + struct SMU7_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t i; + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = ci_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + (uint16_t)smu_data->activity_target[i], + &levels[i]); + if (result) + return result; + if (i > 1) + smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; + if (i == (dpm_table->sclk_table.count - 1)) + smu_data->smc_state_table.GraphicsLevel[i].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + } + + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + + smu_data->smc_state_table.GraphicsDpmLevelCount = (u8)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + result = ci_copy_bytes_to_smc(hwmgr, array, + (u8 *)levels, array_size, + SMC_RAM_END); + + return result; + +} + +static int ci_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; + smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int ci_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + + tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->tdc_vddc_throttle_release_limit_perc; + smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; + + return 0; +} + +static int ci_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (ci_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU7_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else + smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; + + return 0; +} + +static int ci_populate_fuzzy_fan(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + uint16_t tmp; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) + || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) + tmp = hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity; + else + tmp = hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = CONVERT_FROM_HOST_TO_SMC_US(tmp); + + return 0; +} + +static int ci_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) +{ + int i; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; + uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; + uint8_t *hi2_vid = smu_data->power_tune_table.BapmVddCVidHiSidd2; + + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, + "The CAC Leakage table does not exist!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, + "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, + "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); + + for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { + lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); + hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); + hi2_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc3); + } else { + lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc); + hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Leakage); + } + } + + return 0; +} + +static int ci_populate_vddc_vid(struct pp_hwmgr *hwmgr) +{ + int i; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t *vid = smu_data->power_tune_table.VddCVid; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, + "There should never be more than 8 entries for VddcVid!!!", + return -EINVAL); + + for (i = 0; i < (int)data->vddc_voltage_table.count; i++) + vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); + + return 0; +} + +static int ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + u8 *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; + u8 *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; + int i, min, max; + + min = max = hi_vid[0]; + for (i = 0; i < 8; i++) { + if (0 != hi_vid[i]) { + if (min > hi_vid[i]) + min = hi_vid[i]; + if (max < hi_vid[i]) + max = hi_vid[i]; + } + + if (0 != lo_vid[i]) { + if (min > lo_vid[i]) + min = lo_vid[i]; + if (max < lo_vid[i]) + max = lo_vid[i]; + } + } + + if ((min == 0) || (max == 0)) + return -EINVAL; + smu_data->power_tune_table.GnbLPMLMaxVid = (u8)max; + smu_data->power_tune_table.GnbLPMLMinVid = (u8)min; + + return 0; +} + +static int ci_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; + + HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(HiSidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(LoSidd); + + return 0; +} + +static int ci_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + int ret = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) { + pr_err("Attempt to get pm_fuse_table_offset Failed!\n"); + return -EINVAL; + } + + /* DW0 - DW3 */ + ret = ci_populate_bapm_vddc_vid_sidd(hwmgr); + /* DW4 - DW5 */ + ret |= ci_populate_vddc_vid(hwmgr); + /* DW6 */ + ret |= ci_populate_svi_load_line(hwmgr); + /* DW7 */ + ret |= ci_populate_tdc_limit(hwmgr); + /* DW8 */ + ret |= ci_populate_dw8(hwmgr, pm_fuse_table_offset); + + ret |= ci_populate_fuzzy_fan(hwmgr, pm_fuse_table_offset); + + ret |= ci_min_max_v_gnbl_pm_lid_from_bapm_vddc(hwmgr); + + ret |= ci_populate_bapm_vddc_base_leakage_sidd(hwmgr); + if (ret) + return ret; + + ret = ci_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU7_Discrete_PmFuses), SMC_RAM_END); + } + return ret; +} + +static int ci_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + const struct ci_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU7_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; + struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; + const uint16_t *def1, *def2; + int i, j, k; + + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); + + dpm_table->DTETjOffset = 0; + dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; + + if (ppm) { + dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; + dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; + } else { + dpm_table->PPM_PkgPwrLimit = 0; + dpm_table->PPM_TemperatureLimit = 0; + } + + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); + + dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); + def1 = defaults->bapmti_r; + def2 = defaults->bapmti_rc; + + for (i = 0; i < SMU7_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU7_DTE_SOURCES; j++) { + for (k = 0; k < SMU7_DTE_SINKS; k++) { + dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); + dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); + def1++; + def2++; + } + } + } + + return 0; +} + +static int ci_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, + uint16_t *lo) +{ + uint16_t v_index; + bool vol_found = false; + *hi = tab->value * VOLTAGE_SCALE; + *lo = tab->value * VOLTAGE_SCALE; + + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, + "The SCLK/VDDC Dependency Table does not exist.\n", + return -EINVAL); + + if (NULL == hwmgr->dyn_state.cac_leakage_table) { + pr_warn("CAC Leakage Table does not exist, using vddc.\n"); + return 0; + } + + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + if (!vol_found) { + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + if (!vol_found) + pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); + } + + return 0; +} + +static int ci_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, + SMU7_Discrete_VoltageLevel *smc_voltage_tab) +{ + int result; + + result = ci_get_std_voltage_value_sidd(hwmgr, tab, + &smc_voltage_tab->StdVoltageHiSidd, + &smc_voltage_tab->StdVoltageLoSidd); + if (result) { + smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; + smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; + } + + smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageLoSidd); + + return 0; +} + +static int ci_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + unsigned int count; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->VddcLevelCount = data->vddc_voltage_table.count; + for (count = 0; count < table->VddcLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->vddc_voltage_table.entries[count]), + &(table->VddcLevel[count])); + PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); + + /* GPIO voltage control */ + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) + table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low; + else + table->VddcLevel[count].Smio = 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); + + return 0; +} + +static int ci_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->VddciLevelCount = data->vddci_voltage_table.count; + + for (count = 0; count < table->VddciLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->vddci_voltage_table.entries[count]), + &(table->VddciLevel[count])); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low; + else + table->VddciLevel[count].Smio |= 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); + + return 0; +} + +static int ci_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->MvddLevelCount = data->mvdd_voltage_table.count; + + for (count = 0; count < table->MvddLevelCount; count++) { + result = ci_populate_smc_voltage_table(hwmgr, + &(data->mvdd_voltage_table.entries[count]), + &table->MvddLevel[count]); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) + table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low; + else + table->MvddLevel[count].Smio |= 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); + + return 0; +} + + +static int ci_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result; + + result = ci_populate_smc_vddc_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDC voltage table to SMC", return -EINVAL); + + result = ci_populate_smc_vdd_ci_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDCI voltage table to SMC", return -EINVAL); + + result = ci_populate_smc_mvdd_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate MVDD voltage table to SMC", return -EINVAL); + + return 0; +} + +static int ci_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU7_Discrete_Ulv *state) +{ + uint32_t voltage_response_time, ulv_voltage; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); + PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); + + if (ulv_voltage == 0) { + data->ulv_supported = false; + return 0; + } + + if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffset = 0; + else + /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ + state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); + } else { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffsetVid = 0; + else /* used in SVI2 Mode */ + state->VddcOffsetVid = (uint8_t)( + (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) + * VOLTAGE_VID_OFFSET_SCALE2 + / VOLTAGE_VID_OFFSET_SCALE1); + } + state->VddcPhase = 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int ci_populate_ulv_state(struct pp_hwmgr *hwmgr, + SMU7_Discrete_Ulv *ulv_level) +{ + return ci_populate_ulv_level(hwmgr, ulv_level); +} + +static int ci_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t i; + +/* Index dpm_table->pcie_speed_table.count is reserved for PCIE boot level.*/ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = + (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].DownT = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpT = PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int ci_calculate_mclk_params( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU7_Discrete_MemoryLevel *mclk, + bool strobe_mode, + bool dllStateOn + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; + uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; + uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; + uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; + uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; + uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; + uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; + + pp_atomctrl_memory_clock_param mpll_param; + int result; + + result = atomctrl_get_memory_pll_dividers_si(hwmgr, + memory_clock, &mpll_param, strobe_mode); + PP_ASSERT_WITH_CODE(0 == result, + "Error retrieving Memory Clock Parameters from VBIOS.", return result); + + mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); + + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); + + mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, + MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + + if (data->is_memory_gddr5) { + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { + pp_atomctrl_internal_ss_info ss_info; + uint32_t freq_nom; + uint32_t tmp; + uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); + + /* for GDDR5 for all modes and DDR3 */ + if (1 == mpll_param.qdr) + freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); + else + freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); + + /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ + tmp = (freq_nom / reference_clock); + tmp = tmp * tmp; + + if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { + uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; + uint32_t clkv = + (uint32_t)((((131 * ss_info.speed_spectrum_percentage * + ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); + + mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); + mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); + } + } + + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); + + + mclk->MclkFrequency = memory_clock; + mclk->MpllFuncCntl = mpll_func_cntl; + mclk->MpllFuncCntl_1 = mpll_func_cntl_1; + mclk->MpllFuncCntl_2 = mpll_func_cntl_2; + mclk->MpllAdFuncCntl = mpll_ad_func_cntl; + mclk->MpllDqFuncCntl = mpll_dq_func_cntl; + mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; + mclk->DllCntl = dll_cntl; + mclk->MpllSs1 = mpll_ss1; + mclk->MpllSs2 = mpll_ss2; + + return 0; +} + +static uint8_t ci_get_mclk_frequency_ratio(uint32_t memory_clock, + bool strobe_mode) +{ + uint8_t mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) + mc_para_index = 0x00; + else if (memory_clock > 47500) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); + } else { + if (memory_clock < 65000) + mc_para_index = 0x00; + else if (memory_clock > 135000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); + } + + return mc_para_index; +} + +static uint8_t ci_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) +{ + uint8_t mc_para_index; + + if (memory_clock < 10000) + mc_para_index = 0; + else if (memory_clock >= 80000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); + + return mc_para_index; +} + +static int ci_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, + uint32_t memory_clock, uint32_t *p_shed) +{ + unsigned int i; + + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (memory_clock < pl->entries[i].Mclk) { + *p_shed = i; + break; + } + } + + return 0; +} + +static int ci_populate_single_memory_level( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU7_Discrete_MemoryLevel *memory_level + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + bool dll_state_on; + struct cgs_display_info info = {0}; + uint32_t mclk_edc_wr_enable_threshold = 40000; + uint32_t mclk_edc_enable_threshold = 40000; + uint32_t mclk_strobe_mode_threshold = 40000; + + if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); + } + + if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddci_dependency_on_mclk, + memory_clock, + &memory_level->MinVddci); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); + } + + if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) { + result = ci_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.mvdd_dependency_on_mclk, + memory_clock, + &memory_level->MinMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddci voltage value from memory MVDD voltage dependency table", return result); + } + + memory_level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) { + ci_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, + memory_clock, &memory_level->MinVddcPhases); + } + + memory_level->EnabledForThrottle = 1; + memory_level->EnabledForActivity = 1; + memory_level->UpH = 0; + memory_level->DownH = 100; + memory_level->VoltageDownH = 0; + + /* Indicates maximum activity level for this performance level.*/ + memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target; + memory_level->StutterEnable = 0; + memory_level->StrobeEnable = 0; + memory_level->EdcReadEnable = 0; + memory_level->EdcWriteEnable = 0; + memory_level->RttEnable = 0; + + /* default set to low watermark. Highest level will be set to high later.*/ + memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + cgs_get_active_displays_info(hwmgr->device, &info); + data->display_timing.num_existing_displays = info.display_count; + + /* stutter mode not support on ci */ + + /* decide strobe mode*/ + memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && + (memory_clock <= mclk_strobe_mode_threshold); + + /* decide EDC mode and memory clock ratio*/ + if (data->is_memory_gddr5) { + memory_level->StrobeRatio = ci_get_mclk_frequency_ratio(memory_clock, + memory_level->StrobeEnable); + + if ((mclk_edc_enable_threshold != 0) && + (memory_clock > mclk_edc_enable_threshold)) { + memory_level->EdcReadEnable = 1; + } + + if ((mclk_edc_wr_enable_threshold != 0) && + (memory_clock > mclk_edc_wr_enable_threshold)) { + memory_level->EdcWriteEnable = 1; + } + + if (memory_level->StrobeEnable) { + if (ci_get_mclk_frequency_ratio(memory_clock, 1) >= + ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + else + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; + } else + dll_state_on = data->dll_default_on; + } else { + memory_level->StrobeRatio = + ci_get_ddr3_mclk_frequency_ratio(memory_clock); + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } + + result = ci_calculate_mclk_params(hwmgr, + memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); + + if (0 == result) { + memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); + memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); + memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); + /* MCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); + /* Indicates maximum activity level for this performance level.*/ + CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); + } + + return result; +} + +static int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + struct cgs_system_info sys_info = {0}; + uint32_t dev_id; + + uint32_t level_array_address = smu_data->dpm_table_start + offsetof(SMU7_Discrete_DpmTable, MemoryLevel); + uint32_t level_array_size = sizeof(SMU7_Discrete_MemoryLevel) * SMU7_MAX_LEVELS_MEMORY; + SMU7_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", return -EINVAL); + result = ci_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.MemoryLevel[i])); + if (0 != result) + return result; + } + + smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; + cgs_query_system_info(hwmgr->device, &sys_info); + dev_id = (uint32_t)sys_info.value; + + if ((dpm_table->mclk_table.count >= 2) + && ((dev_id == 0x67B0) || (dev_id == 0x67B1))) { + smu_data->smc_state_table.MemoryLevel[1].MinVddci = + smu_data->smc_state_table.MemoryLevel[0].MinVddci; + smu_data->smc_state_table.MemoryLevel[1].MinMvdd = + smu_data->smc_state_table.MemoryLevel[0].MinMvdd; + } + smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + + result = ci_copy_bytes_to_smc(hwmgr, + level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int ci_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, + SMU7_Discrete_VoltageLevel *voltage) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { + if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { + /* Always round to higher voltage. */ + voltage->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + + PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, + "MVDD Voltage is outside the supported range.", return -EINVAL); + + } else { + return -EINVAL; + } + + return 0; +} + +static int ci_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + + SMU7_Discrete_VoltageLevel voltage_level; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + + + /* The ACPI state should not do DPM on DC (or ever).*/ + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (data->acpi_vddc) + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); + else + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); + + table->ACPILevel.MinVddcPhases = data->vddc_phase_shed_control ? 0 : 1; + /* assign zero for now*/ + table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* divider ID for required SCLK*/ + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, + CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + /* For various features to be enabled/disabled while this level is active.*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + /* SCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + + /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ + table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; + table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; + else { + if (data->acpi_vddci != 0) + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); + } + + if (0 == ci_populate_mvdd_value(hwmgr, 0, &voltage_level)) + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinMvdd = 0; + + /* Force reset on DLL*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); + + /* Disable DLL in ACPIState*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); + + /* Enable DLL bypass signal*/ + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK0_BYPASS, 0); + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK1_BYPASS, 0); + + table->MemoryACPILevel.DllCntl = + PP_HOST_TO_SMC_UL(dll_cntl); + table->MemoryACPILevel.MclkPwrmgtCntl = + PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); + table->MemoryACPILevel.MpllAdFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); + table->MemoryACPILevel.MpllDqFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl_1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); + table->MemoryACPILevel.MpllFuncCntl_2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); + table->MemoryACPILevel.MpllSs1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); + table->MemoryACPILevel.MpllSs2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpH = 0; + table->MemoryACPILevel.DownH = 100; + table->MemoryACPILevel.VoltageDownH = 0; + /* Indicates maximum activity level for this performance level.*/ + table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); + + table->MemoryACPILevel.StutterEnable = 0; + table->MemoryACPILevel.StrobeEnable = 0; + table->MemoryACPILevel.EdcReadEnable = 0; + table->MemoryACPILevel.EdcWriteEnable = 0; + table->MemoryACPILevel.RttEnable = 0; + + return result; +} + +static int ci_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + table->UvdLevelCount = (uint8_t)(uvd_table->count); + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].VclkFrequency = + uvd_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = + uvd_table->entries[count].dclk; + table->UvdLevel[count].MinVddc = + uvd_table->entries[count].v * VOLTAGE_SCALE; + table->UvdLevel[count].MinVddcPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(table->UvdLevel[count].MinVddc); + } + + return result; +} + +static int ci_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + table->VceLevelCount = (uint8_t)(vce_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = vce_table->entries[count].evclk; + table->VceLevel[count].MinVoltage = + vce_table->entries[count].v * VOLTAGE_SCALE; + table->VceLevel[count].MinPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_US(table->VceLevel[count].MinVoltage); + } + return result; +} + +static int ci_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_acp_clock_voltage_dependency_table *acp_table = + hwmgr->dyn_state.acp_clock_voltage_dependency_table; + + table->AcpLevelCount = (uint8_t)(acp_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = acp_table->entries[count].acpclk; + table->AcpLevel[count].MinVoltage = acp_table->entries[count].v; + table->AcpLevel[count].MinPhases = 1; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_US(table->AcpLevel[count].MinVoltage); + } + return result; +} + +static int ci_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_samu_clock_voltage_dependency_table *samu_table = + hwmgr->dyn_state.samu_clock_voltage_dependency_table; + + table->SamuBootLevel = 0; + table->SamuLevelCount = (uint8_t)(samu_table->count); + + for (count = 0; count < table->SamuLevelCount; count++) { + table->SamuLevel[count].Frequency = samu_table->entries[count].samclk; + table->SamuLevel[count].MinVoltage = samu_table->entries[count].v * VOLTAGE_SCALE; + table->SamuLevel[count].MinPhases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->SamuLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for samu clock", return result); + + table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_US(table->SamuLevel[count].MinVoltage); + } + return result; +} + +static int ci_populate_memory_timing_parameters( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock, + struct SMU7_Discrete_MCArbDramTimingTableEntry *arb_regs + ) +{ + uint32_t dramTiming; + uint32_t dramTiming2; + uint32_t burstTime; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + engine_clock, memory_clock); + + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + + return 0; +} + +static int ci_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + int result = 0; + SMU7_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + + memset(&arb_regs, 0x00, sizeof(SMU7_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = ci_populate_memory_timing_parameters + (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + + if (0 != result) + break; + } + } + + if (0 == result) { + result = ci_copy_bytes_to_smc( + hwmgr, + smu_data->arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU7_Discrete_MCArbDramTimingTable), + SMC_RAM_END + ); + } + + return result; +} + +static int ci_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table*/ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.GraphicsBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value \ + in dependency table. Using Graphics DPM level 0!"); + result = 0; + } + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.MemoryBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value \ + in dependency table. Using Memory DPM level 0!"); + result = 0; + } + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; + + return result; +} + +static int ci_populate_mc_reg_address(struct pp_hwmgr *hwmgr, + SMU7_Discrete_MCRegisters *mc_reg_table) +{ + const struct ci_smumgr *smu_data = (struct ci_smumgr *)hwmgr->smu_backend; + + uint32_t i, j; + + for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { + if (smu_data->mc_reg_table.validflag & 1<<j) { + PP_ASSERT_WITH_CODE(i < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE, + "Index of mc_reg_table->address[] array out of boundary", return -EINVAL); + mc_reg_table->address[i].s0 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + + mc_reg_table->last = (uint8_t)i; + + return 0; +} + +static void ci_convert_mc_registers( + const struct ci_mc_reg_entry *entry, + SMU7_Discrete_MCRegisterSet *data, + uint32_t num_entries, uint32_t valid_flag) +{ + uint32_t i, j; + + for (i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & 1<<j) { + data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); + i++; + } + } +} + +static int ci_convert_mc_reg_table_entry_to_smc( + struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + SMU7_Discrete_MCRegisterSet *mc_reg_table_data + ) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint32_t i = 0; + + for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { + if (memory_clock <= + smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { + break; + } + } + + if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) + --i; + + ci_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, smu_data->mc_reg_table.last, + smu_data->mc_reg_table.validflag); + + return 0; +} + +static int ci_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, + SMU7_Discrete_MCRegisters *mc_regs) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int res; + uint32_t i; + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + res = ci_convert_mc_reg_table_entry_to_smc( + hwmgr, + data->dpm_table.mclk_table.dpm_levels[i].value, + &mc_regs->data[i] + ); + + if (0 != res) + result = res; + } + + return result; +} + +static int ci_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t address; + int32_t result; + + if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) + return 0; + + + memset(&smu_data->mc_regs, 0, sizeof(SMU7_Discrete_MCRegisters)); + + result = ci_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); + + if (result != 0) + return result; + + address = smu_data->mc_reg_table_start + (uint32_t)offsetof(SMU7_Discrete_MCRegisters, data[0]); + + return ci_copy_bytes_to_smc(hwmgr, address, + (uint8_t *)&smu_data->mc_regs.data[0], + sizeof(SMU7_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, + SMC_RAM_END); +} + +static int ci_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + memset(&smu_data->mc_regs, 0x00, sizeof(SMU7_Discrete_MCRegisters)); + result = ci_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for the MC register addresses!", return result;); + + result = ci_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for driver state!", return result;); + + return ci_copy_bytes_to_smc(hwmgr, smu_data->mc_reg_table_start, + (uint8_t *)&smu_data->mc_regs, sizeof(SMU7_Discrete_MCRegisters), SMC_RAM_END); +} + +static int ci_populate_smc_initial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + uint8_t count, level; + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk + >= data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk + >= data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int ci_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, + SMU7_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) + table->SVI2Enable = 1; + else + table->SVI2Enable = 0; + return 0; +} + +static int ci_start_smc(struct pp_hwmgr *hwmgr) +{ + /* set smc instruct start point at 0x0 */ + ci_program_jump_on_start(hwmgr); + + /* enable smc clock */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, FIRMWARE_FLAGS, + INTERRUPTS_ENABLED, 1); + + return 0; +} + +static int ci_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + SMU7_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + u32 i; + + ci_initialize_power_tune_defaults(hwmgr); + memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) + ci_populate_smc_voltage_tables(hwmgr, table); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (data->ulv_supported) { + result = ci_populate_ulv_state(hwmgr, &(table->Ulv)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = ci_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result); + + result = ci_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result); + + result = ci_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result); + + result = ci_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result); + + result = ci_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result); + + result = ci_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result); + + result = ci_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize SAMU Level!", return result); + + /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ + /* need to populate the ARB settings for the initial state. */ + result = ci_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result); + + result = ci_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result); + + table->UvdBootLevel = 0; + table->VceBootLevel = 0; + table->AcpBootLevel = 0; + table->SamuBootLevel = 0; + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + result = ci_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result); + + result = ci_populate_smc_initial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); + + result = ci_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); + + table->UVDInterval = 1; + table->VCEInterval = 1; + table->ACPInterval = 1; + table->SAMUInterval = 1; + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + + table->TemperatureLimitHigh = + (data->thermal_temp_setting.temperature_high * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + table->TemperatureLimitLow = + (data->thermal_temp_setting.temperature_low * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->VddcVddciDelta = 4000; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + + PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + + table->PCIeBootLinkLevel = (uint8_t)data->dpm_table.pcie_speed_table.count; + table->PCIeGenInterval = 1; + + ci_populate_smc_svi2_config(hwmgr, table); + + for (i = 0; i < SMU7_MAX_ENTRIES_SMIO; i++) + CONVERT_FROM_HOST_TO_SMC_UL(table->Smio[i]); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + table->VddcVddciDelta = PP_HOST_TO_SMC_US(table->VddcVddciDelta); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); + table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); + table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = ci_copy_bytes_to_smc(hwmgr, smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU7_Discrete_DpmTable)-3 * sizeof(SMU7_PIDController), + SMC_RAM_END); + + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result;); + + result = ci_populate_initial_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate initialize MC Reg table!", return result); + + result = ci_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + ci_start_smc(hwmgr); + + return 0; +} + +static int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); + SMU7_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) + return 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (0 == ci_data->fan_table_start) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = smu7_get_xclk(hwmgr); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); + + res = ci_copy_bytes_to_smc(hwmgr, ci_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); + + return 0; +} + +static int ci_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return ci_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int ci_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (hwmgr->gfx_arbiter.sclk_threshold != + data->low_sclk_interrupt_threshold)) { + data->low_sclk_interrupt_threshold = + hwmgr->gfx_arbiter.sclk_threshold; + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = ci_copy_bytes_to_smc( + hwmgr, + smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, + LowSclkInterruptT), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + + result = ci_update_and_upload_mc_reg_table(hwmgr); + + PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); + + result = ci_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + + return result; +} + +static uint32_t ci_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU7_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU7_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU7_SoftRegisters, AverageGraphicsA); + case PreVBlankGap: + return offsetof(SMU7_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU7_SoftRegisters, VBlankTimeout); + case DRAM_LOG_ADDR_H: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU7_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + case SMU_Discrete_DpmTable: + switch (member) { + case LowSclkInterruptThreshold: + return offsetof(SMU7_Discrete_DpmTable, LowSclkInterruptT); + } + } + pr_debug("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t ci_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU7_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU7_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU7_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU7_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU7_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDCI: + return SMU7_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU7_MAX_LEVELS_MVDD; + } + + pr_debug("can't get the mac of %x\n", value); + return 0; +} + +static int ci_load_smc_ucode(struct pp_hwmgr *hwmgr) +{ + uint32_t byte_count, start_addr; + uint8_t *src; + uint32_t data; + + struct cgs_firmware_info info = {0}; + + cgs_get_firmware_info(hwmgr->device, CGS_UCODE_ID_SMU, &info); + + hwmgr->is_kicker = info.is_kicker; + byte_count = info.image_size; + src = (uint8_t *)info.kptr; + start_addr = info.ucode_start_address; + + if (byte_count > SMC_RAM_END) { + pr_err("SMC address is beyond the SMC RAM area.\n"); + return -EINVAL; + } + + cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_0, start_addr); + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); + + for (; byte_count >= 4; byte_count -= 4) { + data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3]; + cgs_write_register(hwmgr->device, mmSMC_IND_DATA_0, data); + src += 4; + } + PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + + if (0 != byte_count) { + pr_err("SMC size must be divisible by 4\n"); + return -EINVAL; + } + + return 0; +} + +static int ci_upload_firmware(struct pp_hwmgr *hwmgr) +{ + if (ci_is_smc_ram_running(hwmgr)) { + pr_info("smc is running, no need to load smc firmware\n"); + return 0; + } + PHM_WAIT_INDIRECT_FIELD(hwmgr, SMC_IND, RCU_UC_EVENTS, + boot_seq_done, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_MISC_CNTL, + pre_fetcher_en, 1); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_RESET_CNTL, rst_reg, 1); + return ci_load_smc_ucode(hwmgr); +} + +static int ci_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct ci_smumgr *ci_data = (struct ci_smumgr *)(hwmgr->smu_backend); + + uint32_t tmp = 0; + int result; + bool error = false; + + if (ci_upload_firmware(hwmgr)) + return -EINVAL; + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->dpm_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (0 == result) { + data->soft_regs_start = tmp; + ci_data->soft_regs_start = tmp; + } + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->mc_reg_table_start = tmp; + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->fan_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (0 == result) + ci_data->arb_table_start = tmp; + + error |= (0 != result); + + result = ci_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU7_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (0 == result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? 1 : 0; +} + +static uint8_t ci_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +static bool ci_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) +{ + bool result = true; + + switch (in_reg) { + case mmMC_SEQ_RAS_TIMING: + *out_reg = mmMC_SEQ_RAS_TIMING_LP; + break; + + case mmMC_SEQ_DLL_STBY: + *out_reg = mmMC_SEQ_DLL_STBY_LP; + break; + + case mmMC_SEQ_G5PDX_CMD0: + *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; + break; + + case mmMC_SEQ_G5PDX_CMD1: + *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; + break; + + case mmMC_SEQ_G5PDX_CTRL: + *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; + break; + + case mmMC_SEQ_CAS_TIMING: + *out_reg = mmMC_SEQ_CAS_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING: + *out_reg = mmMC_SEQ_MISC_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING2: + *out_reg = mmMC_SEQ_MISC_TIMING2_LP; + break; + + case mmMC_SEQ_PMG_DVS_CMD: + *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; + break; + + case mmMC_SEQ_PMG_DVS_CTL: + *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; + break; + + case mmMC_SEQ_RD_CTL_D0: + *out_reg = mmMC_SEQ_RD_CTL_D0_LP; + break; + + case mmMC_SEQ_RD_CTL_D1: + *out_reg = mmMC_SEQ_RD_CTL_D1_LP; + break; + + case mmMC_SEQ_WR_CTL_D0: + *out_reg = mmMC_SEQ_WR_CTL_D0_LP; + break; + + case mmMC_SEQ_WR_CTL_D1: + *out_reg = mmMC_SEQ_WR_CTL_D1_LP; + break; + + case mmMC_PMG_CMD_EMRS: + *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; + break; + + case mmMC_PMG_CMD_MRS: + *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; + break; + + case mmMC_PMG_CMD_MRS1: + *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; + break; + + case mmMC_SEQ_PMG_TIMING: + *out_reg = mmMC_SEQ_PMG_TIMING_LP; + break; + + case mmMC_PMG_CMD_MRS2: + *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; + break; + + case mmMC_SEQ_WR_CTL_2: + *out_reg = mmMC_SEQ_WR_CTL_2_LP; + break; + + default: + result = false; + break; + } + + return result; +} + +static int ci_set_s0_mc_reg_index(struct ci_mc_reg_table *table) +{ + uint32_t i; + uint16_t address; + + for (i = 0; i < table->last; i++) { + table->mc_reg_address[i].s0 = + ci_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) + ? address : table->mc_reg_address[i].s1; + } + return 0; +} + +static int ci_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, + struct ci_mc_reg_table *ni_table) +{ + uint8_t i, j; + + PP_ASSERT_WITH_CODE((table->last <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), + "Invalid VramInfo table.", return -EINVAL); + + for (i = 0; i < table->last; i++) + ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + + ni_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + ni_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + ni_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + + ni_table->num_entries = table->num_entries; + + return 0; +} + +static int ci_set_mc_special_registers(struct pp_hwmgr *hwmgr, + struct ci_mc_reg_table *table) +{ + uint8_t i, j, k; + uint32_t temp_reg; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + for (i = 0, j = table->last; i < table->last; i++) { + PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + switch (table->mc_reg_address[i].s1) { + + case mmMC_SEQ_MISC1: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + } + j++; + PP_ASSERT_WITH_CODE((j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + + if (!data->is_memory_gddr5) + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + if (!data->is_memory_gddr5 && j < SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE) { + table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + } + + break; + + case mmMC_SEQ_RESERVE_M: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU7_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + break; + + default: + break; + } + + } + + table->last = j; + + return 0; +} + +static int ci_set_valid_flag(struct ci_mc_reg_table *table) +{ + uint8_t i, j; + + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != + table->mc_reg_table_entry[j].mc_data[i]) { + table->validflag |= (1 << i); + break; + } + } + } + + return 0; +} + +static int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct ci_smumgr *smu_data = (struct ci_smumgr *)(hwmgr->smu_backend); + pp_atomctrl_mc_reg_table *table; + struct ci_mc_reg_table *ni_table = &smu_data->mc_reg_table; + uint8_t module_index = ci_get_memory_modile_index(hwmgr); + + table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + /* Program additional LP registers that are no longer programmed by VBIOS */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); + + memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table)); + + result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); + + if (0 == result) + result = ci_copy_vbios_smc_reg_table(table, ni_table); + + if (0 == result) { + ci_set_s0_mc_reg_index(ni_table); + result = ci_set_mc_special_registers(hwmgr, ni_table); + } + + if (0 == result) + ci_set_valid_flag(ni_table); + + kfree(table); + + return result; +} + +static bool ci_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return ci_is_smc_ram_running(hwmgr); +} + +static int ci_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + struct ci_smumgr *smu_data = (struct ci_smumgr *) + (hwmgr->smu_backend); + struct SMU7_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->dpm_table_start + + offsetof(SMU7_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU7_Discrete_GraphicsLevel) * + SMU7_MAX_LEVELS_GRAPHICS; + uint32_t i; + + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + levels[i].ActivityLevel = + cpu_to_be16(request->activity_threshold); + levels[i].EnabledForActivity = 1; + levels[i].UpH = request->up_hyst; + levels[i].DownH = request->down_hyst; + } + + return ci_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + array_size, SMC_RAM_END); +} + static int ci_smu_init(struct pp_hwmgr *hwmgr) { diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c deleted file mode 100644 index b1a66b5ada4a..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.c +++ /dev/null @@ -1,2486 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "pp_debug.h" -#include "fiji_smc.h" -#include "smu7_dyn_defaults.h" - -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "atombios.h" -#include "fiji_smumgr.h" -#include "pppcielanes.h" -#include "smu7_ppsmc.h" -#include "smu73.h" -#include "smu/smu_7_1_3_d.h" -#include "smu/smu_7_1_3_sh_mask.h" -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" -#include "smu7_smumgr.h" - -#define VOLTAGE_SCALE 4 -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 -#define VDDC_VDDCI_DELTA 300 -#define MC_CG_ARB_FREQ_F1 0x0b - -/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs - * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] - */ -static const uint16_t fiji_clock_stretcher_lookup_table[2][4] = { - {600, 1050, 3, 0}, {600, 1050, 6, 1} }; - -/* [FF, SS] type, [] 4 voltage ranges, and - * [Floor Freq, Boundary Freq, VID min , VID max] - */ -static const uint32_t fiji_clock_stretcher_ddt_table[2][4][4] = { - { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, - { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } }; - -/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] - * (coming from PWR_CKS_CNTL.stretch_amount reg spec) - */ -static const uint8_t fiji_clock_stretch_amount_conversion[2][6] = { - {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} }; - -static const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { - /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */ - {1, 0xF, 0xFD, - /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */ - 0x19, 5, 45} -}; - -/* PPGen has the gain setting generated in x * 100 unit - * This function is to convert the unit to x * 4096(0x1000) unit. - * This is the unit expected by SMC firmware - */ -static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, - uint32_t clock, uint32_t *voltage, uint32_t *mvdd) -{ - uint32_t i; - uint16_t vddci; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - *voltage = *mvdd = 0; - - - /* clock - voltage dependency table is empty table */ - if (dep_table->count == 0) - return -EINVAL; - - for (i = 0; i < dep_table->count; i++) { - /* find first sclk bigger than request */ - if (dep_table->entries[i].clk >= clock) { - *voltage |= (dep_table->entries[i].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i].vddci) - *voltage |= (dep_table->entries[i].vddci * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i].mvdd * - VOLTAGE_SCALE; - - *voltage |= 1 << PHASES_SHIFT; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i-1].vddci) { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; - - return 0; -} - - -static uint16_t scale_fan_gain_settings(uint16_t raw_setting) -{ - uint32_t tmp; - tmp = raw_setting * 4096 / 100; - return (uint16_t)tmp; -} - -static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t *sda) -{ - switch (line) { - case SMU7_I2CLineID_DDC1: - *scl = SMU7_I2C_DDC1CLK; - *sda = SMU7_I2C_DDC1DATA; - break; - case SMU7_I2CLineID_DDC2: - *scl = SMU7_I2C_DDC2CLK; - *sda = SMU7_I2C_DDC2DATA; - break; - case SMU7_I2CLineID_DDC3: - *scl = SMU7_I2C_DDC3CLK; - *sda = SMU7_I2C_DDC3DATA; - break; - case SMU7_I2CLineID_DDC4: - *scl = SMU7_I2C_DDC4CLK; - *sda = SMU7_I2C_DDC4DATA; - break; - case SMU7_I2CLineID_DDC5: - *scl = SMU7_I2C_DDC5CLK; - *sda = SMU7_I2C_DDC5DATA; - break; - case SMU7_I2CLineID_DDC6: - *scl = SMU7_I2C_DDC6CLK; - *sda = SMU7_I2C_DDC6DATA; - break; - case SMU7_I2CLineID_SCLSDA: - *scl = SMU7_I2C_SCL; - *sda = SMU7_I2C_SDA; - break; - case SMU7_I2CLineID_DDCVGA: - *scl = SMU7_I2C_DDCVGACLK; - *sda = SMU7_I2C_DDCVGADATA; - break; - default: - *scl = 0; - *sda = 0; - break; - } -} - -static void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (table_info && - table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && - table_info->cac_dtp_table->usPowerTuneDataSetID) - smu_data->power_tune_defaults = - &fiji_power_tune_data_set_array - [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; - else - smu_data->power_tune_defaults = &fiji_power_tune_data_set_array[0]; - -} - -static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; - - SMU73_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; - struct pp_advance_fan_control_parameters *fan_table = - &hwmgr->thermal_controller.advanceFanControlParameters; - uint8_t uc_scl, uc_sda; - - /* TDP number of fraction bits are changed from 8 to 7 for Fiji - * as requested by SMC team - */ - dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( - (uint16_t)(cac_dtp_table->usTDP * 128)); - dpm_table->TargetTdp = PP_HOST_TO_SMC_US( - (uint16_t)(cac_dtp_table->usTDP * 128)); - - PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, - "Target Operating Temp is out of Range!", - ); - - dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase; - - /* The following are for new Fiji Multi-input fan/thermal control */ - dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( - cac_dtp_table->usTargetOperatingTemp * 256); - dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitHotspot * 256); - dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitLiquid1 * 256); - dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitLiquid2 * 256); - dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitVrVddc * 256); - dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitVrMvdd * 256); - dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitPlx * 256); - - dpm_table->FanGainEdge = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainEdge)); - dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainHotspot)); - dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainLiquid)); - dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainVrVddc)); - dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainVrMvdd)); - dpm_table->FanGainPlx = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainPlx)); - dpm_table->FanGainHbm = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainHbm)); - - dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address; - dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address; - dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address; - dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address; - - get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda); - dpm_table->Liquid_I2C_LineSCL = uc_scl; - dpm_table->Liquid_I2C_LineSDA = uc_sda; - - get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda); - dpm_table->Vr_I2C_LineSCL = uc_scl; - dpm_table->Vr_I2C_LineSDA = uc_sda; - - get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda); - dpm_table->Plx_I2C_LineSCL = uc_scl; - dpm_table->Plx_I2C_LineSDA = uc_sda; - - return 0; -} - - -static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; - smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - - -static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; - - /* TDC number of fraction bits are changed from 8 to 7 - * for Fiji as requested by SMC team - */ - tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->TDC_VDDC_ThrottleReleaseLimitPerc; - smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; - - return 0; -} - -static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else { - smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; - smu_data->power_tune_table.LPMLTemperatureMin = - (uint8_t)((temp >> 16) & 0xff); - smu_data->power_tune_table.LPMLTemperatureMax = - (uint8_t)((temp >> 8) & 0xff); - smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); - } - return 0; -} - -static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - int i; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; - - return 0; -} - -static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - if ((hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity & (1 << 15)) || - 0 == hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity) - hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity = hwmgr->thermal_controller. - advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = - PP_HOST_TO_SMC_US(hwmgr->thermal_controller. - advanceFanControlParameters.usFanOutputSensitivity); - return 0; -} - -static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; - - HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(HiSidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(LoSidd); - - return 0; -} - -static int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - uint32_t pm_fuse_table_offset; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed!", - return -EINVAL); - - /* DW6 */ - if (fiji_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed!", - return -EINVAL); - /* DW7 */ - if (fiji_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed!", return -EINVAL); - /* DW8 */ - if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl, " - "LPMLTemperature Min and Max Failed!", - return -EINVAL); - - /* DW9-DW12 */ - if (0 != fiji_populate_temperature_scaler(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed!", - return -EINVAL); - - /* DW13-DW14 */ - if (fiji_populate_fuzzy_fan(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate Fuzzy Fan Control parameters Failed!", - return -EINVAL); - - /* DW15-DW18 */ - if (fiji_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed!", - return -EINVAL); - - /* DW20 */ - if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate BapmVddCBaseLeakage Hi and Lo " - "Sidd Failed!", return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - sizeof(struct SMU73_Discrete_PmFuses), SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed!", - return -EINVAL); - } - return 0; -} - -/** -* Preparation of vddc and vddgfx CAC tables for SMC. -* -* @param hwmgr the address of the hardware manager -* @param table the SMC DPM table structure to be populated -* @return always 0 -*/ -static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - uint32_t count; - uint8_t index; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_voltage_lookup_table *lookup_table = - table_info->vddc_lookup_table; - /* tables is already swapped, so in order to use the value from it, - * we need to swap it back. - * We are populating vddc CAC data to BapmVddc table - * in split and merged mode - */ - - for (count = 0; count < lookup_table->count; count++) { - index = phm_get_voltage_index(lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddcVidLoSidd[count] = - convert_to_vid(lookup_table->entries[index].us_cac_low); - table->BapmVddcVidHiSidd[count] = - convert_to_vid(lookup_table->entries[index].us_cac_high); - } - - return 0; -} - -/** -* Preparation of voltage tables for SMC. -* -* @param hwmgr the address of the hardware manager -* @param table the SMC DPM table structure to be populated -* @return always 0 -*/ - -static int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - int result; - - result = fiji_populate_cac_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate CAC voltage tables to SMC", - return -EINVAL); - - return 0; -} - -static int fiji_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_Ulv *state) -{ - int result = 0; - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; - state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * - VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - - state->VddcPhase = 1; - - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - } - return result; -} - -static int fiji_populate_ulv_state(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - return fiji_populate_ulv_level(hwmgr, &table->Ulv); -} - -static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - int i; - - /* Index (dpm_table->pcie_speed_table.count) - * is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( - dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = 1; - table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - - -/** -* Calculates the SCLK dividers using the provided engine clock -* -* @param hwmgr the address of the hardware manager -* @param clock the engine clock to use to populate the structure -* @param sclk the SMC SCLK structure to be populated -*/ -static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU73_Discrete_GraphicsLevel *sclk) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t ref_clock; - uint32_t ref_divider; - uint32_t fbdiv; - int result; - - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ - ref_clock = atomctrl_get_reference_clock(hwmgr); - ref_divider = 1 + dividers.uc_pll_ref_div; - - /* low 14 bits is fraction and high 12 bits is divider */ - fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; - - /* SPLL_FUNC_CNTL setup */ - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_REF_DIV, dividers.uc_pll_ref_div); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_PDIV_A, dividers.uc_pll_post_div); - - /* SPLL_FUNC_CNTL_3 setup*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, - SPLL_FB_DIV, fbdiv); - - /* set to use fractional accumulation*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, - SPLL_DITHEN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { - struct pp_atomctrl_internal_ss_info ssInfo; - - uint32_t vco_freq = clock * dividers.uc_pll_post_div; - if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, - vco_freq, &ssInfo)) { - /* - * ss_info.speed_spectrum_percentage -- in unit of 0.01% - * ss_info.speed_spectrum_rate -- in unit of khz - * - * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 - */ - uint32_t clk_s = ref_clock * 5 / - (ref_divider * ssInfo.speed_spectrum_rate); - /* clkv = 2 * D * fbdiv / NS */ - uint32_t clk_v = 4 * ssInfo.speed_spectrum_percentage * - fbdiv / (clk_s * 10000); - - cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, - CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); - cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, - CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); - cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, - CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); - } - } - - sclk->SclkFrequency = clock; - sclk->CgSpllFuncCntl3 = spll_func_cntl_3; - sclk->CgSpllFuncCntl4 = spll_func_cntl_4; - sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; - sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; - sclk->SclkDid = (uint8_t)dividers.pll_post_divider; - - return 0; -} - -/** -* Populates single SMC SCLK structure using the provided engine clock -* -* @param hwmgr the address of the hardware manager -* @param clock the engine clock to use to populate the structure -* @param sclk the SMC SCLK structure to be populated -*/ - -static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t clock, uint16_t sclk_al_threshold, - struct SMU73_Discrete_GraphicsLevel *level) -{ - int result; - /* PP_Clocks minClocks; */ - uint32_t threshold, mvdd; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - result = fiji_calculate_sclk_params(hwmgr, clock, level); - - /* populate graphics levels */ - result = fiji_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_sclk, clock, - (uint32_t *)(&level->MinVoltage), &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "can not find VDDC voltage value for " - "VDDC engine clock dependency table", - return result); - - level->SclkFrequency = clock; - level->ActivityLevel = sclk_al_threshold; - level->CcPwrDynRm = 0; - level->CcPwrDynRm1 = 0; - level->EnabledForActivity = 0; - level->EnabledForThrottle = 1; - level->UpHyst = 10; - level->DownHyst = 0; - level->VoltageDownHyst = 0; - level->PowerThrottle = 0; - - threshold = clock * data->fast_watermark_threshold / 100; - - data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) - level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, - hwmgr->display_config.min_core_set_clock_in_sr); - - - /* Default to slow, highest DPM level will be - * set to PPSMC_DISPLAY_WATERMARK_LOW later. - */ - level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); - - return 0; -} -/** -* Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states -* -* @param hwmgr the address of the hardware manager -*/ -int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; - uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count; - int result = 0; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) * - SMU73_MAX_LEVELS_GRAPHICS; - struct SMU73_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t i, max_entry; - uint8_t hightest_pcie_level_enabled = 0, - lowest_pcie_level_enabled = 0, - mid_pcie_level_enabled = 0, - count = 0; - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - result = fiji_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - (uint16_t)smu_data->activity_target[i], - &levels[i]); - if (result) - return result; - - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - levels[i].DeepSleepDivId = 0; - } - - /* Only enable level 0 for now.*/ - levels[0].EnabledForActivity = 1; - - /* set highest level watermark to high */ - levels[dpm_table->sclk_table.count - 1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - if (pcie_table != NULL) { - PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - max_entry = pcie_entry_cnt - 1; - for (i = 0; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = - (uint8_t) ((i < max_entry) ? i : max_entry); - } else { - while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (hightest_pcie_level_enabled + 1))) != 0)) - hightest_pcie_level_enabled++; - - while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << lowest_pcie_level_enabled)) == 0)) - lowest_pcie_level_enabled++; - - while ((count < hightest_pcie_level_enabled) && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) - count++; - - mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < - hightest_pcie_level_enabled ? - (lowest_pcie_level_enabled + 1 + count) : - hightest_pcie_level_enabled; - - /* set pcieDpmLevel to hightest_pcie_level_enabled */ - for (i = 2; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = hightest_pcie_level_enabled; - - /* set pcieDpmLevel to lowest_pcie_level_enabled */ - levels[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled */ - levels[1].pcieDpmLevel = mid_pcie_level_enabled; - } - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - - -/** - * MCLK Frequency Ratio - * SEQ_CG_RESP Bit[31:24] - 0x0 - * Bit[27:24] \96 DDR3 Frequency ratio - * 0x0 <= 100MHz, 450 < 0x8 <= 500MHz - * 100 < 0x1 <= 150MHz, 500 < 0x9 <= 550MHz - * 150 < 0x2 <= 200MHz, 550 < 0xA <= 600MHz - * 200 < 0x3 <= 250MHz, 600 < 0xB <= 650MHz - * 250 < 0x4 <= 300MHz, 650 < 0xC <= 700MHz - * 300 < 0x5 <= 350MHz, 700 < 0xD <= 750MHz - * 350 < 0x6 <= 400MHz, 750 < 0xE <= 800MHz - * 400 < 0x7 <= 450MHz, 800 < 0xF - */ -static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock) -{ - if (mem_clock <= 10000) - return 0x0; - if (mem_clock <= 15000) - return 0x1; - if (mem_clock <= 20000) - return 0x2; - if (mem_clock <= 25000) - return 0x3; - if (mem_clock <= 30000) - return 0x4; - if (mem_clock <= 35000) - return 0x5; - if (mem_clock <= 40000) - return 0x6; - if (mem_clock <= 45000) - return 0x7; - if (mem_clock <= 50000) - return 0x8; - if (mem_clock <= 55000) - return 0x9; - if (mem_clock <= 60000) - return 0xa; - if (mem_clock <= 65000) - return 0xb; - if (mem_clock <= 70000) - return 0xc; - if (mem_clock <= 75000) - return 0xd; - if (mem_clock <= 80000) - return 0xe; - /* mem_clock > 800MHz */ - return 0xf; -} - -/** -* Populates the SMC MCLK structure using the provided memory clock -* -* @param hwmgr the address of the hardware manager -* @param clock the memory clock to use to populate the structure -* @param sclk the SMC SCLK structure to be populated -*/ -static int fiji_calculate_mclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU73_Discrete_MemoryLevel *mclk) -{ - struct pp_atomctrl_memory_clock_param mem_param; - int result; - - result = atomctrl_get_memory_pll_dividers_vi(hwmgr, clock, &mem_param); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to get Memory PLL Dividers.", - ); - - /* Save the result data to outpupt memory level structure */ - mclk->MclkFrequency = clock; - mclk->MclkDivider = (uint8_t)mem_param.mpll_post_divider; - mclk->FreqRange = fiji_get_mclk_frequency_ratio(clock); - - return result; -} - -static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU73_Discrete_MemoryLevel *mem_level) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - int result = 0; - uint32_t mclk_stutter_mode_threshold = 60000; - - if (table_info->vdd_dep_on_mclk) { - result = fiji_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_mclk, clock, - (uint32_t *)(&mem_level->MinVoltage), &mem_level->MinMvdd); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddc voltage value from memory " - "VDDC voltage dependency table", return result); - } - - mem_level->EnabledForThrottle = 1; - mem_level->EnabledForActivity = 0; - mem_level->UpHyst = 0; - mem_level->DownHyst = 100; - mem_level->VoltageDownHyst = 0; - mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target; - mem_level->StutterEnable = false; - - mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - /* enable stutter mode if all the follow condition applied - * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI, - * &(data->DisplayTiming.numExistingDisplays)); - */ - data->display_timing.num_existing_displays = 1; - - if (mclk_stutter_mode_threshold && - (clock <= mclk_stutter_mode_threshold) && - (!data->is_uvd_enabled) && - (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE) & 0x1)) - mem_level->StutterEnable = true; - - result = fiji_calculate_mclk_params(hwmgr, clock, mem_level); - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); - } - return result; -} - -/** -* Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states -* -* @param hwmgr the address of the hardware manager -*/ -int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result; - /* populate MCLK dpm table to SMU7 */ - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, MemoryLevel); - uint32_t array_size = sizeof(SMU73_Discrete_MemoryLevel) * - SMU73_MAX_LEVELS_MEMORY; - struct SMU73_Discrete_MemoryLevel *levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", - return -EINVAL); - result = fiji_populate_single_memory_level(hwmgr, - dpm_table->mclk_table.dpm_levels[i].value, - &levels[i]); - if (result) - return result; - } - - /* Only enable level 0 for now. */ - levels[0].EnabledForActivity = 1; - - /* in order to prevent MC activity from stutter mode to push DPM up. - * the UVD change complements this by putting the MCLK in - * a higher state by default such that we are not effected by - * up threshold or and MCLK DPM latency. - */ - levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target; - CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = - (uint8_t)dpm_table->mclk_table.count; - data->dpm_level_enable_mask.mclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - /* set highest level watermark to high */ - levels[dpm_table->mclk_table.count - 1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - - -/** -* Populates the SMC MVDD structure using the provided memory clock. -* -* @param hwmgr the address of the hardware manager -* @param mclk the MCLK value to be used in the decision if MVDD should be high or low. -* @param voltage the SMC VOLTAGE structure to be populated -*/ -static int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr, - uint32_t mclk, SMIO_Pattern *smio_pat) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { - if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { - smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, - "MVDD Voltage is outside the supported range.", - return -EINVAL); - } else - return -EINVAL; - - return 0; -} - -static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU73_Discrete_DpmTable *table) -{ - int result = 0; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct pp_atomctrl_clock_dividers_vi dividers; - SMIO_Pattern vol_level; - uint32_t mvdd; - uint16_t us_mvdd; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; - - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - if (!data->sclk_dpm_key_disabled) { - /* Get MinVoltage and Frequency from DPM0, - * already converted to SMC_UL */ - table->ACPILevel.SclkFrequency = - data->dpm_table.sclk_table.dpm_levels[0].value; - result = fiji_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_sclk, - table->ACPILevel.SclkFrequency, - (uint32_t *)(&table->ACPILevel.MinVoltage), &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDC voltage value " \ - "in Clock Dependency Table", - ); - } else { - table->ACPILevel.SclkFrequency = - data->vbios_boot_state.sclk_bootup_value; - table->ACPILevel.MinVoltage = - data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE; - } - - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, - table->ACPILevel.SclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; - table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - table->ACPILevel.DeepSleepDivId = 0; - - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_PWRON, 0); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_RESET, 1); - spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, - SCLK_MUX_SEL, 4); - - table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; - table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; - table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - if (!data->mclk_dpm_key_disabled) { - /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ - table->MemoryACPILevel.MclkFrequency = - data->dpm_table.mclk_table.dpm_levels[0].value; - result = fiji_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_mclk, - table->MemoryACPILevel.MclkFrequency, - (uint32_t *)(&table->MemoryACPILevel.MinVoltage), &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDCI voltage value in Clock Dependency Table", - ); - } else { - table->MemoryACPILevel.MclkFrequency = - data->vbios_boot_state.mclk_bootup_value; - table->MemoryACPILevel.MinVoltage = - data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE; - } - - us_mvdd = 0; - if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || - (data->mclk_dpm_key_disabled)) - us_mvdd = data->vbios_boot_state.mvdd_bootup_value; - else { - if (!fiji_populate_mvdd_value(hwmgr, - data->dpm_table.mclk_table.dpm_levels[0].value, - &vol_level)) - us_mvdd = vol_level.Voltage; - } - - table->MemoryACPILevel.MinMvdd = - PP_HOST_TO_SMC_UL(us_mvdd * VOLTAGE_SCALE); - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - table->MemoryACPILevel.ActivityLevel = - PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); - - table->MemoryACPILevel.StutterEnable = false; - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); - - return result; -} - -static int fiji_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU73_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - - table->VceLevelCount = (uint8_t)(mm_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = mm_table->entries[count].eclk; - table->VceLevel[count].MinVoltage = 0; - table->VceLevel[count].MinVoltage |= - (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - table->VceLevel[count].MinVoltage |= - ((mm_table->entries[count].vddc - VDDC_VDDCI_DELTA) * - VOLTAGE_SCALE) << VDDCI_SHIFT; - table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /*retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); - } - return result; -} - -static int fiji_populate_smc_acp_level(struct pp_hwmgr *hwmgr, - SMU73_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - - table->AcpLevelCount = (uint8_t)(mm_table->count); - table->AcpBootLevel = 0; - - for (count = 0; count < table->AcpLevelCount; count++) { - table->AcpLevel[count].Frequency = mm_table->entries[count].aclk; - table->AcpLevel[count].MinVoltage |= (mm_table->entries[count].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - table->AcpLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - - VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->AcpLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->AcpLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for engine clock", return result); - - table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].MinVoltage); - } - return result; -} - -static int fiji_populate_smc_samu_level(struct pp_hwmgr *hwmgr, - SMU73_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - - table->SamuBootLevel = 0; - table->SamuLevelCount = (uint8_t)(mm_table->count); - - for (count = 0; count < table->SamuLevelCount; count++) { - /* not sure whether we need evclk or not */ - table->SamuLevel[count].MinVoltage = 0; - table->SamuLevel[count].Frequency = mm_table->entries[count].samclock; - table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - table->SamuLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - - VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->SamuLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for samu clock", return result); - - table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage); - } - return result; -} - -static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, - int32_t eng_clock, int32_t mem_clock, - struct SMU73_Discrete_MCArbDramTimingTableEntry *arb_regs) -{ - uint32_t dram_timing; - uint32_t dram_timing2; - uint32_t burstTime; - ULONG state, trrds, trrdl; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - eng_clock, mem_clock); - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burstTime = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME); - - state = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, STATE0); - trrds = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDS0); - trrdl = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDL0); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); - arb_regs->McArbBurstTime = (uint8_t)burstTime; - arb_regs->TRRDS = (uint8_t)trrds; - arb_regs->TRRDL = (uint8_t)trrdl; - - return 0; -} - -static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct SMU73_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - int result = 0; - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { - result = fiji_populate_memory_timing_parameters(hwmgr, - data->dpm_table.sclk_table.dpm_levels[i].value, - data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - if (result) - break; - } - } - - if (!result) - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU73_Discrete_MCArbDramTimingTable), - SMC_RAM_END); - return result; -} - -static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - - table->UvdLevelCount = (uint8_t)(mm_table->count); - table->UvdBootLevel = 0; - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].MinVoltage = 0; - table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; - table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - table->UvdLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - - VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].VclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Vclk clock", return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Dclk clock", return result); - - table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); - - } - return result; -} - -static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table */ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(table->GraphicsBootLevel)); - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(table->MemoryBootLevel)); - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value * - VOLTAGE_SCALE; - table->BootVddci = data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE; - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); - CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); - - return 0; -} - -static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint8_t count, level; - - count = (uint8_t)(table_info->vdd_dep_on_sclk->count); - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_sclk->entries[level].clk >= - data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(table_info->vdd_dep_on_mclk->count); - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_mclk->entries[level].clk >= - data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - -static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) -{ - uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, - volt_with_cks, value; - uint16_t clock_freq_u16; - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, - volt_offset = 0; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - - stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; - - /* Read SMU_Eefuse to read and calculate RO and determine - * if the part is SS or FF. if RO >= 1660MHz, part is FF. - */ - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (146 * 4)); - efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (148 * 4)); - efuse &= 0xFF000000; - efuse = efuse >> 24; - efuse2 &= 0xF; - - if (efuse2 == 1) - ro = (2300 - 1350) * efuse / 255 + 1350; - else - ro = (2500 - 1000) * efuse / 255 + 1000; - - if (ro >= 1660) - type = 0; - else - type = 1; - - /* Populate Stretch amount */ - smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; - - /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ - for (i = 0; i < sclk_table->count; i++) { - smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= - sclk_table->entries[i].cks_enable << i; - volt_without_cks = (uint32_t)((14041 * - (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / - (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); - volt_with_cks = (uint32_t)((13946 * - (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / - (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); - if (volt_without_cks >= volt_with_cks) - volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + - sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); - smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; - } - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - STRETCH_ENABLE, 0x0); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - masterReset, 0x1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - staticEnable, 0x1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - masterReset, 0x0); - - /* Populate CKS Lookup Table */ - if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) - stretch_amount2 = 0; - else if (stretch_amount == 3 || stretch_amount == 4) - stretch_amount2 = 1; - else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - PP_ASSERT_WITH_CODE(false, - "Stretch Amount in PPTable not supported\n", - return -EINVAL); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL); - value &= 0xFFC2FF87; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = - fiji_clock_stretcher_lookup_table[stretch_amount2][0]; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = - fiji_clock_stretcher_lookup_table[stretch_amount2][1]; - clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. - GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. - SclkFrequency) / 100); - if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] < - clock_freq_u16 && - fiji_clock_stretcher_lookup_table[stretch_amount2][1] > - clock_freq_u16) { - /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ - value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; - /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ - value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; - /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ - value |= (fiji_clock_stretch_amount_conversion - [fiji_clock_stretcher_lookup_table[stretch_amount2][3]] - [stretch_amount]) << 3; - } - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. - CKS_LOOKUPTableEntry[0].minFreq); - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. - CKS_LOOKUPTableEntry[0].maxFreq); - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = - fiji_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= - (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL, value); - - /* Populate DDT Lookup Table */ - for (i = 0; i < 4; i++) { - /* Assign the minimum and maximum VID stored - * in the last row of Clock Stretcher Voltage Table. - */ - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].minVID = - (uint8_t) fiji_clock_stretcher_ddt_table[type][i][2]; - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].maxVID = - (uint8_t) fiji_clock_stretcher_ddt_table[type][i][3]; - /* Loop through each SCLK and check the frequency - * to see if it lies within the frequency for clock stretcher. - */ - for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { - cks_setting = 0; - clock_freq = PP_SMC_TO_HOST_UL( - smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); - /* Check the allowed frequency against the sclk level[j]. - * Sclk's endianness has already been converted, - * and it's in 10Khz unit, - * as opposed to Data table, which is in Mhz unit. - */ - if (clock_freq >= - (fiji_clock_stretcher_ddt_table[type][i][0]) * 100) { - cks_setting |= 0x2; - if (clock_freq < - (fiji_clock_stretcher_ddt_table[type][i][1]) * 100) - cks_setting |= 0x1; - } - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); - } - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. - ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].setting); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); - value &= 0xFFFFFFFE; - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); - - return 0; -} - -/** -* Populates the SMC VRConfig field in DPM table. -* -* @param hwmgr the address of the hardware manager -* @param table the SMC DPM table structure to be populated -* @return always 0 -*/ -static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr, - struct SMU73_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint16_t config; - - config = VR_MERGED_WITH_VDDC; - table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); - - /* Set Vddc Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - config = VR_SVI2_PLANE_1; - table->VRConfig |= config; - } else { - PP_ASSERT_WITH_CODE(false, - "VDDC should be on SVI2 control in merged mode!", - ); - } - /* Set Vddci Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - config = VR_SVI2_PLANE_2; /* only in merged mode */ - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - config = VR_SMIO_PATTERN_1; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } - /* Set Mvdd Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - config = VR_SMIO_PATTERN_2; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } - - return 0; -} - -static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t tmp; - int result; - - /* This is a read-modify-write on the first byte of the ARB table. - * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure - * is the field 'current'. - * This solution is ugly, but we never write the whole table only - * individual fields in it. - * In reality this field should not be in that structure - * but in a soft register. - */ - result = smu7_read_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); - - if (result) - return result; - - tmp &= 0x00FFFFFF; - tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - - return smu7_write_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); -} - -static int fiji_save_default_power_profile(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct SMU73_Discrete_GraphicsLevel *levels = - data->smc_state_table.GraphicsLevel; - unsigned min_level = 1; - - hwmgr->default_gfx_power_profile.activity_threshold = - be16_to_cpu(levels[0].ActivityLevel); - hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst; - hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst; - hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; - - hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile; - hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; - - /* Workaround compute SDMA instability: disable lowest SCLK - * DPM level. Optimize compute power profile: Use only highest - * 2 power levels (if more than 2 are available), Hysteresis: - * 0ms up, 5ms down - */ - if (data->smc_state_table.GraphicsDpmLevelCount > 2) - min_level = data->smc_state_table.GraphicsDpmLevelCount - 2; - else if (data->smc_state_table.GraphicsDpmLevelCount == 2) - min_level = 1; - else - min_level = 0; - hwmgr->default_compute_power_profile.min_sclk = - be32_to_cpu(levels[min_level].SclkFrequency); - hwmgr->default_compute_power_profile.up_hyst = 0; - hwmgr->default_compute_power_profile.down_hyst = 5; - - hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; - hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; - - return 0; -} - -static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr) -{ - pp_atomctrl_voltage_table param_led_dpm; - int result = 0; - u32 mask = 0; - - result = atomctrl_get_voltage_table_v3(hwmgr, - VOLTAGE_TYPE_LEDDPM, VOLTAGE_OBJ_GPIO_LUT, - ¶m_led_dpm); - if (result == 0) { - int i, j; - u32 tmp = param_led_dpm.mask_low; - - for (i = 0, j = 0; i < 32; i++) { - if (tmp & 1) { - mask |= (i << (8 * j)); - if (++j >= 3) - break; - } - tmp >>= 1; - } - } - if (mask) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_LedConfig, - mask); - return 0; -} - -/** -* Initializes the SMC table and uploads it -* -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data (PowerState) -* @return always 0 -*/ -int fiji_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct SMU73_Discrete_DpmTable *table = &(smu_data->smc_state_table); - uint8_t i; - struct pp_atomctrl_gpio_pin_assignment gpio_pin; - - fiji_initialize_power_tune_defaults(hwmgr); - - if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) - fiji_populate_smc_voltage_tables(hwmgr, table); - - table->SystemFlags = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - if (data->ulv_supported && table_info->us_ulv_voltage_offset) { - result = fiji_populate_ulv_state(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ULV state!", return result); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, 0x40035); - } - - result = fiji_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Link Level!", return result); - - result = fiji_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Graphics Level!", return result); - - result = fiji_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Memory Level!", return result); - - result = fiji_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACPI Level!", return result); - - result = fiji_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize VCE Level!", return result); - - result = fiji_populate_smc_acp_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACP Level!", return result); - - result = fiji_populate_smc_samu_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize SAMU Level!", return result); - - /* Since only the initial state is completely set up at this point - * (the other states are just copies of the boot state) we only - * need to populate the ARB settings for the initial state. - */ - result = fiji_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to Write ARB settings for the initial state.", return result); - - result = fiji_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize UVD Level!", return result); - - result = fiji_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot Level!", return result); - - result = fiji_populate_smc_initailial_state(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot State!", return result); - - result = fiji_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate BAPM Parameters!", return result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - result = fiji_populate_clock_stretcher_data_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate Clock Stretcher Data Table!", - return result); - } - - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - table->TemperatureLimitHigh = - table_info->cac_dtp_table->usTargetOperatingTemp * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->TemperatureLimitLow = - (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; /* 0:Gen1 1:Gen2 2:Gen3*/ - table->PCIeGenInterval = 1; - table->VRConfig = 0; - - result = fiji_populate_vr_config(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate VRConfig setting!", return result); - - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { - table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, - &gpio_pin)) { - table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } else { - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } - - /* Thermal Output GPIO */ - if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, - &gpio_pin)) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - - table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; - - /* For porlarity read GPIOPAD_A with assigned Gpio pin - * since VBIOS will program this register to set 'inactive state', - * driver can then determine 'active state' from this and - * program SMU with correct polarity - */ - table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & - (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; - - /* if required, combine VRHot/PCC with thermal out GPIO */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot) && - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CombinePCCWithThermalSignal)) - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; - } else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - table->ThermOutGpio = 17; - table->ThermOutPolarity = 1; - table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; - } - - for (i = 0; i < SMU73_MAX_ENTRIES_SMIO; i++) - table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU73_Discrete_DpmTable) - 3 * sizeof(SMU73_PIDController), - SMC_RAM_END); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload dpm data to SMC memory!", return result); - - result = fiji_init_arb_table_index(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload arb data to SMC memory!", return result); - - result = fiji_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate PM fuses to SMC memory!", return result); - - result = fiji_setup_dpm_led_config(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to setup dpm led config", return result); - - fiji_save_default_power_profile(hwmgr); - - return 0; -} - -/** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (smu_data->smu7_data.fan_table_start == 0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL1, FMAX_DUTY100); - - if (duty100 == 0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. - usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr-> - thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = smu7_get_xclk(hwmgr); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> - thermal_controller.advanceFanControlParameters.ulCycleDelay * - reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( - hwmgr->device, CGS_IND_REG__SMC, - CG_MULT_THERMAL_CTRL, TEMP_SEL); - - res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, - (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), - SMC_RAM_END); - - if (!res && hwmgr->thermal_controller. - advanceFanControlParameters.ucMinimumPWMLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanMinPwm, - hwmgr->thermal_controller. - advanceFanControlParameters.ucMinimumPWMLimit); - - if (!res && hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanSclkTarget, - hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit); - - if (res) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - - return 0; -} - - -int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr) -{ - int ret; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - if (smu_data->avfs.avfs_btc_status != AVFS_BTC_ENABLEAVFS) - return 0; - - ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs); - - if (!ret) - /* If this param is not changed, this function could fire unnecessarily */ - smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY; - - return ret; -} - -static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return fiji_program_memory_timing_parameters(hwmgr); - - return 0; -} - -int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (hwmgr->gfx_arbiter.sclk_threshold != - data->low_sclk_interrupt_threshold)) { - data->low_sclk_interrupt_threshold = - hwmgr->gfx_arbiter.sclk_threshold; - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - result = fiji_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - return result; -} - -uint32_t fiji_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU73_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU73_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU73_SoftRegisters, AverageGraphicsActivity); - case PreVBlankGap: - return offsetof(SMU73_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU73_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU73_SoftRegisters, UcodeLoadStatus); - } - case SMU_Discrete_DpmTable: - switch (member) { - case UvdBootLevel: - return offsetof(SMU73_Discrete_DpmTable, UvdBootLevel); - case VceBootLevel: - return offsetof(SMU73_Discrete_DpmTable, VceBootLevel); - case SamuBootLevel: - return offsetof(SMU73_Discrete_DpmTable, SamuBootLevel); - case LowSclkInterruptThreshold: - return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold); - } - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -uint32_t fiji_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU73_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU73_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU73_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU73_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU73_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDGFX: - return SMU73_MAX_LEVELS_VDDGFX; - case SMU_MAX_LEVELS_VDDCI: - return SMU73_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU73_MAX_LEVELS_MVDD; - } - - pr_warn("can't get the mac of %x\n", value); - return 0; -} - - -static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - smu_data->smc_state_table.UvdBootLevel = 0; - if (table_info->mm_dep_table->count > 0) - smu_data->smc_state_table.UvdBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU73_Discrete_DpmTable, - UvdBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0x00FFFFFF; - mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); - return 0; -} - -static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smu_data->smc_state_table.VceBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - else - smu_data->smc_state_table.VceBootLevel = 0; - - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, VceBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFF00FFFF; - mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_VCEDPM_SetEnabledMask, - (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); - return 0; -} - -static int fiji_update_samu_smc_table(struct pp_hwmgr *hwmgr) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - - - smu_data->smc_state_table.SamuBootLevel = 0; - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, SamuBootLevel); - - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFFFFFF00; - mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SAMUDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); - return 0; -} - -int fiji_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - switch (type) { - case SMU_UVD_TABLE: - fiji_update_uvd_smc_table(hwmgr); - break; - case SMU_VCE_TABLE: - fiji_update_vce_smc_table(hwmgr); - break; - case SMU_SAMU_TABLE: - fiji_update_samu_smc_table(hwmgr); - break; - default: - break; - } - return 0; -} - - -/** -* Get the location of various tables inside the FW image. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) - smu_data->smu7_data.dpm_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (!result) { - data->soft_regs_start = tmp; - smu_data->smu7_data.soft_regs_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.mc_reg_table_start = tmp; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.fan_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.arb_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU73_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (!result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (0 != result); - - return error ? -1 : 0; -} - -int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - - /* Program additional LP registers - * that are no longer programmed by VBIOS - */ - cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); - - return 0; -} - -bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request) -{ - struct fiji_smumgr *smu_data = (struct fiji_smumgr *) - (hwmgr->smu_backend); - struct SMU73_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) * - SMU73_MAX_LEVELS_GRAPHICS; - uint32_t i; - - for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { - levels[i].ActivityLevel = - cpu_to_be16(request->activity_threshold); - levels[i].EnabledForActivity = 1; - levels[i].UpHyst = request->up_hyst; - levels[i].DownHyst = request->down_hyst; - } - - return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - array_size, SMC_RAM_END); -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.h b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.h deleted file mode 100644 index d9c72d992e30..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smc.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef FIJI_SMC_H -#define FIJI_SMC_H - -#include "smumgr.h" -#include "smu73.h" - -struct fiji_pt_defaults { - uint8_t SviLoadLineEn; - uint8_t SviLoadLineVddC; - uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; - uint8_t TDC_MAWt; - uint8_t TdcWaterfallCtl; - uint8_t DTEAmbientTempBase; -}; - -int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); -int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr); -int fiji_init_smc_table(struct pp_hwmgr *hwmgr); -int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); -int fiji_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type); -int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr); -uint32_t fiji_get_offsetof(uint32_t type, uint32_t member); -uint32_t fiji_get_mac_definition(uint32_t value); -int fiji_process_firmware_header(struct pp_hwmgr *hwmgr); -int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); -bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr); -int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request); -int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr); -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c index 5b25e067b2f1..f572beff197f 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c @@ -23,6 +23,7 @@ #include "pp_debug.h" #include "smumgr.h" +#include "smu7_dyn_defaults.h" #include "smu73.h" #include "smu_ucode_xfer_vi.h" #include "fiji_smumgr.h" @@ -37,14 +38,54 @@ #include "gca/gfx_8_0_d.h" #include "bif/bif_5_0_d.h" #include "bif/bif_5_0_sh_mask.h" -#include "fiji_pwrvirus.h" -#include "fiji_smc.h" +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" +#include "hardwaremanager.h" +#include "cgs_common.h" +#include "atombios.h" +#include "pppcielanes.h" +#include "hwmgr.h" +#include "smu7_hwmgr.h" + #define AVFS_EN_MSB 1568 #define AVFS_EN_LSB 1568 #define FIJI_SMC_SIZE 0x20000 +#define VOLTAGE_SCALE 4 +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 +#define VDDC_VDDCI_DELTA 300 +#define MC_CG_ARB_FREQ_F1 0x0b + +/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs + * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] + */ +static const uint16_t fiji_clock_stretcher_lookup_table[2][4] = { + {600, 1050, 3, 0}, {600, 1050, 6, 1} }; + +/* [FF, SS] type, [] 4 voltage ranges, and + * [Floor Freq, Boundary Freq, VID min , VID max] + */ +static const uint32_t fiji_clock_stretcher_ddt_table[2][4][4] = { + { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, + { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } }; + +/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] + * (coming from PWR_CKS_CNTL.stretch_amount reg spec) + */ +static const uint8_t fiji_clock_stretch_amount_conversion[2][6] = { + {0, 1, 3, 2, 4, 5}, {0, 2, 4, 5, 6, 5} }; + +static const struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { + /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */ + {1, 0xF, 0xFD, + /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */ + 0x19, 5, 45} +}; + static const struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = { /* Min Sclk pcie DeepSleep Activity CgSpll CgSpll spllSpread SpllSpread CcPwr CcPwr Sclk Display Enabled Enabled Voltage Power */ /* Voltage, Frequency, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, Spectrum, Spectrum2, DynRm, DynRm1 Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */ @@ -159,39 +200,6 @@ static int fiji_start_smu_in_non_protection_mode(struct pp_hwmgr *hwmgr) return result; } -static int fiji_setup_pwr_virus(struct pp_hwmgr *hwmgr) -{ - int i; - int result = -EINVAL; - uint32_t reg, data; - - const PWR_Command_Table *pvirus = PwrVirusTable; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - for (i = 0; i < PWR_VIRUS_TABLE_SIZE; i++) { - switch (pvirus->command) { - case PwrCmdWrite: - reg = pvirus->reg; - data = pvirus->data; - cgs_write_register(hwmgr->device, reg, data); - break; - - case PwrCmdEnd: - result = 0; - break; - - default: - pr_info("Table Exit with Invalid Command!"); - smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; - result = -EINVAL; - break; - } - pvirus++; - } - - return result; -} - static int fiji_start_avfs_btc(struct pp_hwmgr *hwmgr) { int result = 0; @@ -270,7 +278,7 @@ static int fiji_avfs_event_mgr(struct pp_hwmgr *hwmgr, bool smu_started) " table over to SMU", return -EINVAL;); smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; - PP_ASSERT_WITH_CODE(0 == fiji_setup_pwr_virus(hwmgr), + PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr), "[AVFS][fiji_avfs_event_mgr] Could not setup " "Pwr Virus for AVFS ", return -EINVAL;); @@ -358,13 +366,6 @@ static bool fiji_is_hw_avfs_present(struct pp_hwmgr *hwmgr) return false; } -/** -* Write a 32bit value to the SMC SRAM space. -* ALL PARAMETERS ARE IN HOST BYTE ORDER. -* @param smumgr the address of the powerplay hardware manager. -* @param smc_addr the address in the SMC RAM to access. -* @param value to write to the SMC SRAM. -*/ static int fiji_smu_init(struct pp_hwmgr *hwmgr) { int i; @@ -386,6 +387,2334 @@ static int fiji_smu_init(struct pp_hwmgr *hwmgr) return 0; } +static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, + uint32_t clock, uint32_t *voltage, uint32_t *mvdd) +{ + uint32_t i; + uint16_t vddci; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + *voltage = *mvdd = 0; + + + /* clock - voltage dependency table is empty table */ + if (dep_table->count == 0) + return -EINVAL; + + for (i = 0; i < dep_table->count; i++) { + /* find first sclk bigger than request */ + if (dep_table->entries[i].clk >= clock) { + *voltage |= (dep_table->entries[i].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i].vddci) + *voltage |= (dep_table->entries[i].vddci * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i].mvdd * + VOLTAGE_SCALE; + + *voltage |= 1 << PHASES_SHIFT; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i-1].vddci) { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; + + return 0; +} + + +static uint16_t scale_fan_gain_settings(uint16_t raw_setting) +{ + uint32_t tmp; + tmp = raw_setting * 4096 / 100; + return (uint16_t)tmp; +} + +static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t *sda) +{ + switch (line) { + case SMU7_I2CLineID_DDC1: + *scl = SMU7_I2C_DDC1CLK; + *sda = SMU7_I2C_DDC1DATA; + break; + case SMU7_I2CLineID_DDC2: + *scl = SMU7_I2C_DDC2CLK; + *sda = SMU7_I2C_DDC2DATA; + break; + case SMU7_I2CLineID_DDC3: + *scl = SMU7_I2C_DDC3CLK; + *sda = SMU7_I2C_DDC3DATA; + break; + case SMU7_I2CLineID_DDC4: + *scl = SMU7_I2C_DDC4CLK; + *sda = SMU7_I2C_DDC4DATA; + break; + case SMU7_I2CLineID_DDC5: + *scl = SMU7_I2C_DDC5CLK; + *sda = SMU7_I2C_DDC5DATA; + break; + case SMU7_I2CLineID_DDC6: + *scl = SMU7_I2C_DDC6CLK; + *sda = SMU7_I2C_DDC6DATA; + break; + case SMU7_I2CLineID_SCLSDA: + *scl = SMU7_I2C_SCL; + *sda = SMU7_I2C_SDA; + break; + case SMU7_I2CLineID_DDCVGA: + *scl = SMU7_I2C_DDCVGACLK; + *sda = SMU7_I2C_DDCVGADATA; + break; + default: + *scl = 0; + *sda = 0; + break; + } +} + +static void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (table_info && + table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && + table_info->cac_dtp_table->usPowerTuneDataSetID) + smu_data->power_tune_defaults = + &fiji_power_tune_data_set_array + [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; + else + smu_data->power_tune_defaults = &fiji_power_tune_data_set_array[0]; + +} + +static int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; + + SMU73_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; + struct pp_advance_fan_control_parameters *fan_table = + &hwmgr->thermal_controller.advanceFanControlParameters; + uint8_t uc_scl, uc_sda; + + /* TDP number of fraction bits are changed from 8 to 7 for Fiji + * as requested by SMC team + */ + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usTDP * 128)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usTDP * 128)); + + PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, + "Target Operating Temp is out of Range!", + ); + + dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase; + + /* The following are for new Fiji Multi-input fan/thermal control */ + dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( + cac_dtp_table->usTargetOperatingTemp * 256); + dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitHotspot * 256); + dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitLiquid1 * 256); + dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitLiquid2 * 256); + dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitVrVddc * 256); + dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitVrMvdd * 256); + dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitPlx * 256); + + dpm_table->FanGainEdge = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainEdge)); + dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHotspot)); + dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainLiquid)); + dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainVrVddc)); + dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainVrMvdd)); + dpm_table->FanGainPlx = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainPlx)); + dpm_table->FanGainHbm = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHbm)); + + dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address; + dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address; + dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address; + dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address; + + get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Liquid_I2C_LineSCL = uc_scl; + dpm_table->Liquid_I2C_LineSDA = uc_sda; + + get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Vr_I2C_LineSCL = uc_scl; + dpm_table->Vr_I2C_LineSDA = uc_sda; + + get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Plx_I2C_LineSCL = uc_scl; + dpm_table->Plx_I2C_LineSDA = uc_sda; + + return 0; +} + + +static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; + smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + + +static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; + + /* TDC number of fraction bits are changed from 8 to 7 + * for Fiji as requested by SMC team + */ + tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->TDC_VDDC_ThrottleReleaseLimitPerc; + smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; + + return 0; +} + +static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + const struct fiji_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else { + smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; + smu_data->power_tune_table.LPMLTemperatureMin = + (uint8_t)((temp >> 16) & 0xff); + smu_data->power_tune_table.LPMLTemperatureMax = + (uint8_t)((temp >> 8) & 0xff); + smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); + } + return 0; +} + +static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + int i; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; + + return 0; +} + +static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + if ((hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity & (1 << 15)) || + 0 == hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity) + hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity = hwmgr->thermal_controller. + advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = + PP_HOST_TO_SMC_US(hwmgr->thermal_controller. + advanceFanControlParameters.usFanOutputSensitivity); + return 0; +} + +static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + + HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(HiSidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(LoSidd); + + return 0; +} + +static int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + uint32_t pm_fuse_table_offset; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed!", + return -EINVAL); + + /* DW6 */ + if (fiji_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed!", + return -EINVAL); + /* DW7 */ + if (fiji_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed!", return -EINVAL); + /* DW8 */ + if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl, " + "LPMLTemperature Min and Max Failed!", + return -EINVAL); + + /* DW9-DW12 */ + if (0 != fiji_populate_temperature_scaler(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed!", + return -EINVAL); + + /* DW13-DW14 */ + if (fiji_populate_fuzzy_fan(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate Fuzzy Fan Control parameters Failed!", + return -EINVAL); + + /* DW15-DW18 */ + if (fiji_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed!", + return -EINVAL); + + /* DW20 */ + if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate BapmVddCBaseLeakage Hi and Lo " + "Sidd Failed!", return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU73_Discrete_PmFuses), SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed!", + return -EINVAL); + } + return 0; +} + +static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *lookup_table = + table_info->vddc_lookup_table; + /* tables is already swapped, so in order to use the value from it, + * we need to swap it back. + * We are populating vddc CAC data to BapmVddc table + * in split and merged mode + */ + + for (count = 0; count < lookup_table->count; count++) { + index = phm_get_voltage_index(lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = + convert_to_vid(lookup_table->entries[index].us_cac_low); + table->BapmVddcVidHiSidd[count] = + convert_to_vid(lookup_table->entries[index].us_cac_high); + } + + return 0; +} + +static int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result; + + result = fiji_populate_cac_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate CAC voltage tables to SMC", + return -EINVAL); + + return 0; +} + +static int fiji_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_Ulv *state) +{ + int result = 0; + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; + state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * + VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); + + state->VddcPhase = 1; + + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + } + return result; +} + +static int fiji_populate_ulv_state(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + return fiji_populate_ulv_level(hwmgr, &table->Ulv); +} + +static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + int i; + + /* Index (dpm_table->pcie_speed_table.count) + * is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( + dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t ref_clock; + uint32_t ref_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ + ref_clock = atomctrl_get_reference_clock(hwmgr); + ref_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider */ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup */ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + struct pp_atomctrl_internal_ss_info ssInfo; + + uint32_t vco_freq = clock * dividers.uc_pll_post_div; + if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, + vco_freq, &ssInfo)) { + /* + * ss_info.speed_spectrum_percentage -- in unit of 0.01% + * ss_info.speed_spectrum_rate -- in unit of khz + * + * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 + */ + uint32_t clk_s = ref_clock * 5 / + (ref_divider * ssInfo.speed_spectrum_rate); + /* clkv = 2 * D * fbdiv / NS */ + uint32_t clk_v = 4 * ssInfo.speed_spectrum_percentage * + fbdiv / (clk_s * 10000); + + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, + CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); + } + } + + sclk->SclkFrequency = clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint16_t sclk_al_threshold, + struct SMU73_Discrete_GraphicsLevel *level) +{ + int result; + /* PP_Clocks minClocks; */ + uint32_t threshold, mvdd; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + result = fiji_calculate_sclk_params(hwmgr, clock, level); + + /* populate graphics levels */ + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, clock, + (uint32_t *)(&level->MinVoltage), &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for " + "VDDC engine clock dependency table", + return result); + + level->SclkFrequency = clock; + level->ActivityLevel = sclk_al_threshold; + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + level->EnabledForThrottle = 1; + level->UpHyst = 10; + level->DownHyst = 0; + level->VoltageDownHyst = 0; + level->PowerThrottle = 0; + + threshold = clock * data->fast_watermark_threshold / 100; + + data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) + level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, + hwmgr->display_config.min_core_set_clock_in_sr); + + + /* Default to slow, highest DPM level will be + * set to PPSMC_DISPLAY_WATERMARK_LOW later. + */ + level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + + return 0; +} + +static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count; + int result = 0; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) * + SMU73_MAX_LEVELS_GRAPHICS; + struct SMU73_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t i, max_entry; + uint8_t hightest_pcie_level_enabled = 0, + lowest_pcie_level_enabled = 0, + mid_pcie_level_enabled = 0, + count = 0; + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = fiji_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + (uint16_t)smu_data->activity_target[i], + &levels[i]); + if (result) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + levels[i].DeepSleepDivId = 0; + } + + /* Only enable level 0 for now.*/ + levels[0].EnabledForActivity = 1; + + /* set highest level watermark to high */ + levels[dpm_table->sclk_table.count - 1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + max_entry = pcie_entry_cnt - 1; + for (i = 0; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = + (uint8_t) ((i < max_entry) ? i : max_entry); + } else { + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (hightest_pcie_level_enabled + 1))) != 0)) + hightest_pcie_level_enabled++; + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << lowest_pcie_level_enabled)) == 0)) + lowest_pcie_level_enabled++; + + while ((count < hightest_pcie_level_enabled) && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) + count++; + + mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < + hightest_pcie_level_enabled ? + (lowest_pcie_level_enabled + 1 + count) : + hightest_pcie_level_enabled; + + /* set pcieDpmLevel to hightest_pcie_level_enabled */ + for (i = 2; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = hightest_pcie_level_enabled; + + /* set pcieDpmLevel to lowest_pcie_level_enabled */ + levels[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled */ + levels[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + + +/** + * MCLK Frequency Ratio + * SEQ_CG_RESP Bit[31:24] - 0x0 + * Bit[27:24] \96 DDR3 Frequency ratio + * 0x0 <= 100MHz, 450 < 0x8 <= 500MHz + * 100 < 0x1 <= 150MHz, 500 < 0x9 <= 550MHz + * 150 < 0x2 <= 200MHz, 550 < 0xA <= 600MHz + * 200 < 0x3 <= 250MHz, 600 < 0xB <= 650MHz + * 250 < 0x4 <= 300MHz, 650 < 0xC <= 700MHz + * 300 < 0x5 <= 350MHz, 700 < 0xD <= 750MHz + * 350 < 0x6 <= 400MHz, 750 < 0xE <= 800MHz + * 400 < 0x7 <= 450MHz, 800 < 0xF + */ +static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock) +{ + if (mem_clock <= 10000) + return 0x0; + if (mem_clock <= 15000) + return 0x1; + if (mem_clock <= 20000) + return 0x2; + if (mem_clock <= 25000) + return 0x3; + if (mem_clock <= 30000) + return 0x4; + if (mem_clock <= 35000) + return 0x5; + if (mem_clock <= 40000) + return 0x6; + if (mem_clock <= 45000) + return 0x7; + if (mem_clock <= 50000) + return 0x8; + if (mem_clock <= 55000) + return 0x9; + if (mem_clock <= 60000) + return 0xa; + if (mem_clock <= 65000) + return 0xb; + if (mem_clock <= 70000) + return 0xc; + if (mem_clock <= 75000) + return 0xd; + if (mem_clock <= 80000) + return 0xe; + /* mem_clock > 800MHz */ + return 0xf; +} + +static int fiji_calculate_mclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_MemoryLevel *mclk) +{ + struct pp_atomctrl_memory_clock_param mem_param; + int result; + + result = atomctrl_get_memory_pll_dividers_vi(hwmgr, clock, &mem_param); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to get Memory PLL Dividers.", + ); + + /* Save the result data to outpupt memory level structure */ + mclk->MclkFrequency = clock; + mclk->MclkDivider = (uint8_t)mem_param.mpll_post_divider; + mclk->FreqRange = fiji_get_mclk_frequency_ratio(clock); + + return result; +} + +static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_MemoryLevel *mem_level) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result = 0; + uint32_t mclk_stutter_mode_threshold = 60000; + + if (table_info->vdd_dep_on_mclk) { + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, clock, + (uint32_t *)(&mem_level->MinVoltage), &mem_level->MinMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory " + "VDDC voltage dependency table", return result); + } + + mem_level->EnabledForThrottle = 1; + mem_level->EnabledForActivity = 0; + mem_level->UpHyst = 0; + mem_level->DownHyst = 100; + mem_level->VoltageDownHyst = 0; + mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target; + mem_level->StutterEnable = false; + + mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + /* enable stutter mode if all the follow condition applied + * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI, + * &(data->DisplayTiming.numExistingDisplays)); + */ + data->display_timing.num_existing_displays = 1; + + if (mclk_stutter_mode_threshold && + (clock <= mclk_stutter_mode_threshold) && + (!data->is_uvd_enabled) && + (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE) & 0x1)) + mem_level->StutterEnable = true; + + result = fiji_calculate_mclk_params(hwmgr, clock, mem_level); + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); + } + return result; +} + +static int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + /* populate MCLK dpm table to SMU7 */ + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, MemoryLevel); + uint32_t array_size = sizeof(SMU73_Discrete_MemoryLevel) * + SMU73_MAX_LEVELS_MEMORY; + struct SMU73_Discrete_MemoryLevel *levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", + return -EINVAL); + result = fiji_populate_single_memory_level(hwmgr, + dpm_table->mclk_table.dpm_levels[i].value, + &levels[i]); + if (result) + return result; + } + + /* Only enable level 0 for now. */ + levels[0].EnabledForActivity = 1; + + /* in order to prevent MC activity from stutter mode to push DPM up. + * the UVD change complements this by putting the MCLK in + * a higher state by default such that we are not effected by + * up threshold or and MCLK DPM latency. + */ + levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target; + CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = + (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + /* set highest level watermark to high */ + levels[dpm_table->mclk_table.count - 1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + +static int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr, + uint32_t mclk, SMIO_Pattern *smio_pat) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { + smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", + return -EINVAL); + } else + return -EINVAL; + + return 0; +} + +static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = 0; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct pp_atomctrl_clock_dividers_vi dividers; + SMIO_Pattern vol_level; + uint32_t mvdd; + uint16_t us_mvdd; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (!data->sclk_dpm_key_disabled) { + /* Get MinVoltage and Frequency from DPM0, + * already converted to SMC_UL */ + table->ACPILevel.SclkFrequency = + data->dpm_table.sclk_table.dpm_levels[0].value; + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, + table->ACPILevel.SclkFrequency, + (uint32_t *)(&table->ACPILevel.MinVoltage), &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDC voltage value " \ + "in Clock Dependency Table", + ); + } else { + table->ACPILevel.SclkFrequency = + data->vbios_boot_state.sclk_bootup_value; + table->ACPILevel.MinVoltage = + data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE; + } + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, + SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + if (!data->mclk_dpm_key_disabled) { + /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ + table->MemoryACPILevel.MclkFrequency = + data->dpm_table.mclk_table.dpm_levels[0].value; + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, + table->MemoryACPILevel.MclkFrequency, + (uint32_t *)(&table->MemoryACPILevel.MinVoltage), &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDCI voltage value in Clock Dependency Table", + ); + } else { + table->MemoryACPILevel.MclkFrequency = + data->vbios_boot_state.mclk_bootup_value; + table->MemoryACPILevel.MinVoltage = + data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE; + } + + us_mvdd = 0; + if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || + (data->mclk_dpm_key_disabled)) + us_mvdd = data->vbios_boot_state.mvdd_bootup_value; + else { + if (!fiji_populate_mvdd_value(hwmgr, + data->dpm_table.mclk_table.dpm_levels[0].value, + &vol_level)) + us_mvdd = vol_level.Voltage; + } + + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(us_mvdd * VOLTAGE_SCALE); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + table->MemoryACPILevel.ActivityLevel = + PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); + + table->MemoryACPILevel.StutterEnable = false; + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); + + return result; +} + +static int fiji_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + table->VceLevelCount = (uint8_t)(mm_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage = 0; + table->VceLevel[count].MinVoltage |= + (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + table->VceLevel[count].MinVoltage |= + ((mm_table->entries[count].vddc - VDDC_VDDCI_DELTA) * + VOLTAGE_SCALE) << VDDCI_SHIFT; + table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /*retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); + } + return result; +} + +static int fiji_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + table->AcpLevelCount = (uint8_t)(mm_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = mm_table->entries[count].aclk; + table->AcpLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + table->AcpLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - + VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->AcpLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].MinVoltage); + } + return result; +} + +static int fiji_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + table->SamuBootLevel = 0; + table->SamuLevelCount = (uint8_t)(mm_table->count); + + for (count = 0; count < table->SamuLevelCount; count++) { + /* not sure whether we need evclk or not */ + table->SamuLevel[count].MinVoltage = 0; + table->SamuLevel[count].Frequency = mm_table->entries[count].samclock; + table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + table->SamuLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - + VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->SamuLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for samu clock", return result); + + table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage); + } + return result; +} + +static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, + int32_t eng_clock, int32_t mem_clock, + struct SMU73_Discrete_MCArbDramTimingTableEntry *arb_regs) +{ + uint32_t dram_timing; + uint32_t dram_timing2; + uint32_t burstTime; + ULONG state, trrds, trrdl; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + eng_clock, mem_clock); + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME); + + state = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, STATE0); + trrds = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDS0); + trrdl = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDL0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + arb_regs->TRRDS = (uint8_t)trrds; + arb_regs->TRRDL = (uint8_t)trrdl; + + return 0; +} + +static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct SMU73_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + int result = 0; + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = fiji_populate_memory_timing_parameters(hwmgr, + data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + if (result) + break; + } + } + + if (!result) + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU73_Discrete_MCArbDramTimingTable), + SMC_RAM_END); + return result; +} + +static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + table->UvdLevelCount = (uint8_t)(mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].MinVoltage = 0; + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + table->UvdLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - + VDDC_VDDCI_DELTA) * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); + + } + return result; +} + +static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table */ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(table->GraphicsBootLevel)); + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(table->MemoryBootLevel)); + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value * + VOLTAGE_SCALE; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return 0; +} + +static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint8_t count, level; + + count = (uint8_t)(table_info->vdd_dep_on_sclk->count); + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_sclk->entries[level].clk >= + data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(table_info->vdd_dep_on_mclk->count); + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_mclk->entries[level].clk >= + data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, + volt_with_cks, value; + uint16_t clock_freq_u16; + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, + volt_offset = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + + stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; + + /* Read SMU_Eefuse to read and calculate RO and determine + * if the part is SS or FF. if RO >= 1660MHz, part is FF. + */ + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (146 * 4)); + efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (148 * 4)); + efuse &= 0xFF000000; + efuse = efuse >> 24; + efuse2 &= 0xF; + + if (efuse2 == 1) + ro = (2300 - 1350) * efuse / 255 + 1350; + else + ro = (2500 - 1000) * efuse / 255 + 1000; + + if (ro >= 1660) + type = 0; + else + type = 1; + + /* Populate Stretch amount */ + smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; + + /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ + for (i = 0; i < sclk_table->count; i++) { + smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= + sclk_table->entries[i].cks_enable << i; + volt_without_cks = (uint32_t)((14041 * + (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / + (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); + volt_with_cks = (uint32_t)((13946 * + (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / + (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); + if (volt_without_cks >= volt_with_cks) + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + + sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); + smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; + } + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + STRETCH_ENABLE, 0x0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + staticEnable, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x0); + + /* Populate CKS Lookup Table */ + if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) + stretch_amount2 = 0; + else if (stretch_amount == 3 || stretch_amount == 4) + stretch_amount2 = 1; + else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + PP_ASSERT_WITH_CODE(false, + "Stretch Amount in PPTable not supported\n", + return -EINVAL); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL); + value &= 0xFFC2FF87; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = + fiji_clock_stretcher_lookup_table[stretch_amount2][0]; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = + fiji_clock_stretcher_lookup_table[stretch_amount2][1]; + clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. + GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. + SclkFrequency) / 100); + if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] < + clock_freq_u16 && + fiji_clock_stretcher_lookup_table[stretch_amount2][1] > + clock_freq_u16) { + /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ + value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; + /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ + value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; + /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ + value |= (fiji_clock_stretch_amount_conversion + [fiji_clock_stretcher_lookup_table[stretch_amount2][3]] + [stretch_amount]) << 3; + } + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].minFreq); + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].maxFreq); + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = + fiji_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= + (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL, value); + + /* Populate DDT Lookup Table */ + for (i = 0; i < 4; i++) { + /* Assign the minimum and maximum VID stored + * in the last row of Clock Stretcher Voltage Table. + */ + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].minVID = + (uint8_t) fiji_clock_stretcher_ddt_table[type][i][2]; + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].maxVID = + (uint8_t) fiji_clock_stretcher_ddt_table[type][i][3]; + /* Loop through each SCLK and check the frequency + * to see if it lies within the frequency for clock stretcher. + */ + for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { + cks_setting = 0; + clock_freq = PP_SMC_TO_HOST_UL( + smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); + /* Check the allowed frequency against the sclk level[j]. + * Sclk's endianness has already been converted, + * and it's in 10Khz unit, + * as opposed to Data table, which is in Mhz unit. + */ + if (clock_freq >= + (fiji_clock_stretcher_ddt_table[type][i][0]) * 100) { + cks_setting |= 0x2; + if (clock_freq < + (fiji_clock_stretcher_ddt_table[type][i][1]) * 100) + cks_setting |= 0x1; + } + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); + } + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. + ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); + value &= 0xFFFFFFFE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); + + return 0; +} + +static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint16_t config; + + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); + + /* Set Vddc Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + PP_ASSERT_WITH_CODE(false, + "VDDC should be on SVI2 control in merged mode!", + ); + } + /* Set Vddci Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } + /* Set Mvdd Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + config = VR_SMIO_PATTERN_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } + + return 0; +} + +static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t tmp; + int result; + + /* This is a read-modify-write on the first byte of the ARB table. + * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure + * is the field 'current'. + * This solution is ugly, but we never write the whole table only + * individual fields in it. + * In reality this field should not be in that structure + * but in a soft register. + */ + result = smu7_read_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); + + if (result) + return result; + + tmp &= 0x00FFFFFF; + tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; + + return smu7_write_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); +} + +static int fiji_save_default_power_profile(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct SMU73_Discrete_GraphicsLevel *levels = + data->smc_state_table.GraphicsLevel; + unsigned min_level = 1; + + hwmgr->default_gfx_power_profile.activity_threshold = + be16_to_cpu(levels[0].ActivityLevel); + hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst; + hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst; + hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; + + hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; + + /* Workaround compute SDMA instability: disable lowest SCLK + * DPM level. Optimize compute power profile: Use only highest + * 2 power levels (if more than 2 are available), Hysteresis: + * 0ms up, 5ms down + */ + if (data->smc_state_table.GraphicsDpmLevelCount > 2) + min_level = data->smc_state_table.GraphicsDpmLevelCount - 2; + else if (data->smc_state_table.GraphicsDpmLevelCount == 2) + min_level = 1; + else + min_level = 0; + hwmgr->default_compute_power_profile.min_sclk = + be32_to_cpu(levels[min_level].SclkFrequency); + hwmgr->default_compute_power_profile.up_hyst = 0; + hwmgr->default_compute_power_profile.down_hyst = 5; + + hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; + + return 0; +} + +static int fiji_setup_dpm_led_config(struct pp_hwmgr *hwmgr) +{ + pp_atomctrl_voltage_table param_led_dpm; + int result = 0; + u32 mask = 0; + + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_LEDDPM, VOLTAGE_OBJ_GPIO_LUT, + ¶m_led_dpm); + if (result == 0) { + int i, j; + u32 tmp = param_led_dpm.mask_low; + + for (i = 0, j = 0; i < 32; i++) { + if (tmp & 1) { + mask |= (i << (8 * j)); + if (++j >= 3) + break; + } + tmp >>= 1; + } + } + if (mask) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_LedConfig, + mask); + return 0; +} + +static int fiji_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct SMU73_Discrete_DpmTable *table = &(smu_data->smc_state_table); + uint8_t i; + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + + fiji_initialize_power_tune_defaults(hwmgr); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) + fiji_populate_smc_voltage_tables(hwmgr, table); + + table->SystemFlags = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (data->ulv_supported && table_info->us_ulv_voltage_offset) { + result = fiji_populate_ulv_state(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = fiji_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result); + + result = fiji_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result); + + result = fiji_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result); + + result = fiji_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result); + + result = fiji_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result); + + result = fiji_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result); + + result = fiji_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize SAMU Level!", return result); + + /* Since only the initial state is completely set up at this point + * (the other states are just copies of the boot state) we only + * need to populate the ARB settings for the initial state. + */ + result = fiji_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result); + + result = fiji_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result); + + result = fiji_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result); + + result = fiji_populate_smc_initailial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot State!", return result); + + result = fiji_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate BAPM Parameters!", return result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = fiji_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate Clock Stretcher Data Table!", + return result); + } + + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + table_info->cac_dtp_table->usTargetOperatingTemp * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + table->PCIeBootLinkLevel = 0; /* 0:Gen1 1:Gen2 2:Gen3*/ + table->PCIeGenInterval = 1; + table->VRConfig = 0; + + result = fiji_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate VRConfig setting!", return result); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, + &gpio_pin)) { + table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } else { + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + /* Thermal Output GPIO */ + if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, + &gpio_pin)) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; + + /* For porlarity read GPIOPAD_A with assigned Gpio pin + * since VBIOS will program this register to set 'inactive state', + * driver can then determine 'active state' from this and + * program SMU with correct polarity + */ + table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & + (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot) && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CombinePCCWithThermalSignal)) + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + for (i = 0; i < SMU73_MAX_ENTRIES_SMIO; i++) + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU73_Discrete_DpmTable) - 3 * sizeof(SMU73_PIDController), + SMC_RAM_END); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result); + + result = fiji_init_arb_table_index(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload arb data to SMC memory!", return result); + + result = fiji_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + result = fiji_setup_dpm_led_config(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to setup dpm led config", return result); + + fiji_save_default_power_profile(hwmgr); + + return 0; +} + +static int fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (smu_data->smu7_data.fan_table_start == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. + usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - + hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr-> + thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = smu7_get_xclk(hwmgr); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> + thermal_controller.advanceFanControlParameters.ulCycleDelay * + reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( + hwmgr->device, CGS_IND_REG__SMC, + CG_MULT_THERMAL_CTRL, TEMP_SEL); + + res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, + (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), + SMC_RAM_END); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanMinPwm, + hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanSclkTarget, + hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit); + + if (res) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + return 0; +} + + +static int fiji_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +{ + int ret; + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + + if (smu_data->avfs.avfs_btc_status != AVFS_BTC_ENABLEAVFS) + return 0; + + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs); + + if (!ret) + /* If this param is not changed, this function could fire unnecessarily */ + smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY; + + return ret; +} + +static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return fiji_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (hwmgr->gfx_arbiter.sclk_threshold != + data->low_sclk_interrupt_threshold)) { + data->low_sclk_interrupt_threshold = + hwmgr->gfx_arbiter.sclk_threshold; + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + result = fiji_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + return result; +} + +static uint32_t fiji_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU73_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU73_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU73_SoftRegisters, AverageGraphicsActivity); + case PreVBlankGap: + return offsetof(SMU73_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU73_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU73_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU73_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + case SMU_Discrete_DpmTable: + switch (member) { + case UvdBootLevel: + return offsetof(SMU73_Discrete_DpmTable, UvdBootLevel); + case VceBootLevel: + return offsetof(SMU73_Discrete_DpmTable, VceBootLevel); + case SamuBootLevel: + return offsetof(SMU73_Discrete_DpmTable, SamuBootLevel); + case LowSclkInterruptThreshold: + return offsetof(SMU73_Discrete_DpmTable, LowSclkInterruptThreshold); + } + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t fiji_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU73_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU73_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU73_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU73_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU73_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDGFX: + return SMU73_MAX_LEVELS_VDDGFX; + case SMU_MAX_LEVELS_VDDCI: + return SMU73_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU73_MAX_LEVELS_MVDD; + } + + pr_warn("can't get the mac of %x\n", value); + return 0; +} + + +static int fiji_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + smu_data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + smu_data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU73_Discrete_DpmTable, + UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); + return 0; +} + +static int fiji_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smu_data->smc_state_table.VceBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + else + smu_data->smc_state_table.VceBootLevel = 0; + + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); + return 0; +} + +static int fiji_update_samu_smc_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + + + smu_data->smc_state_table.SamuBootLevel = 0; + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, SamuBootLevel); + + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFFFFFF00; + mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SAMUDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); + return 0; +} + +static int fiji_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + fiji_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + fiji_update_vce_smc_table(hwmgr); + break; + case SMU_SAMU_TABLE: + fiji_update_samu_smc_table(hwmgr); + break; + default: + break; + } + return 0; +} + +static int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smu_backend); + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) + smu_data->smu7_data.dpm_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (!result) { + data->soft_regs_start = tmp; + smu_data->smu7_data.soft_regs_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.mc_reg_table_start = tmp; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.fan_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.arb_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (!result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? -1 : 0; +} + +static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + + /* Program additional LP registers + * that are no longer programmed by VBIOS + */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + + return 0; +} + +static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static int fiji_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + struct fiji_smumgr *smu_data = (struct fiji_smumgr *) + (hwmgr->smu_backend); + struct SMU73_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) * + SMU73_MAX_LEVELS_GRAPHICS; + uint32_t i; + + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + levels[i].ActivityLevel = + cpu_to_be16(request->activity_threshold); + levels[i].EnabledForActivity = 1; + levels[i].UpHyst = request->up_hyst; + levels[i].DownHyst = request->down_hyst; + } + + return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + array_size, SMC_RAM_END); +} const struct pp_smumgr_func fiji_smu_funcs = { .smu_init = &fiji_smu_init, diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h index 175bf9f8ef9c..279647772578 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h @@ -28,6 +28,15 @@ #include "smu7_smumgr.h" +struct fiji_pt_defaults { + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + uint8_t TdcWaterfallCtl; + uint8_t DTEAmbientTempBase; +}; + struct fiji_smumgr { struct smu7_smumgr smu7_data; struct SMU73_Discrete_DpmTable smc_state_table; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c deleted file mode 100644 index efb0fc033274..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smc.c +++ /dev/null @@ -1,2568 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * - */ - -#include "pp_debug.h" -#include "iceland_smc.h" -#include "smu7_dyn_defaults.h" - -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "atombios.h" -#include "pppcielanes.h" -#include "pp_endian.h" -#include "smu7_ppsmc.h" - -#include "smu71_discrete.h" - -#include "smu/smu_7_1_1_d.h" -#include "smu/smu_7_1_1_sh_mask.h" - -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" - -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" - -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" -#include "processpptables.h" - -#include "iceland_smumgr.h" - -#define VOLTAGE_SCALE 4 -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 -#define MC_CG_ARB_FREQ_F1 0x0b -#define VDDC_VDDCI_DELTA 200 - -#define DEVICE_ID_VI_ICELAND_M_6900 0x6900 -#define DEVICE_ID_VI_ICELAND_M_6901 0x6901 -#define DEVICE_ID_VI_ICELAND_M_6902 0x6902 -#define DEVICE_ID_VI_ICELAND_M_6903 0x6903 - -static const struct iceland_pt_defaults defaults_iceland = { - /* - * sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, - * TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT - */ - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, - { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, - { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } -}; - -/* 35W - XT, XTL */ -static const struct iceland_pt_defaults defaults_icelandxt = { - /* - * sviLoadLIneEn, SviLoadLineVddC, - * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, - * BAPM_TEMP_GRADIENT - */ - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0, - { 0xA7, 0x0, 0x0, 0xB5, 0x0, 0x0, 0x9F, 0x0, 0x0, 0xD6, 0x0, 0x0, 0xD7, 0x0, 0x0}, - { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0} -}; - -/* 25W - PRO, LE */ -static const struct iceland_pt_defaults defaults_icelandpro = { - /* - * sviLoadLIneEn, SviLoadLineVddC, - * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, - * BAPM_TEMP_GRADIENT - */ - 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0, - { 0xB7, 0x0, 0x0, 0xC3, 0x0, 0x0, 0xB5, 0x0, 0x0, 0xEA, 0x0, 0x0, 0xE6, 0x0, 0x0}, - { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0} -}; - -static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - struct cgs_system_info sys_info = {0}; - uint32_t dev_id; - - sys_info.size = sizeof(struct cgs_system_info); - sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; - cgs_query_system_info(hwmgr->device, &sys_info); - dev_id = (uint32_t)sys_info.value; - - switch (dev_id) { - case DEVICE_ID_VI_ICELAND_M_6900: - case DEVICE_ID_VI_ICELAND_M_6903: - smu_data->power_tune_defaults = &defaults_icelandxt; - break; - - case DEVICE_ID_VI_ICELAND_M_6901: - case DEVICE_ID_VI_ICELAND_M_6902: - smu_data->power_tune_defaults = &defaults_icelandpro; - break; - default: - smu_data->power_tune_defaults = &defaults_iceland; - pr_warn("Unknown V.I. Device ID.\n"); - break; - } - return; -} - -static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; - smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; - - tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->tdc_vddc_throttle_release_limit_perc; - smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; - - return 0; -} - -static int iceland_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU71_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else - smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; - - return 0; -} - -static int iceland_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - return 0; -} - -static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 8; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; - - HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(HiSidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(LoSidd); - - return 0; -} - -static int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) -{ - int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; - uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; - - PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, - "The CAC Leakage table does not exist!", return -EINVAL); - PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, - "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); - PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, - "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { - for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { - lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); - hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); - } - } else { - PP_ASSERT_WITH_CODE(false, "Iceland should always support EVV", return -EINVAL); - } - - return 0; -} - -static int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr) -{ - int i; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint8_t *vid = smu_data->power_tune_table.VddCVid; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, - "There should never be more than 8 entries for VddcVid!!!", - return -EINVAL); - - for (i = 0; i < (int)data->vddc_voltage_table.count; i++) { - vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); - } - - return 0; -} - - - -static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed!", - return -EINVAL); - - /* DW0 - DW3 */ - if (iceland_populate_bapm_vddc_vid_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate bapm vddc vid Failed!", - return -EINVAL); - - /* DW4 - DW5 */ - if (iceland_populate_vddc_vid(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate vddc vid Failed!", - return -EINVAL); - - /* DW6 */ - if (iceland_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed!", - return -EINVAL); - /* DW7 */ - if (iceland_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed!", return -EINVAL); - /* DW8 */ - if (iceland_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl, " - "LPMLTemperature Min and Max Failed!", - return -EINVAL); - - /* DW9-DW12 */ - if (0 != iceland_populate_temperature_scaler(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed!", - return -EINVAL); - - /* DW13-DW16 */ - if (iceland_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed!", - return -EINVAL); - - /* DW18 */ - if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!", - return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - sizeof(struct SMU71_Discrete_PmFuses), SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed!", - return -EINVAL); - } - return 0; -} - -static int iceland_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, - uint32_t clock, uint32_t *vol) -{ - uint32_t i = 0; - - /* clock - voltage dependency table is empty table */ - if (allowed_clock_voltage_table->count == 0) - return -EINVAL; - - for (i = 0; i < allowed_clock_voltage_table->count; i++) { - /* find first sclk bigger than request */ - if (allowed_clock_voltage_table->entries[i].clk >= clock) { - *vol = allowed_clock_voltage_table->entries[i].v; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - *vol = allowed_clock_voltage_table->entries[i - 1].v; - - return 0; -} - -static int iceland_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, - pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, - uint16_t *lo) -{ - uint16_t v_index; - bool vol_found = false; - *hi = tab->value * VOLTAGE_SCALE; - *lo = tab->value * VOLTAGE_SCALE; - - /* SCLK/VDDC Dependency Table has to exist. */ - PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, - "The SCLK/VDDC Dependency Table does not exist.\n", - return -EINVAL); - - if (NULL == hwmgr->dyn_state.cac_leakage_table) { - pr_warn("CAC Leakage Table does not exist, using vddc.\n"); - return 0; - } - - /* - * Since voltage in the sclk/vddc dependency table is not - * necessarily in ascending order because of ELB voltage - * patching, loop through entire list to find exact voltage. - */ - for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { - if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { - vol_found = true; - if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { - *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); - } else { - pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); - *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); - } - break; - } - } - - /* - * If voltage is not found in the first pass, loop again to - * find the best match, equal or higher value. - */ - if (!vol_found) { - for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { - if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { - vol_found = true; - if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { - *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; - } else { - pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); - *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; - *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); - } - break; - } - } - - if (!vol_found) - pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); - } - - return 0; -} - -static int iceland_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, - pp_atomctrl_voltage_table_entry *tab, - SMU71_Discrete_VoltageLevel *smc_voltage_tab) -{ - int result; - - result = iceland_get_std_voltage_value_sidd(hwmgr, tab, - &smc_voltage_tab->StdVoltageHiSidd, - &smc_voltage_tab->StdVoltageLoSidd); - if (0 != result) { - smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; - smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; - } - - smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); - CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); - - return 0; -} - -static int iceland_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - unsigned int count; - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->VddcLevelCount = data->vddc_voltage_table.count; - for (count = 0; count < table->VddcLevelCount; count++) { - result = iceland_populate_smc_voltage_table(hwmgr, - &(data->vddc_voltage_table.entries[count]), - &(table->VddcLevel[count])); - PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); - - /* GPIO voltage control */ - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) - table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low; - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) - table->VddcLevel[count].Smio = 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); - - return 0; -} - -static int iceland_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - int result; - - table->VddciLevelCount = data->vddci_voltage_table.count; - - for (count = 0; count < table->VddciLevelCount; count++) { - result = iceland_populate_smc_voltage_table(hwmgr, - &(data->vddci_voltage_table.entries[count]), - &(table->VddciLevel[count])); - PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low; - else - table->VddciLevel[count].Smio |= 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); - - return 0; -} - -static int iceland_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - int result; - - table->MvddLevelCount = data->mvdd_voltage_table.count; - - for (count = 0; count < table->VddciLevelCount; count++) { - result = iceland_populate_smc_voltage_table(hwmgr, - &(data->mvdd_voltage_table.entries[count]), - &table->MvddLevel[count]); - PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) - table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low; - else - table->MvddLevel[count].Smio |= 0; - } - - CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); - - return 0; -} - - -static int iceland_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - int result; - - result = iceland_populate_smc_vddc_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate VDDC voltage table to SMC", return -EINVAL); - - result = iceland_populate_smc_vdd_ci_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate VDDCI voltage table to SMC", return -EINVAL); - - result = iceland_populate_smc_mvdd_table(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "can not populate MVDD voltage table to SMC", return -EINVAL); - - return 0; -} - -static int iceland_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU71_Discrete_Ulv *state) -{ - uint32_t voltage_response_time, ulv_voltage; - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); - PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); - - if (ulv_voltage == 0) { - data->ulv_supported = false; - return 0; - } - - if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { - /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ - if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) - state->VddcOffset = 0; - else - /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ - state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); - } else { - /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ - if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) - state->VddcOffsetVid = 0; - else /* used in SVI2 Mode */ - state->VddcOffsetVid = (uint8_t)( - (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) - * VOLTAGE_VID_OFFSET_SCALE2 - / VOLTAGE_VID_OFFSET_SCALE1); - } - state->VddcPhase = 1; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int iceland_populate_ulv_state(struct pp_hwmgr *hwmgr, - SMU71_Discrete_Ulv *ulv_level) -{ - return iceland_populate_ulv_level(hwmgr, ulv_level); -} - -static int iceland_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU71_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint32_t i; - - /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = - (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = - 1; - table->LinkLevel[i].SPC = - (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = - PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = - PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - -/** - * Calculates the SCLK dividers using the provided engine clock - * - * @param hwmgr the address of the hardware manager - * @param engine_clock the engine clock to use to populate the structure - * @param sclk the SMC SCLK structure to be populated - */ -static int iceland_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t engine_clock, SMU71_Discrete_GraphicsLevel *sclk) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - pp_atomctrl_clock_dividers_vi dividers; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t reference_clock; - uint32_t reference_divider; - uint32_t fbdiv; - int result; - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", return result); - - /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ - reference_clock = atomctrl_get_reference_clock(hwmgr); - - reference_divider = 1 + dividers.uc_pll_ref_div; - - /* low 14 bits is fraction and high 12 bits is divider*/ - fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; - - /* SPLL_FUNC_CNTL setup*/ - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); - - /* SPLL_FUNC_CNTL_3 setup*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, - CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); - - /* set to use fractional accumulation*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, - CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { - pp_atomctrl_internal_ss_info ss_info; - - uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; - if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { - /* - * ss_info.speed_spectrum_percentage -- in unit of 0.01% - * ss_info.speed_spectrum_rate -- in unit of khz - */ - /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ - uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); - - /* clkv = 2 * D * fbdiv / NS */ - uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); - - cg_spll_spread_spectrum = - PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); - cg_spll_spread_spectrum = - PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); - cg_spll_spread_spectrum_2 = - PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); - } - } - - sclk->SclkFrequency = engine_clock; - sclk->CgSpllFuncCntl3 = spll_func_cntl_3; - sclk->CgSpllFuncCntl4 = spll_func_cntl_4; - sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; - sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; - sclk->SclkDid = (uint8_t)dividers.pll_post_divider; - - return 0; -} - -static int iceland_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, - const struct phm_phase_shedding_limits_table *pl, - uint32_t sclk, uint32_t *p_shed) -{ - unsigned int i; - - /* use the minimum phase shedding */ - *p_shed = 1; - - for (i = 0; i < pl->count; i++) { - if (sclk < pl->entries[i].Sclk) { - *p_shed = i; - break; - } - } - return 0; -} - -/** - * Populates single SMC SCLK structure using the provided engine clock - * - * @param hwmgr the address of the hardware manager - * @param engine_clock the engine clock to use to populate the structure - * @param sclk the SMC SCLK structure to be populated - */ -static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint16_t sclk_activity_level_threshold, - SMU71_Discrete_GraphicsLevel *graphic_level) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - result = iceland_calculate_sclk_params(hwmgr, engine_clock, graphic_level); - - /* populate graphics levels*/ - result = iceland_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddc_dependency_on_sclk, engine_clock, - &graphic_level->MinVddc); - PP_ASSERT_WITH_CODE((0 == result), - "can not find VDDC voltage value for VDDC \ - engine clock dependency table", return result); - - /* SCLK frequency in units of 10KHz*/ - graphic_level->SclkFrequency = engine_clock; - graphic_level->MinVddcPhases = 1; - - if (data->vddc_phase_shed_control) - iceland_populate_phase_value_based_on_sclk(hwmgr, - hwmgr->dyn_state.vddc_phase_shed_limits_table, - engine_clock, - &graphic_level->MinVddcPhases); - - /* Indicates maximum activity level for this performance level. 50% for now*/ - graphic_level->ActivityLevel = sclk_activity_level_threshold; - - graphic_level->CcPwrDynRm = 0; - graphic_level->CcPwrDynRm1 = 0; - /* this level can be used if activity is high enough.*/ - graphic_level->EnabledForActivity = 0; - /* this level can be used for throttling.*/ - graphic_level->EnabledForThrottle = 1; - graphic_level->UpHyst = 0; - graphic_level->DownHyst = 100; - graphic_level->VoltageDownHyst = 0; - graphic_level->PowerThrottle = 0; - - data->display_timing.min_clock_in_sr = - hwmgr->display_config.min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) - graphic_level->DeepSleepDivId = - smu7_get_sleep_divider_id_from_clock(engine_clock, - data->display_timing.min_clock_in_sr); - - /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ - graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - if (0 == result) { - graphic_level->MinVddc = PP_HOST_TO_SMC_UL(graphic_level->MinVddc * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); - } - - return result; -} - -/** - * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states - * - * @param hwmgr the address of the hardware manager - */ -int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + - offsetof(SMU71_Discrete_DpmTable, GraphicsLevel); - - uint32_t level_array_size = sizeof(SMU71_Discrete_GraphicsLevel) * - SMU71_MAX_LEVELS_GRAPHICS; - - SMU71_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; - - uint32_t i; - uint8_t highest_pcie_level_enabled = 0; - uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; - uint8_t count = 0; - int result = 0; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - result = iceland_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - (uint16_t)smu_data->activity_target[i], - &(smu_data->smc_state_table.GraphicsLevel[i])); - if (result != 0) - return result; - - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; - } - - /* Only enable level 0 for now. */ - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; - - /* set highest level watermark to high */ - if (dpm_table->sclk_table.count > 1) - smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (highest_pcie_level_enabled + 1))) != 0) { - highest_pcie_level_enabled++; - } - - while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << lowest_pcie_level_enabled)) == 0) { - lowest_pcie_level_enabled++; - } - - while ((count < highest_pcie_level_enabled) && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) { - count++; - } - - mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? - (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; - - - /* set pcieDpmLevel to highest_pcie_level_enabled*/ - for (i = 2; i < dpm_table->sclk_table.count; i++) { - smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; - } - - /* set pcieDpmLevel to lowest_pcie_level_enabled*/ - smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled*/ - smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; - - /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr, level_array_adress, - (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -/** - * Populates the SMC MCLK structure using the provided memory clock - * - * @param hwmgr the address of the hardware manager - * @param memory_clock the memory clock to use to populate the structure - * @param sclk the SMC SCLK structure to be populated - */ -static int iceland_calculate_mclk_params( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU71_Discrete_MemoryLevel *mclk, - bool strobe_mode, - bool dllStateOn - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; - uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; - uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; - uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; - uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; - uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; - uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; - - pp_atomctrl_memory_clock_param mpll_param; - int result; - - result = atomctrl_get_memory_pll_dividers_si(hwmgr, - memory_clock, &mpll_param, strobe_mode); - PP_ASSERT_WITH_CODE(0 == result, - "Error retrieving Memory Clock Parameters from VBIOS.", return result); - - /* MPLL_FUNC_CNTL setup*/ - mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); - - /* MPLL_FUNC_CNTL_1 setup*/ - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); - - /* MPLL_AD_FUNC_CNTL setup*/ - mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, - MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); - - if (data->is_memory_gddr5) { - /* MPLL_DQ_FUNC_CNTL setup*/ - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { - /* - ************************************ - Fref = Reference Frequency - NF = Feedback divider ratio - NR = Reference divider ratio - Fnom = Nominal VCO output frequency = Fref * NF / NR - Fs = Spreading Rate - D = Percentage down-spread / 2 - Fint = Reference input frequency to PFD = Fref / NR - NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) - CLKS = NS - 1 = ISS_STEP_NUM[11:0] - NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) - CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] - ************************************* - */ - pp_atomctrl_internal_ss_info ss_info; - uint32_t freq_nom; - uint32_t tmp; - uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); - - /* for GDDR5 for all modes and DDR3 */ - if (1 == mpll_param.qdr) - freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); - else - freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); - - /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ - tmp = (freq_nom / reference_clock); - tmp = tmp * tmp; - - if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { - /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ - /* ss.Info.speed_spectrum_rate -- in unit of khz */ - /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ - /* = reference_clock * 5 / speed_spectrum_rate */ - uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; - - /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ - /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ - uint32_t clkv = - (uint32_t)((((131 * ss_info.speed_spectrum_percentage * - ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); - - mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); - mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); - } - } - - /* MCLK_PWRMGT_CNTL setup */ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); - - - /* Save the result data to outpupt memory level structure */ - mclk->MclkFrequency = memory_clock; - mclk->MpllFuncCntl = mpll_func_cntl; - mclk->MpllFuncCntl_1 = mpll_func_cntl_1; - mclk->MpllFuncCntl_2 = mpll_func_cntl_2; - mclk->MpllAdFuncCntl = mpll_ad_func_cntl; - mclk->MpllDqFuncCntl = mpll_dq_func_cntl; - mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; - mclk->DllCntl = dll_cntl; - mclk->MpllSs1 = mpll_ss1; - mclk->MpllSs2 = mpll_ss2; - - return 0; -} - -static uint8_t iceland_get_mclk_frequency_ratio(uint32_t memory_clock, - bool strobe_mode) -{ - uint8_t mc_para_index; - - if (strobe_mode) { - if (memory_clock < 12500) { - mc_para_index = 0x00; - } else if (memory_clock > 47500) { - mc_para_index = 0x0f; - } else { - mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); - } - } else { - if (memory_clock < 65000) { - mc_para_index = 0x00; - } else if (memory_clock > 135000) { - mc_para_index = 0x0f; - } else { - mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); - } - } - - return mc_para_index; -} - -static uint8_t iceland_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) -{ - uint8_t mc_para_index; - - if (memory_clock < 10000) { - mc_para_index = 0; - } else if (memory_clock >= 80000) { - mc_para_index = 0x0f; - } else { - mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); - } - - return mc_para_index; -} - -static int iceland_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, - uint32_t memory_clock, uint32_t *p_shed) -{ - unsigned int i; - - *p_shed = 1; - - for (i = 0; i < pl->count; i++) { - if (memory_clock < pl->entries[i].Mclk) { - *p_shed = i; - break; - } - } - - return 0; -} - -static int iceland_populate_single_memory_level( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU71_Discrete_MemoryLevel *memory_level - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int result = 0; - bool dll_state_on; - struct cgs_display_info info = {0}; - uint32_t mclk_edc_wr_enable_threshold = 40000; - uint32_t mclk_edc_enable_threshold = 40000; - uint32_t mclk_strobe_mode_threshold = 40000; - - if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { - result = iceland_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); - } - - if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) { - memory_level->MinVddci = memory_level->MinVddc; - } else if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { - result = iceland_get_dependency_volt_by_clk(hwmgr, - hwmgr->dyn_state.vddci_dependency_on_mclk, - memory_clock, - &memory_level->MinVddci); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); - } - - memory_level->MinVddcPhases = 1; - - if (data->vddc_phase_shed_control) { - iceland_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, - memory_clock, &memory_level->MinVddcPhases); - } - - memory_level->EnabledForThrottle = 1; - memory_level->EnabledForActivity = 0; - memory_level->UpHyst = 0; - memory_level->DownHyst = 100; - memory_level->VoltageDownHyst = 0; - - /* Indicates maximum activity level for this performance level.*/ - memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target; - memory_level->StutterEnable = 0; - memory_level->StrobeEnable = 0; - memory_level->EdcReadEnable = 0; - memory_level->EdcWriteEnable = 0; - memory_level->RttEnable = 0; - - /* default set to low watermark. Highest level will be set to high later.*/ - memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - cgs_get_active_displays_info(hwmgr->device, &info); - data->display_timing.num_existing_displays = info.display_count; - - /* stutter mode not support on iceland */ - - /* decide strobe mode*/ - memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && - (memory_clock <= mclk_strobe_mode_threshold); - - /* decide EDC mode and memory clock ratio*/ - if (data->is_memory_gddr5) { - memory_level->StrobeRatio = iceland_get_mclk_frequency_ratio(memory_clock, - memory_level->StrobeEnable); - - if ((mclk_edc_enable_threshold != 0) && - (memory_clock > mclk_edc_enable_threshold)) { - memory_level->EdcReadEnable = 1; - } - - if ((mclk_edc_wr_enable_threshold != 0) && - (memory_clock > mclk_edc_wr_enable_threshold)) { - memory_level->EdcWriteEnable = 1; - } - - if (memory_level->StrobeEnable) { - if (iceland_get_mclk_frequency_ratio(memory_clock, 1) >= - ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - else - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; - } else - dll_state_on = data->dll_default_on; - } else { - memory_level->StrobeRatio = - iceland_get_ddr3_mclk_frequency_ratio(memory_clock); - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - } - - result = iceland_calculate_mclk_params(hwmgr, - memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); - - if (0 == result) { - memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); - memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); - memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); - /* MCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); - /* Indicates maximum activity level for this performance level.*/ - CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); - } - - return result; -} - -/** - * Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states - * - * @param hwmgr the address of the hardware manager - */ - -int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result; - - /* populate MCLK dpm table to SMU7 */ - uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, MemoryLevel); - uint32_t level_array_size = sizeof(SMU71_Discrete_MemoryLevel) * SMU71_MAX_LEVELS_MEMORY; - SMU71_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", return -EINVAL); - result = iceland_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.MemoryLevel[i])); - if (0 != result) { - return result; - } - } - - /* Only enable level 0 for now.*/ - smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; - - /* - * in order to prevent MC activity from stutter mode to push DPM up. - * the UVD change complements this by putting the MCLK in a higher state - * by default such that we are not effected by up threshold or and MCLK DPM latency. - */ - smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; - data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - /* set highest level watermark to high*/ - smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - - /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr, - level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -static int iceland_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, - SMU71_Discrete_VoltageLevel *voltage) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { - if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { - /* Always round to higher voltage. */ - voltage->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - - PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, - "MVDD Voltage is outside the supported range.", return -EINVAL); - - } else { - return -EINVAL; - } - - return 0; -} - -static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - int result = 0; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - uint32_t vddc_phase_shed_control = 0; - - SMU71_Discrete_VoltageLevel voltage_level; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - - - /* The ACPI state should not do DPM on DC (or ever).*/ - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - if (data->acpi_vddc) - table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); - else - table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); - - table->ACPILevel.MinVddcPhases = vddc_phase_shed_control ? 0 : 1; - /* assign zero for now*/ - table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, - table->ACPILevel.SclkFrequency, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", return result); - - /* divider ID for required SCLK*/ - table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; - table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - table->ACPILevel.DeepSleepDivId = 0; - - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); - spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, - CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); - - table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; - table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; - table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - - /* For various features to be enabled/disabled while this level is active.*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - /* SCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ - table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; - table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; - else { - if (data->acpi_vddci != 0) - table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); - } - - if (0 == iceland_populate_mvdd_value(hwmgr, 0, &voltage_level)) - table->MemoryACPILevel.MinMvdd = - PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinMvdd = 0; - - /* Force reset on DLL*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); - - /* Disable DLL in ACPIState*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); - - /* Enable DLL bypass signal*/ - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK0_BYPASS, 0); - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK1_BYPASS, 0); - - table->MemoryACPILevel.DllCntl = - PP_HOST_TO_SMC_UL(dll_cntl); - table->MemoryACPILevel.MclkPwrmgtCntl = - PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); - table->MemoryACPILevel.MpllAdFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); - table->MemoryACPILevel.MpllDqFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl_1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); - table->MemoryACPILevel.MpllFuncCntl_2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); - table->MemoryACPILevel.MpllSs1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); - table->MemoryACPILevel.MpllSs2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - /* Indicates maximum activity level for this performance level.*/ - table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); - - table->MemoryACPILevel.StutterEnable = 0; - table->MemoryACPILevel.StrobeEnable = 0; - table->MemoryACPILevel.EdcReadEnable = 0; - table->MemoryACPILevel.EdcWriteEnable = 0; - table->MemoryACPILevel.RttEnable = 0; - - return result; -} - -static int iceland_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - return 0; -} - -static int iceland_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - return 0; -} - -static int iceland_populate_smc_acp_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - return 0; -} - -static int iceland_populate_smc_samu_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - return 0; -} - -static int iceland_populate_memory_timing_parameters( - struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint32_t memory_clock, - struct SMU71_Discrete_MCArbDramTimingTableEntry *arb_regs - ) -{ - uint32_t dramTiming; - uint32_t dramTiming2; - uint32_t burstTime; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - engine_clock, memory_clock); - - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); - arb_regs->McArbBurstTime = (uint8_t)burstTime; - - return 0; -} - -/** - * Setup parameters for the MC ARB. - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - * This function is to be called from the SetPowerState table. - */ -static int iceland_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - int result = 0; - SMU71_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - - memset(&arb_regs, 0x00, sizeof(SMU71_Discrete_MCArbDramTimingTable)); - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { - result = iceland_populate_memory_timing_parameters - (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, - data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - - if (0 != result) { - break; - } - } - } - - if (0 == result) { - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU71_Discrete_MCArbDramTimingTable), - SMC_RAM_END - ); - } - - return result; -} - -static int iceland_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table*/ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); - - if (0 != result) { - smu_data->smc_state_table.GraphicsBootLevel = 0; - pr_err("VBIOS did not find boot engine clock value \ - in dependency table. Using Graphics DPM level 0!"); - result = 0; - } - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); - - if (0 != result) { - smu_data->smc_state_table.MemoryBootLevel = 0; - pr_err("VBIOS did not find boot engine clock value \ - in dependency table. Using Memory DPM level 0!"); - result = 0; - } - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value; - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - table->BootVddci = table->BootVddc; - else - table->BootVddci = data->vbios_boot_state.vddci_bootup_value; - - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; - - return result; -} - -static int iceland_populate_mc_reg_address(struct pp_hwmgr *hwmgr, - SMU71_Discrete_MCRegisters *mc_reg_table) -{ - const struct iceland_smumgr *smu_data = (struct iceland_smumgr *)hwmgr->smu_backend; - - uint32_t i, j; - - for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { - if (smu_data->mc_reg_table.validflag & 1<<j) { - PP_ASSERT_WITH_CODE(i < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE, - "Index of mc_reg_table->address[] array out of boundary", return -EINVAL); - mc_reg_table->address[i].s0 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); - mc_reg_table->address[i].s1 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); - i++; - } - } - - mc_reg_table->last = (uint8_t)i; - - return 0; -} - -/*convert register values from driver to SMC format */ -static void iceland_convert_mc_registers( - const struct iceland_mc_reg_entry *entry, - SMU71_Discrete_MCRegisterSet *data, - uint32_t num_entries, uint32_t valid_flag) -{ - uint32_t i, j; - - for (i = 0, j = 0; j < num_entries; j++) { - if (valid_flag & 1<<j) { - data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); - i++; - } - } -} - -static int iceland_convert_mc_reg_table_entry_to_smc(struct pp_hwmgr *hwmgr, - const uint32_t memory_clock, - SMU71_Discrete_MCRegisterSet *mc_reg_table_data - ) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint32_t i = 0; - - for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { - if (memory_clock <= - smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { - break; - } - } - - if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) - --i; - - iceland_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], - mc_reg_table_data, smu_data->mc_reg_table.last, - smu_data->mc_reg_table.validflag); - - return 0; -} - -static int iceland_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, - SMU71_Discrete_MCRegisters *mc_regs) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int res; - uint32_t i; - - for (i = 0; i < data->dpm_table.mclk_table.count; i++) { - res = iceland_convert_mc_reg_table_entry_to_smc( - hwmgr, - data->dpm_table.mclk_table.dpm_levels[i].value, - &mc_regs->data[i] - ); - - if (0 != res) - result = res; - } - - return result; -} - -static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t address; - int32_t result; - - if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) - return 0; - - - memset(&smu_data->mc_regs, 0, sizeof(SMU71_Discrete_MCRegisters)); - - result = iceland_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); - - if (result != 0) - return result; - - - address = smu_data->smu7_data.mc_reg_table_start + (uint32_t)offsetof(SMU71_Discrete_MCRegisters, data[0]); - - return smu7_copy_bytes_to_smc(hwmgr, address, - (uint8_t *)&smu_data->mc_regs.data[0], - sizeof(SMU71_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, - SMC_RAM_END); -} - -static int iceland_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - - memset(&smu_data->mc_regs, 0x00, sizeof(SMU71_Discrete_MCRegisters)); - result = iceland_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize MCRegTable for the MC register addresses!", return result;); - - result = iceland_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize MCRegTable for driver state!", return result;); - - return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, - (uint8_t *)&smu_data->mc_regs, sizeof(SMU71_Discrete_MCRegisters), SMC_RAM_END); -} - -static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - uint8_t count, level; - - count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); - - for (level = 0; level < count; level++) { - if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk - >= data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); - - for (level = 0; level < count; level++) { - if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk - >= data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - -static int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU71_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); - struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; - struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; - const uint16_t *def1, *def2; - int i, j, k; - - - /* - * TDP number of fraction bits are changed from 8 to 7 for Iceland - * as requested by SMC team - */ - - dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); - dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); - - - dpm_table->DTETjOffset = 0; - - dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; - - /* The following are for new Iceland Multi-input fan/thermal control */ - if (NULL != ppm) { - dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; - dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; - } else { - dpm_table->PPM_PkgPwrLimit = 0; - dpm_table->PPM_TemperatureLimit = 0; - } - - CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); - CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); - - dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); - def1 = defaults->bapmti_r; - def2 = defaults->bapmti_rc; - - for (i = 0; i < SMU71_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU71_DTE_SOURCES; j++) { - for (k = 0; k < SMU71_DTE_SINKS; k++) { - dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); - dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); - def1++; - def2++; - } - } - } - - return 0; -} - -static int iceland_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, - SMU71_Discrete_DpmTable *tab) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) - tab->SVI2Enable |= VDDC_ON_SVI2; - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - tab->SVI2Enable |= VDDCI_ON_SVI2; - else - tab->MergedVddci = 1; - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) - tab->SVI2Enable |= MVDD_ON_SVI2; - - PP_ASSERT_WITH_CODE(tab->SVI2Enable != (VDDC_ON_SVI2 | VDDCI_ON_SVI2 | MVDD_ON_SVI2) && - (tab->SVI2Enable & VDDC_ON_SVI2), "SVI2 domain configuration is incorrect!", return -EINVAL); - - return 0; -} - -/** - * Initializes the SMC table and uploads it - * - * @param hwmgr the address of the powerplay hardware manager. - * @param pInput the pointer to input data (PowerState) - * @return always 0 - */ -int iceland_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - SMU71_Discrete_DpmTable *table = &(smu_data->smc_state_table); - - - iceland_initialize_power_tune_defaults(hwmgr); - memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); - - if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) { - iceland_populate_smc_voltage_tables(hwmgr, table); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - - if (data->ulv_supported) { - result = iceland_populate_ulv_state(hwmgr, &(smu_data->ulv_setting)); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ULV state!", return result;); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, 0x40035); - } - - result = iceland_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Link Level!", return result;); - - result = iceland_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Graphics Level!", return result;); - - result = iceland_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Memory Level!", return result;); - - result = iceland_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACPI Level!", return result;); - - result = iceland_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize VCE Level!", return result;); - - result = iceland_populate_smc_acp_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACP Level!", return result;); - - result = iceland_populate_smc_samu_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize SAMU Level!", return result;); - - /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ - /* need to populate the ARB settings for the initial state. */ - result = iceland_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to Write ARB settings for the initial state.", return result;); - - result = iceland_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize UVD Level!", return result;); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - result = iceland_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot Level!", return result;); - - result = iceland_populate_smc_initial_state(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); - - result = iceland_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); - - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - - table->TemperatureLimitHigh = - (data->thermal_temp_setting.temperature_high * - SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - table->TemperatureLimitLow = - (data->thermal_temp_setting.temperature_low * - SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; - - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; - table->PCIeGenInterval = 1; - - result = iceland_populate_smc_svi2_config(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate SVI2 setting!", return result); - - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); - table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); - table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.dpm_table_start + - offsetof(SMU71_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU71_Discrete_DpmTable)-3 * sizeof(SMU71_PIDController), - SMC_RAM_END); - - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload dpm data to SMC memory!", return result;); - - /* Upload all ulv setting to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.ulv_setting_starts, - (uint8_t *)&(smu_data->ulv_setting), - sizeof(SMU71_Discrete_Ulv), - SMC_RAM_END); - - - result = iceland_populate_initial_mc_reg_table(hwmgr); - PP_ASSERT_WITH_CODE((0 == result), - "Failed to populate initialize MC Reg table!", return result); - - result = iceland_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate PM fuses to SMC memory!", return result); - - return 0; -} - -/** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) - return 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (0 == smu7_data->fan_table_start) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); - - if (0 == duty100) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = smu7_get_xclk(hwmgr); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); - - /* fan_table.FanControl_GL_Flag = 1; */ - - res = smu7_copy_bytes_to_smc(hwmgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); - - return 0; -} - - -static int iceland_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return iceland_program_memory_timing_parameters(hwmgr); - - return 0; -} - -int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (hwmgr->gfx_arbiter.sclk_threshold != - data->low_sclk_interrupt_threshold)) { - data->low_sclk_interrupt_threshold = - hwmgr->gfx_arbiter.sclk_threshold; - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU71_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - - result = iceland_update_and_upload_mc_reg_table(hwmgr); - - PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); - - result = iceland_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - - return result; -} - -uint32_t iceland_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU71_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU71_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU71_SoftRegisters, AverageGraphicsActivity); - case PreVBlankGap: - return offsetof(SMU71_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU71_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU71_SoftRegisters, UcodeLoadStatus); - } - case SMU_Discrete_DpmTable: - switch (member) { - case LowSclkInterruptThreshold: - return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold); - } - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -uint32_t iceland_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU71_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU71_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU71_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU71_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU71_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDCI: - return SMU71_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU71_MAX_LEVELS_MVDD; - } - - pr_warn("can't get the mac of %x\n", value); - return 0; -} - -/** - * Get the location of various tables inside the FW image. - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - */ -int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->dpm_table_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (0 == result) { - data->soft_regs_start = tmp; - smu7_data->soft_regs_start = tmp; - } - - error |= (0 != result); - - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->mc_reg_table_start = tmp; - } - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->fan_table_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->arb_table_start = tmp; - } - - error |= (0 != result); - - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (0 == result) { - hwmgr->microcode_version_info.SMC = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU71_FIRMWARE_HEADER_LOCATION + - offsetof(SMU71_Firmware_Header, UlvSettings), - &tmp, SMC_RAM_END); - - if (0 == result) { - smu7_data->ulv_setting_starts = tmp; - } - - error |= (0 != result); - - return error ? 1 : 0; -} - -/*---------------------------MC----------------------------*/ - -static uint8_t iceland_get_memory_modile_index(struct pp_hwmgr *hwmgr) -{ - return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); -} - -static bool iceland_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) -{ - bool result = true; - - switch (in_reg) { - case mmMC_SEQ_RAS_TIMING: - *out_reg = mmMC_SEQ_RAS_TIMING_LP; - break; - - case mmMC_SEQ_DLL_STBY: - *out_reg = mmMC_SEQ_DLL_STBY_LP; - break; - - case mmMC_SEQ_G5PDX_CMD0: - *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; - break; - - case mmMC_SEQ_G5PDX_CMD1: - *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; - break; - - case mmMC_SEQ_G5PDX_CTRL: - *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; - break; - - case mmMC_SEQ_CAS_TIMING: - *out_reg = mmMC_SEQ_CAS_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING: - *out_reg = mmMC_SEQ_MISC_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING2: - *out_reg = mmMC_SEQ_MISC_TIMING2_LP; - break; - - case mmMC_SEQ_PMG_DVS_CMD: - *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; - break; - - case mmMC_SEQ_PMG_DVS_CTL: - *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; - break; - - case mmMC_SEQ_RD_CTL_D0: - *out_reg = mmMC_SEQ_RD_CTL_D0_LP; - break; - - case mmMC_SEQ_RD_CTL_D1: - *out_reg = mmMC_SEQ_RD_CTL_D1_LP; - break; - - case mmMC_SEQ_WR_CTL_D0: - *out_reg = mmMC_SEQ_WR_CTL_D0_LP; - break; - - case mmMC_SEQ_WR_CTL_D1: - *out_reg = mmMC_SEQ_WR_CTL_D1_LP; - break; - - case mmMC_PMG_CMD_EMRS: - *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; - break; - - case mmMC_PMG_CMD_MRS: - *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; - break; - - case mmMC_PMG_CMD_MRS1: - *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; - break; - - case mmMC_SEQ_PMG_TIMING: - *out_reg = mmMC_SEQ_PMG_TIMING_LP; - break; - - case mmMC_PMG_CMD_MRS2: - *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; - break; - - case mmMC_SEQ_WR_CTL_2: - *out_reg = mmMC_SEQ_WR_CTL_2_LP; - break; - - default: - result = false; - break; - } - - return result; -} - -static int iceland_set_s0_mc_reg_index(struct iceland_mc_reg_table *table) -{ - uint32_t i; - uint16_t address; - - for (i = 0; i < table->last; i++) { - table->mc_reg_address[i].s0 = - iceland_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) - ? address : table->mc_reg_address[i].s1; - } - return 0; -} - -static int iceland_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, - struct iceland_mc_reg_table *ni_table) -{ - uint8_t i, j; - - PP_ASSERT_WITH_CODE((table->last <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), - "Invalid VramInfo table.", return -EINVAL); - - for (i = 0; i < table->last; i++) { - ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; - } - ni_table->last = table->last; - - for (i = 0; i < table->num_entries; i++) { - ni_table->mc_reg_table_entry[i].mclk_max = - table->mc_reg_table_entry[i].mclk_max; - for (j = 0; j < table->last; j++) { - ni_table->mc_reg_table_entry[i].mc_data[j] = - table->mc_reg_table_entry[i].mc_data[j]; - } - } - - ni_table->num_entries = table->num_entries; - - return 0; -} - -/** - * VBIOS omits some information to reduce size, we need to recover them here. - * 1. when we see mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to mmMC_PMG_CMD_EMRS /_LP[15:0]. - * Bit[15:0] MRS, need to be update mmMC_PMG_CMD_MRS/_LP[15:0] - * 2. when we see mmMC_SEQ_RESERVE_M, bit[15:0] EMRS2, need to be write to mmMC_PMG_CMD_MRS1/_LP[15:0]. - * 3. need to set these data for each clock range - * - * @param hwmgr the address of the powerplay hardware manager. - * @param table the address of MCRegTable - * @return always 0 - */ -static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr, - struct iceland_mc_reg_table *table) -{ - uint8_t i, j, k; - uint32_t temp_reg; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - for (i = 0, j = table->last; i < table->last; i++) { - PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - switch (table->mc_reg_address[i].s1) { - - case mmMC_SEQ_MISC1: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - ((temp_reg & 0xffff0000)) | - ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); - } - j++; - PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - - if (!data->is_memory_gddr5) { - table->mc_reg_table_entry[k].mc_data[j] |= 0x100; - } - } - j++; - PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - if (!data->is_memory_gddr5 && j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE) { - table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; - table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; - } - j++; - PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - } - - break; - - case mmMC_SEQ_RESERVE_M: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - } - j++; - PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - break; - - default: - break; - } - - } - - table->last = j; - - return 0; -} - -static int iceland_set_valid_flag(struct iceland_mc_reg_table *table) -{ - uint8_t i, j; - for (i = 0; i < table->last; i++) { - for (j = 1; j < table->num_entries; j++) { - if (table->mc_reg_table_entry[j-1].mc_data[i] != - table->mc_reg_table_entry[j].mc_data[i]) { - table->validflag |= (1<<i); - break; - } - } - } - - return 0; -} - -int iceland_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); - pp_atomctrl_mc_reg_table *table; - struct iceland_mc_reg_table *ni_table = &smu_data->mc_reg_table; - uint8_t module_index = iceland_get_memory_modile_index(hwmgr); - - table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); - - if (NULL == table) - return -ENOMEM; - - /* Program additional LP registers that are no longer programmed by VBIOS */ - cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); - - memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table)); - - result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); - - if (0 == result) - result = iceland_copy_vbios_smc_reg_table(table, ni_table); - - if (0 == result) { - iceland_set_s0_mc_reg_index(ni_table); - result = iceland_set_mc_special_registers(hwmgr, ni_table); - } - - if (0 == result) - iceland_set_valid_flag(ni_table); - - kfree(table); - - return result; -} - -bool iceland_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c index 78aa1122eacc..34128822b8fb 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/iceland_smumgr.c @@ -30,15 +30,84 @@ #include "smumgr.h" #include "iceland_smumgr.h" -#include "smu_ucode_xfer_vi.h" + #include "ppsmc.h" + +#include "cgs_common.h" + +#include "smu7_dyn_defaults.h" +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" +#include "atombios.h" +#include "pppcielanes.h" +#include "pp_endian.h" +#include "processpptables.h" + + #include "smu/smu_7_1_1_d.h" #include "smu/smu_7_1_1_sh_mask.h" -#include "cgs_common.h" -#include "iceland_smc.h" +#include "smu71_discrete.h" + +#include "smu_ucode_xfer_vi.h" +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + #define ICELAND_SMC_SIZE 0x20000 +#define VOLTAGE_SCALE 4 +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 +#define MC_CG_ARB_FREQ_F1 0x0b +#define VDDC_VDDCI_DELTA 200 + +#define DEVICE_ID_VI_ICELAND_M_6900 0x6900 +#define DEVICE_ID_VI_ICELAND_M_6901 0x6901 +#define DEVICE_ID_VI_ICELAND_M_6902 0x6902 +#define DEVICE_ID_VI_ICELAND_M_6903 0x6903 + +static const struct iceland_pt_defaults defaults_iceland = { + /* + * sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, + * TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT + */ + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, + { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61 }, + { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } +}; + +/* 35W - XT, XTL */ +static const struct iceland_pt_defaults defaults_icelandxt = { + /* + * sviLoadLIneEn, SviLoadLineVddC, + * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, + * BAPM_TEMP_GRADIENT + */ + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0, + { 0xA7, 0x0, 0x0, 0xB5, 0x0, 0x0, 0x9F, 0x0, 0x0, 0xD6, 0x0, 0x0, 0xD7, 0x0, 0x0}, + { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0} +}; + +/* 25W - PRO, LE */ +static const struct iceland_pt_defaults defaults_icelandpro = { + /* + * sviLoadLIneEn, SviLoadLineVddC, + * TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, + * BAPM_TEMP_GRADIENT + */ + 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0x0, + { 0xB7, 0x0, 0x0, 0xC3, 0x0, 0x0, 0xB5, 0x0, 0x0, 0xEA, 0x0, 0x0, 0xE6, 0x0, 0x0}, + { 0x1EA, 0x0, 0x0, 0x224, 0x0, 0x0, 0x25E, 0x0, 0x0, 0x28E, 0x0, 0x0, 0x2AB, 0x0, 0x0} +}; + static int iceland_start_smc(struct pp_hwmgr *hwmgr) { PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, @@ -108,7 +177,7 @@ static int iceland_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); - PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be dividable by 4.", return -EINVAL); + PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL); return 0; } @@ -191,13 +260,6 @@ static int iceland_start_smu(struct pp_hwmgr *hwmgr) return result; } -/** - * Write a 32bit value to the SMC SRAM space. - * ALL PARAMETERS ARE IN HOST BYTE ORDER. - * @param smumgr the address of the powerplay hardware manager. - * @param smcAddress the address in the SMC RAM to access. - * @param value to write to the SMC SRAM. - */ static int iceland_smu_init(struct pp_hwmgr *hwmgr) { int i; @@ -219,6 +281,2413 @@ static int iceland_smu_init(struct pp_hwmgr *hwmgr) return 0; } + +static void iceland_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + struct cgs_system_info sys_info = {0}; + uint32_t dev_id; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; + cgs_query_system_info(hwmgr->device, &sys_info); + dev_id = (uint32_t)sys_info.value; + + switch (dev_id) { + case DEVICE_ID_VI_ICELAND_M_6900: + case DEVICE_ID_VI_ICELAND_M_6903: + smu_data->power_tune_defaults = &defaults_icelandxt; + break; + + case DEVICE_ID_VI_ICELAND_M_6901: + case DEVICE_ID_VI_ICELAND_M_6902: + smu_data->power_tune_defaults = &defaults_icelandpro; + break; + default: + smu_data->power_tune_defaults = &defaults_iceland; + pr_warn("Unknown V.I. Device ID.\n"); + break; + } + return; +} + +static int iceland_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; + smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddc; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int iceland_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; + + tdc_limit = (uint16_t)(hwmgr->dyn_state.cac_dtp_table->usTDC * 256); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->tdc_vddc_throttle_release_limit_perc; + smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; + + return 0; +} + +static int iceland_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU71_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else + smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; + + return 0; +} + +static int iceland_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +static int iceland_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 8; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int iceland_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint16_t HiSidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t LoSidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = hwmgr->dyn_state.cac_dtp_table; + + HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(HiSidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(LoSidd); + + return 0; +} + +static int iceland_populate_bapm_vddc_vid_sidd(struct pp_hwmgr *hwmgr) +{ + int i; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint8_t *hi_vid = smu_data->power_tune_table.BapmVddCVidHiSidd; + uint8_t *lo_vid = smu_data->power_tune_table.BapmVddCVidLoSidd; + + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.cac_leakage_table, + "The CAC Leakage table does not exist!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count <= 8, + "There should never be more than 8 entries for BapmVddcVid!!!", return -EINVAL); + PP_ASSERT_WITH_CODE(hwmgr->dyn_state.cac_leakage_table->count == hwmgr->dyn_state.vddc_dependency_on_sclk->count, + "CACLeakageTable->count and VddcDependencyOnSCLk->count not equal", return -EINVAL); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_EVV)) { + for (i = 0; (uint32_t) i < hwmgr->dyn_state.cac_leakage_table->count; i++) { + lo_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc1); + hi_vid[i] = convert_to_vid(hwmgr->dyn_state.cac_leakage_table->entries[i].Vddc2); + } + } else { + PP_ASSERT_WITH_CODE(false, "Iceland should always support EVV", return -EINVAL); + } + + return 0; +} + +static int iceland_populate_vddc_vid(struct pp_hwmgr *hwmgr) +{ + int i; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint8_t *vid = smu_data->power_tune_table.VddCVid; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + PP_ASSERT_WITH_CODE(data->vddc_voltage_table.count <= 8, + "There should never be more than 8 entries for VddcVid!!!", + return -EINVAL); + + for (i = 0; i < (int)data->vddc_voltage_table.count; i++) { + vid[i] = convert_to_vid(data->vddc_voltage_table.entries[i].value); + } + + return 0; +} + + + +static int iceland_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed!", + return -EINVAL); + + /* DW0 - DW3 */ + if (iceland_populate_bapm_vddc_vid_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate bapm vddc vid Failed!", + return -EINVAL); + + /* DW4 - DW5 */ + if (iceland_populate_vddc_vid(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate vddc vid Failed!", + return -EINVAL); + + /* DW6 */ + if (iceland_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed!", + return -EINVAL); + /* DW7 */ + if (iceland_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed!", return -EINVAL); + /* DW8 */ + if (iceland_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl, " + "LPMLTemperature Min and Max Failed!", + return -EINVAL); + + /* DW9-DW12 */ + if (0 != iceland_populate_temperature_scaler(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed!", + return -EINVAL); + + /* DW13-DW16 */ + if (iceland_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed!", + return -EINVAL); + + /* DW18 */ + if (iceland_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate BapmVddCBaseLeakage Hi and Lo Sidd Failed!", + return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU71_Discrete_PmFuses), SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed!", + return -EINVAL); + } + return 0; +} + +static int iceland_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table *allowed_clock_voltage_table, + uint32_t clock, uint32_t *vol) +{ + uint32_t i = 0; + + /* clock - voltage dependency table is empty table */ + if (allowed_clock_voltage_table->count == 0) + return -EINVAL; + + for (i = 0; i < allowed_clock_voltage_table->count; i++) { + /* find first sclk bigger than request */ + if (allowed_clock_voltage_table->entries[i].clk >= clock) { + *vol = allowed_clock_voltage_table->entries[i].v; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + *vol = allowed_clock_voltage_table->entries[i - 1].v; + + return 0; +} + +static int iceland_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, uint16_t *hi, + uint16_t *lo) +{ + uint16_t v_index; + bool vol_found = false; + *hi = tab->value * VOLTAGE_SCALE; + *lo = tab->value * VOLTAGE_SCALE; + + /* SCLK/VDDC Dependency Table has to exist. */ + PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk, + "The SCLK/VDDC Dependency Table does not exist.\n", + return -EINVAL); + + if (NULL == hwmgr->dyn_state.cac_leakage_table) { + pr_warn("CAC Leakage Table does not exist, using vddc.\n"); + return 0; + } + + /* + * Since voltage in the sclk/vddc dependency table is not + * necessarily in ascending order because of ELB voltage + * patching, loop through entire list to find exact voltage. + */ + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE); + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n"); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + /* + * If voltage is not found in the first pass, loop again to + * find the best match, equal or higher value. + */ + if (!vol_found) { + for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) { + if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) { + vol_found = true; + if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) { + *lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE; + } else { + pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table."); + *lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE; + *hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE); + } + break; + } + } + + if (!vol_found) + pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n"); + } + + return 0; +} + +static int iceland_populate_smc_voltage_table(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table_entry *tab, + SMU71_Discrete_VoltageLevel *smc_voltage_tab) +{ + int result; + + result = iceland_get_std_voltage_value_sidd(hwmgr, tab, + &smc_voltage_tab->StdVoltageHiSidd, + &smc_voltage_tab->StdVoltageLoSidd); + if (0 != result) { + smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE; + smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE; + } + + smc_voltage_tab->Voltage = PP_HOST_TO_SMC_US(tab->value * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); + CONVERT_FROM_HOST_TO_SMC_US(smc_voltage_tab->StdVoltageHiSidd); + + return 0; +} + +static int iceland_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + unsigned int count; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->VddcLevelCount = data->vddc_voltage_table.count; + for (count = 0; count < table->VddcLevelCount; count++) { + result = iceland_populate_smc_voltage_table(hwmgr, + &(data->vddc_voltage_table.entries[count]), + &(table->VddcLevel[count])); + PP_ASSERT_WITH_CODE(0 == result, "do not populate SMC VDDC voltage table", return -EINVAL); + + /* GPIO voltage control */ + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->voltage_control) + table->VddcLevel[count].Smio |= data->vddc_voltage_table.entries[count].smio_low; + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) + table->VddcLevel[count].Smio = 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); + + return 0; +} + +static int iceland_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->VddciLevelCount = data->vddci_voltage_table.count; + + for (count = 0; count < table->VddciLevelCount; count++) { + result = iceland_populate_smc_voltage_table(hwmgr, + &(data->vddci_voltage_table.entries[count]), + &(table->VddciLevel[count])); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC VDDCI voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + table->VddciLevel[count].Smio |= data->vddci_voltage_table.entries[count].smio_low; + else + table->VddciLevel[count].Smio |= 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); + + return 0; +} + +static int iceland_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + int result; + + table->MvddLevelCount = data->mvdd_voltage_table.count; + + for (count = 0; count < table->VddciLevelCount; count++) { + result = iceland_populate_smc_voltage_table(hwmgr, + &(data->mvdd_voltage_table.entries[count]), + &table->MvddLevel[count]); + PP_ASSERT_WITH_CODE(result == 0, "do not populate SMC mvdd voltage table", return -EINVAL); + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) + table->MvddLevel[count].Smio |= data->mvdd_voltage_table.entries[count].smio_low; + else + table->MvddLevel[count].Smio |= 0; + } + + CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); + + return 0; +} + + +static int iceland_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + int result; + + result = iceland_populate_smc_vddc_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDC voltage table to SMC", return -EINVAL); + + result = iceland_populate_smc_vdd_ci_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDCI voltage table to SMC", return -EINVAL); + + result = iceland_populate_smc_mvdd_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate MVDD voltage table to SMC", return -EINVAL); + + return 0; +} + +static int iceland_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU71_Discrete_Ulv *state) +{ + uint32_t voltage_response_time, ulv_voltage; + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + result = pp_tables_get_response_times(hwmgr, &voltage_response_time, &ulv_voltage); + PP_ASSERT_WITH_CODE((0 == result), "can not get ULV voltage value", return result;); + + if (ulv_voltage == 0) { + data->ulv_supported = false; + return 0; + } + + if (data->voltage_control != SMU7_VOLTAGE_CONTROL_BY_SVID2) { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffset = 0; + else + /* used in SMIO Mode. not implemented for now. this is backup only for CI. */ + state->VddcOffset = (uint16_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage); + } else { + /* use minimum voltage if ulv voltage in pptable is bigger than minimum voltage */ + if (ulv_voltage > hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v) + state->VddcOffsetVid = 0; + else /* used in SVI2 Mode */ + state->VddcOffsetVid = (uint8_t)( + (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[0].v - ulv_voltage) + * VOLTAGE_VID_OFFSET_SCALE2 + / VOLTAGE_VID_OFFSET_SCALE1); + } + state->VddcPhase = 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int iceland_populate_ulv_state(struct pp_hwmgr *hwmgr, + SMU71_Discrete_Ulv *ulv_level) +{ + return iceland_populate_ulv_level(hwmgr, ulv_level); +} + +static int iceland_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU71_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint32_t i; + + /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = + (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = + 1; + table->LinkLevel[i].SPC = + (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = + PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = + PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int iceland_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, SMU71_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t reference_clock; + uint32_t reference_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ + reference_clock = atomctrl_get_reference_clock(hwmgr); + + reference_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider*/ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup*/ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + pp_atomctrl_internal_ss_info ss_info; + + uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; + if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { + /* + * ss_info.speed_spectrum_percentage -- in unit of 0.01% + * ss_info.speed_spectrum_rate -- in unit of khz + */ + /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ + uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); + + /* clkv = 2 * D * fbdiv / NS */ + uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); + + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = + PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); + } + } + + sclk->SclkFrequency = engine_clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static int iceland_populate_phase_value_based_on_sclk(struct pp_hwmgr *hwmgr, + const struct phm_phase_shedding_limits_table *pl, + uint32_t sclk, uint32_t *p_shed) +{ + unsigned int i; + + /* use the minimum phase shedding */ + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (sclk < pl->entries[i].Sclk) { + *p_shed = i; + break; + } + } + return 0; +} + +static int iceland_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint16_t sclk_activity_level_threshold, + SMU71_Discrete_GraphicsLevel *graphic_level) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + result = iceland_calculate_sclk_params(hwmgr, engine_clock, graphic_level); + + /* populate graphics levels*/ + result = iceland_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_sclk, engine_clock, + &graphic_level->MinVddc); + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for VDDC \ + engine clock dependency table", return result); + + /* SCLK frequency in units of 10KHz*/ + graphic_level->SclkFrequency = engine_clock; + graphic_level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) + iceland_populate_phase_value_based_on_sclk(hwmgr, + hwmgr->dyn_state.vddc_phase_shed_limits_table, + engine_clock, + &graphic_level->MinVddcPhases); + + /* Indicates maximum activity level for this performance level. 50% for now*/ + graphic_level->ActivityLevel = sclk_activity_level_threshold; + + graphic_level->CcPwrDynRm = 0; + graphic_level->CcPwrDynRm1 = 0; + /* this level can be used if activity is high enough.*/ + graphic_level->EnabledForActivity = 0; + /* this level can be used for throttling.*/ + graphic_level->EnabledForThrottle = 1; + graphic_level->UpHyst = 0; + graphic_level->DownHyst = 100; + graphic_level->VoltageDownHyst = 0; + graphic_level->PowerThrottle = 0; + + data->display_timing.min_clock_in_sr = + hwmgr->display_config.min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) + graphic_level->DeepSleepDivId = + smu7_get_sleep_divider_id_from_clock(engine_clock, + data->display_timing.min_clock_in_sr); + + /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ + graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + if (0 == result) { + graphic_level->MinVddc = PP_HOST_TO_SMC_UL(graphic_level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); + } + + return result; +} + +static int iceland_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + + offsetof(SMU71_Discrete_DpmTable, GraphicsLevel); + + uint32_t level_array_size = sizeof(SMU71_Discrete_GraphicsLevel) * + SMU71_MAX_LEVELS_GRAPHICS; + + SMU71_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; + + uint32_t i; + uint8_t highest_pcie_level_enabled = 0; + uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; + uint8_t count = 0; + int result = 0; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = iceland_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + (uint16_t)smu_data->activity_target[i], + &(smu_data->smc_state_table.GraphicsLevel[i])); + if (result != 0) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; + } + + /* Only enable level 0 for now. */ + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + + /* set highest level watermark to high */ + if (dpm_table->sclk_table.count > 1) + smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (highest_pcie_level_enabled + 1))) != 0) { + highest_pcie_level_enabled++; + } + + while ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << lowest_pcie_level_enabled)) == 0) { + lowest_pcie_level_enabled++; + } + + while ((count < highest_pcie_level_enabled) && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) { + count++; + } + + mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? + (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; + + + /* set pcieDpmLevel to highest_pcie_level_enabled*/ + for (i = 2; i < dpm_table->sclk_table.count; i++) { + smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; + } + + /* set pcieDpmLevel to lowest_pcie_level_enabled*/ + smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled*/ + smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; + + /* level count will send to smc once at init smc table and never change*/ + result = smu7_copy_bytes_to_smc(hwmgr, level_array_adress, + (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int iceland_calculate_mclk_params( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU71_Discrete_MemoryLevel *mclk, + bool strobe_mode, + bool dllStateOn + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; + uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; + uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; + uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; + uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; + uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; + uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; + + pp_atomctrl_memory_clock_param mpll_param; + int result; + + result = atomctrl_get_memory_pll_dividers_si(hwmgr, + memory_clock, &mpll_param, strobe_mode); + PP_ASSERT_WITH_CODE(0 == result, + "Error retrieving Memory Clock Parameters from VBIOS.", return result); + + /* MPLL_FUNC_CNTL setup*/ + mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); + + /* MPLL_FUNC_CNTL_1 setup*/ + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); + + /* MPLL_AD_FUNC_CNTL setup*/ + mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, + MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + + if (data->is_memory_gddr5) { + /* MPLL_DQ_FUNC_CNTL setup*/ + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { + /* + ************************************ + Fref = Reference Frequency + NF = Feedback divider ratio + NR = Reference divider ratio + Fnom = Nominal VCO output frequency = Fref * NF / NR + Fs = Spreading Rate + D = Percentage down-spread / 2 + Fint = Reference input frequency to PFD = Fref / NR + NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) + CLKS = NS - 1 = ISS_STEP_NUM[11:0] + NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) + CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] + ************************************* + */ + pp_atomctrl_internal_ss_info ss_info; + uint32_t freq_nom; + uint32_t tmp; + uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); + + /* for GDDR5 for all modes and DDR3 */ + if (1 == mpll_param.qdr) + freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); + else + freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); + + /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ + tmp = (freq_nom / reference_clock); + tmp = tmp * tmp; + + if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { + /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ + /* ss.Info.speed_spectrum_rate -- in unit of khz */ + /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ + /* = reference_clock * 5 / speed_spectrum_rate */ + uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; + + /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ + /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ + uint32_t clkv = + (uint32_t)((((131 * ss_info.speed_spectrum_percentage * + ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); + + mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); + mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); + } + } + + /* MCLK_PWRMGT_CNTL setup */ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); + + + /* Save the result data to outpupt memory level structure */ + mclk->MclkFrequency = memory_clock; + mclk->MpllFuncCntl = mpll_func_cntl; + mclk->MpllFuncCntl_1 = mpll_func_cntl_1; + mclk->MpllFuncCntl_2 = mpll_func_cntl_2; + mclk->MpllAdFuncCntl = mpll_ad_func_cntl; + mclk->MpllDqFuncCntl = mpll_dq_func_cntl; + mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; + mclk->DllCntl = dll_cntl; + mclk->MpllSs1 = mpll_ss1; + mclk->MpllSs2 = mpll_ss2; + + return 0; +} + +static uint8_t iceland_get_mclk_frequency_ratio(uint32_t memory_clock, + bool strobe_mode) +{ + uint8_t mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) { + mc_para_index = 0x00; + } else if (memory_clock > 47500) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); + } + } else { + if (memory_clock < 65000) { + mc_para_index = 0x00; + } else if (memory_clock > 135000) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); + } + } + + return mc_para_index; +} + +static uint8_t iceland_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) +{ + uint8_t mc_para_index; + + if (memory_clock < 10000) { + mc_para_index = 0; + } else if (memory_clock >= 80000) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); + } + + return mc_para_index; +} + +static int iceland_populate_phase_value_based_on_mclk(struct pp_hwmgr *hwmgr, const struct phm_phase_shedding_limits_table *pl, + uint32_t memory_clock, uint32_t *p_shed) +{ + unsigned int i; + + *p_shed = 1; + + for (i = 0; i < pl->count; i++) { + if (memory_clock < pl->entries[i].Mclk) { + *p_shed = i; + break; + } + } + + return 0; +} + +static int iceland_populate_single_memory_level( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU71_Discrete_MemoryLevel *memory_level + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int result = 0; + bool dll_state_on; + struct cgs_display_info info = {0}; + uint32_t mclk_edc_wr_enable_threshold = 40000; + uint32_t mclk_edc_enable_threshold = 40000; + uint32_t mclk_strobe_mode_threshold = 40000; + + if (hwmgr->dyn_state.vddc_dependency_on_mclk != NULL) { + result = iceland_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddc_dependency_on_mclk, memory_clock, &memory_level->MinVddc); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); + } + + if (data->vddci_control == SMU7_VOLTAGE_CONTROL_NONE) { + memory_level->MinVddci = memory_level->MinVddc; + } else if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { + result = iceland_get_dependency_volt_by_clk(hwmgr, + hwmgr->dyn_state.vddci_dependency_on_mclk, + memory_clock, + &memory_level->MinVddci); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddci voltage value from memory VDDCI voltage dependency table", return result); + } + + memory_level->MinVddcPhases = 1; + + if (data->vddc_phase_shed_control) { + iceland_populate_phase_value_based_on_mclk(hwmgr, hwmgr->dyn_state.vddc_phase_shed_limits_table, + memory_clock, &memory_level->MinVddcPhases); + } + + memory_level->EnabledForThrottle = 1; + memory_level->EnabledForActivity = 0; + memory_level->UpHyst = 0; + memory_level->DownHyst = 100; + memory_level->VoltageDownHyst = 0; + + /* Indicates maximum activity level for this performance level.*/ + memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target; + memory_level->StutterEnable = 0; + memory_level->StrobeEnable = 0; + memory_level->EdcReadEnable = 0; + memory_level->EdcWriteEnable = 0; + memory_level->RttEnable = 0; + + /* default set to low watermark. Highest level will be set to high later.*/ + memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + cgs_get_active_displays_info(hwmgr->device, &info); + data->display_timing.num_existing_displays = info.display_count; + + /* stutter mode not support on iceland */ + + /* decide strobe mode*/ + memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && + (memory_clock <= mclk_strobe_mode_threshold); + + /* decide EDC mode and memory clock ratio*/ + if (data->is_memory_gddr5) { + memory_level->StrobeRatio = iceland_get_mclk_frequency_ratio(memory_clock, + memory_level->StrobeEnable); + + if ((mclk_edc_enable_threshold != 0) && + (memory_clock > mclk_edc_enable_threshold)) { + memory_level->EdcReadEnable = 1; + } + + if ((mclk_edc_wr_enable_threshold != 0) && + (memory_clock > mclk_edc_wr_enable_threshold)) { + memory_level->EdcWriteEnable = 1; + } + + if (memory_level->StrobeEnable) { + if (iceland_get_mclk_frequency_ratio(memory_clock, 1) >= + ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + else + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; + } else + dll_state_on = data->dll_default_on; + } else { + memory_level->StrobeRatio = + iceland_get_ddr3_mclk_frequency_ratio(memory_clock); + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } + + result = iceland_calculate_mclk_params(hwmgr, + memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); + + if (0 == result) { + memory_level->MinVddc = PP_HOST_TO_SMC_UL(memory_level->MinVddc * VOLTAGE_SCALE); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinVddcPhases); + memory_level->MinVddci = PP_HOST_TO_SMC_UL(memory_level->MinVddci * VOLTAGE_SCALE); + memory_level->MinMvdd = PP_HOST_TO_SMC_UL(memory_level->MinMvdd * VOLTAGE_SCALE); + /* MCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); + /* Indicates maximum activity level for this performance level.*/ + CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); + } + + return result; +} + +static int iceland_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + + /* populate MCLK dpm table to SMU7 */ + uint32_t level_array_adress = smu_data->smu7_data.dpm_table_start + offsetof(SMU71_Discrete_DpmTable, MemoryLevel); + uint32_t level_array_size = sizeof(SMU71_Discrete_MemoryLevel) * SMU71_MAX_LEVELS_MEMORY; + SMU71_Discrete_MemoryLevel *levels = smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", return -EINVAL); + result = iceland_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.MemoryLevel[i])); + if (0 != result) { + return result; + } + } + + /* Only enable level 0 for now.*/ + smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + + /* + * in order to prevent MC activity from stutter mode to push DPM up. + * the UVD change complements this by putting the MCLK in a higher state + * by default such that we are not effected by up threshold or and MCLK DPM latency. + */ + smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + /* set highest level watermark to high*/ + smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change*/ + result = smu7_copy_bytes_to_smc(hwmgr, + level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int iceland_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, + SMU71_Discrete_VoltageLevel *voltage) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count; i++) { + if (mclk <= hwmgr->dyn_state.mvdd_dependency_on_mclk->entries[i].clk) { + /* Always round to higher voltage. */ + voltage->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + + PP_ASSERT_WITH_CODE(i < hwmgr->dyn_state.mvdd_dependency_on_mclk->count, + "MVDD Voltage is outside the supported range.", return -EINVAL); + + } else { + return -EINVAL; + } + + return 0; +} + +static int iceland_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + int result = 0; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + uint32_t vddc_phase_shed_control = 0; + + SMU71_Discrete_VoltageLevel voltage_level; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + + + /* The ACPI state should not do DPM on DC (or ever).*/ + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (data->acpi_vddc) + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->acpi_vddc * VOLTAGE_SCALE); + else + table->ACPILevel.MinVddc = PP_HOST_TO_SMC_UL(data->min_vddc_in_pptable * VOLTAGE_SCALE); + + table->ACPILevel.MinVddcPhases = vddc_phase_shed_control ? 0 : 1; + /* assign zero for now*/ + table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* divider ID for required SCLK*/ + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, + CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + + /* For various features to be enabled/disabled while this level is active.*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + /* SCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ + table->MemoryACPILevel.MinVddc = table->ACPILevel.MinVddc; + table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + table->MemoryACPILevel.MinVddci = table->MemoryACPILevel.MinVddc; + else { + if (data->acpi_vddci != 0) + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->acpi_vddci * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinVddci = PP_HOST_TO_SMC_UL(data->min_vddci_in_pptable * VOLTAGE_SCALE); + } + + if (0 == iceland_populate_mvdd_value(hwmgr, 0, &voltage_level)) + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinMvdd = 0; + + /* Force reset on DLL*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); + + /* Disable DLL in ACPIState*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); + + /* Enable DLL bypass signal*/ + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK0_BYPASS, 0); + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK1_BYPASS, 0); + + table->MemoryACPILevel.DllCntl = + PP_HOST_TO_SMC_UL(dll_cntl); + table->MemoryACPILevel.MclkPwrmgtCntl = + PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); + table->MemoryACPILevel.MpllAdFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); + table->MemoryACPILevel.MpllDqFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl_1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); + table->MemoryACPILevel.MpllFuncCntl_2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); + table->MemoryACPILevel.MpllSs1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); + table->MemoryACPILevel.MpllSs2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + /* Indicates maximum activity level for this performance level.*/ + table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); + + table->MemoryACPILevel.StutterEnable = 0; + table->MemoryACPILevel.StrobeEnable = 0; + table->MemoryACPILevel.EdcReadEnable = 0; + table->MemoryACPILevel.EdcWriteEnable = 0; + table->MemoryACPILevel.RttEnable = 0; + + return result; +} + +static int iceland_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + return 0; +} + +static int iceland_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + return 0; +} + +static int iceland_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + return 0; +} + +static int iceland_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + return 0; +} + +static int iceland_populate_memory_timing_parameters( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock, + struct SMU71_Discrete_MCArbDramTimingTableEntry *arb_regs + ) +{ + uint32_t dramTiming; + uint32_t dramTiming2; + uint32_t burstTime; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + engine_clock, memory_clock); + + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + + return 0; +} + +static int iceland_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + int result = 0; + SMU71_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + + memset(&arb_regs, 0x00, sizeof(SMU71_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = iceland_populate_memory_timing_parameters + (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + + if (0 != result) { + break; + } + } + } + + if (0 == result) { + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU71_Discrete_MCArbDramTimingTable), + SMC_RAM_END + ); + } + + return result; +} + +static int iceland_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table*/ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.GraphicsBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value \ + in dependency table. Using Graphics DPM level 0!"); + result = 0; + } + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); + + if (0 != result) { + smu_data->smc_state_table.MemoryBootLevel = 0; + pr_err("VBIOS did not find boot engine clock value \ + in dependency table. Using Memory DPM level 0!"); + result = 0; + } + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value; + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + table->BootVddci = table->BootVddc; + else + table->BootVddci = data->vbios_boot_state.vddci_bootup_value; + + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; + + return result; +} + +static int iceland_populate_mc_reg_address(struct pp_hwmgr *hwmgr, + SMU71_Discrete_MCRegisters *mc_reg_table) +{ + const struct iceland_smumgr *smu_data = (struct iceland_smumgr *)hwmgr->smu_backend; + + uint32_t i, j; + + for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { + if (smu_data->mc_reg_table.validflag & 1<<j) { + PP_ASSERT_WITH_CODE(i < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE, + "Index of mc_reg_table->address[] array out of boundary", return -EINVAL); + mc_reg_table->address[i].s0 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + + mc_reg_table->last = (uint8_t)i; + + return 0; +} + +/*convert register values from driver to SMC format */ +static void iceland_convert_mc_registers( + const struct iceland_mc_reg_entry *entry, + SMU71_Discrete_MCRegisterSet *data, + uint32_t num_entries, uint32_t valid_flag) +{ + uint32_t i, j; + + for (i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & 1<<j) { + data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); + i++; + } + } +} + +static int iceland_convert_mc_reg_table_entry_to_smc(struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + SMU71_Discrete_MCRegisterSet *mc_reg_table_data + ) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint32_t i = 0; + + for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { + if (memory_clock <= + smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { + break; + } + } + + if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) + --i; + + iceland_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, smu_data->mc_reg_table.last, + smu_data->mc_reg_table.validflag); + + return 0; +} + +static int iceland_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, + SMU71_Discrete_MCRegisters *mc_regs) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int res; + uint32_t i; + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + res = iceland_convert_mc_reg_table_entry_to_smc( + hwmgr, + data->dpm_table.mclk_table.dpm_levels[i].value, + &mc_regs->data[i] + ); + + if (0 != res) + result = res; + } + + return result; +} + +static int iceland_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t address; + int32_t result; + + if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) + return 0; + + + memset(&smu_data->mc_regs, 0, sizeof(SMU71_Discrete_MCRegisters)); + + result = iceland_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); + + if (result != 0) + return result; + + + address = smu_data->smu7_data.mc_reg_table_start + (uint32_t)offsetof(SMU71_Discrete_MCRegisters, data[0]); + + return smu7_copy_bytes_to_smc(hwmgr, address, + (uint8_t *)&smu_data->mc_regs.data[0], + sizeof(SMU71_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, + SMC_RAM_END); +} + +static int iceland_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + + memset(&smu_data->mc_regs, 0x00, sizeof(SMU71_Discrete_MCRegisters)); + result = iceland_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for the MC register addresses!", return result;); + + result = iceland_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for driver state!", return result;); + + return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, + (uint8_t *)&smu_data->mc_regs, sizeof(SMU71_Discrete_MCRegisters), SMC_RAM_END); +} + +static int iceland_populate_smc_initial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + uint8_t count, level; + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_sclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_sclk->entries[level].clk + >= data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(hwmgr->dyn_state.vddc_dependency_on_mclk->count); + + for (level = 0; level < count; level++) { + if (hwmgr->dyn_state.vddc_dependency_on_mclk->entries[level].clk + >= data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int iceland_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + const struct iceland_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU71_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + struct phm_cac_tdp_table *cac_dtp_table = hwmgr->dyn_state.cac_dtp_table; + struct phm_ppm_table *ppm = hwmgr->dyn_state.ppm_parameter_table; + const uint16_t *def1, *def2; + int i, j, k; + + + /* + * TDP number of fraction bits are changed from 8 to 7 for Iceland + * as requested by SMC team + */ + + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 256)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); + + + dpm_table->DTETjOffset = 0; + + dpm_table->GpuTjMax = (uint8_t)(data->thermal_temp_setting.temperature_high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; + + /* The following are for new Iceland Multi-input fan/thermal control */ + if (NULL != ppm) { + dpm_table->PPM_PkgPwrLimit = (uint16_t)ppm->dgpu_tdp * 256 / 1000; + dpm_table->PPM_TemperatureLimit = (uint16_t)ppm->tj_max * 256; + } else { + dpm_table->PPM_PkgPwrLimit = 0; + dpm_table->PPM_TemperatureLimit = 0; + } + + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_PkgPwrLimit); + CONVERT_FROM_HOST_TO_SMC_US(dpm_table->PPM_TemperatureLimit); + + dpm_table->BAPM_TEMP_GRADIENT = PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); + def1 = defaults->bapmti_r; + def2 = defaults->bapmti_rc; + + for (i = 0; i < SMU71_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU71_DTE_SOURCES; j++) { + for (k = 0; k < SMU71_DTE_SINKS; k++) { + dpm_table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*def1); + dpm_table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*def2); + def1++; + def2++; + } + } + } + + return 0; +} + +static int iceland_populate_smc_svi2_config(struct pp_hwmgr *hwmgr, + SMU71_Discrete_DpmTable *tab) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) + tab->SVI2Enable |= VDDC_ON_SVI2; + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + tab->SVI2Enable |= VDDCI_ON_SVI2; + else + tab->MergedVddci = 1; + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) + tab->SVI2Enable |= MVDD_ON_SVI2; + + PP_ASSERT_WITH_CODE(tab->SVI2Enable != (VDDC_ON_SVI2 | VDDCI_ON_SVI2 | MVDD_ON_SVI2) && + (tab->SVI2Enable & VDDC_ON_SVI2), "SVI2 domain configuration is incorrect!", return -EINVAL); + + return 0; +} + +static int iceland_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + SMU71_Discrete_DpmTable *table = &(smu_data->smc_state_table); + + + iceland_initialize_power_tune_defaults(hwmgr); + memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) { + iceland_populate_smc_voltage_tables(hwmgr, table); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + + if (data->ulv_supported) { + result = iceland_populate_ulv_state(hwmgr, &(smu_data->ulv_setting)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result;); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = iceland_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result;); + + result = iceland_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result;); + + result = iceland_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result;); + + result = iceland_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result;); + + result = iceland_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result;); + + result = iceland_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result;); + + result = iceland_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize SAMU Level!", return result;); + + /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ + /* need to populate the ARB settings for the initial state. */ + result = iceland_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result;); + + result = iceland_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result;); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + result = iceland_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result;); + + result = iceland_populate_smc_initial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to initialize Boot State!", return result); + + result = iceland_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to populate BAPM Parameters!", return result); + + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + + table->TemperatureLimitHigh = + (data->thermal_temp_setting.temperature_high * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + table->TemperatureLimitLow = + (data->thermal_temp_setting.temperature_low * + SMU7_Q88_FORMAT_CONVERSION_UNIT) / PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + table->PCIeBootLinkLevel = 0; + table->PCIeGenInterval = 1; + + result = iceland_populate_smc_svi2_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate SVI2 setting!", return result); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddcPhase); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskVddciVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMaskMvddVid); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + table->BootVddc = PP_HOST_TO_SMC_US(table->BootVddc * VOLTAGE_SCALE); + table->BootVddci = PP_HOST_TO_SMC_US(table->BootVddci * VOLTAGE_SCALE); + table->BootMVdd = PP_HOST_TO_SMC_US(table->BootMVdd * VOLTAGE_SCALE); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.dpm_table_start + + offsetof(SMU71_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU71_Discrete_DpmTable)-3 * sizeof(SMU71_PIDController), + SMC_RAM_END); + + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result;); + + /* Upload all ulv setting to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.ulv_setting_starts, + (uint8_t *)&(smu_data->ulv_setting), + sizeof(SMU71_Discrete_Ulv), + SMC_RAM_END); + + + result = iceland_populate_initial_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate initialize MC Reg table!", return result); + + result = iceland_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + return 0; +} + +int iceland_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + SMU71_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) + return 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (0 == smu7_data->fan_table_start) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = smu7_get_xclk(hwmgr); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); + + /* fan_table.FanControl_GL_Flag = 1; */ + + res = smu7_copy_bytes_to_smc(hwmgr, smu7_data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), SMC_RAM_END); + + return 0; +} + + +static int iceland_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return iceland_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int iceland_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (hwmgr->gfx_arbiter.sclk_threshold != + data->low_sclk_interrupt_threshold)) { + data->low_sclk_interrupt_threshold = + hwmgr->gfx_arbiter.sclk_threshold; + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU71_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + + result = iceland_update_and_upload_mc_reg_table(hwmgr); + + PP_ASSERT_WITH_CODE((0 == result), "Failed to upload MC reg table!", return result); + + result = iceland_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + + return result; +} + +static uint32_t iceland_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU71_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU71_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU71_SoftRegisters, AverageGraphicsActivity); + case PreVBlankGap: + return offsetof(SMU71_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU71_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU71_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU71_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + case SMU_Discrete_DpmTable: + switch (member) { + case LowSclkInterruptThreshold: + return offsetof(SMU71_Discrete_DpmTable, LowSclkInterruptThreshold); + } + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t iceland_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU71_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU71_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU71_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU71_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU71_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDCI: + return SMU71_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU71_MAX_LEVELS_MVDD; + } + + pr_warn("can't get the mac of %x\n", value); + return 0; +} + +static int iceland_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_smumgr *smu7_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->dpm_table_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (0 == result) { + data->soft_regs_start = tmp; + smu7_data->soft_regs_start = tmp; + } + + error |= (0 != result); + + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->mc_reg_table_start = tmp; + } + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->fan_table_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->arb_table_start = tmp; + } + + error |= (0 != result); + + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (0 == result) { + hwmgr->microcode_version_info.SMC = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU71_FIRMWARE_HEADER_LOCATION + + offsetof(SMU71_Firmware_Header, UlvSettings), + &tmp, SMC_RAM_END); + + if (0 == result) { + smu7_data->ulv_setting_starts = tmp; + } + + error |= (0 != result); + + return error ? 1 : 0; +} + +/*---------------------------MC----------------------------*/ + +static uint8_t iceland_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +static bool iceland_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) +{ + bool result = true; + + switch (in_reg) { + case mmMC_SEQ_RAS_TIMING: + *out_reg = mmMC_SEQ_RAS_TIMING_LP; + break; + + case mmMC_SEQ_DLL_STBY: + *out_reg = mmMC_SEQ_DLL_STBY_LP; + break; + + case mmMC_SEQ_G5PDX_CMD0: + *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; + break; + + case mmMC_SEQ_G5PDX_CMD1: + *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; + break; + + case mmMC_SEQ_G5PDX_CTRL: + *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; + break; + + case mmMC_SEQ_CAS_TIMING: + *out_reg = mmMC_SEQ_CAS_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING: + *out_reg = mmMC_SEQ_MISC_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING2: + *out_reg = mmMC_SEQ_MISC_TIMING2_LP; + break; + + case mmMC_SEQ_PMG_DVS_CMD: + *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; + break; + + case mmMC_SEQ_PMG_DVS_CTL: + *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; + break; + + case mmMC_SEQ_RD_CTL_D0: + *out_reg = mmMC_SEQ_RD_CTL_D0_LP; + break; + + case mmMC_SEQ_RD_CTL_D1: + *out_reg = mmMC_SEQ_RD_CTL_D1_LP; + break; + + case mmMC_SEQ_WR_CTL_D0: + *out_reg = mmMC_SEQ_WR_CTL_D0_LP; + break; + + case mmMC_SEQ_WR_CTL_D1: + *out_reg = mmMC_SEQ_WR_CTL_D1_LP; + break; + + case mmMC_PMG_CMD_EMRS: + *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; + break; + + case mmMC_PMG_CMD_MRS: + *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; + break; + + case mmMC_PMG_CMD_MRS1: + *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; + break; + + case mmMC_SEQ_PMG_TIMING: + *out_reg = mmMC_SEQ_PMG_TIMING_LP; + break; + + case mmMC_PMG_CMD_MRS2: + *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; + break; + + case mmMC_SEQ_WR_CTL_2: + *out_reg = mmMC_SEQ_WR_CTL_2_LP; + break; + + default: + result = false; + break; + } + + return result; +} + +static int iceland_set_s0_mc_reg_index(struct iceland_mc_reg_table *table) +{ + uint32_t i; + uint16_t address; + + for (i = 0; i < table->last; i++) { + table->mc_reg_address[i].s0 = + iceland_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) + ? address : table->mc_reg_address[i].s1; + } + return 0; +} + +static int iceland_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, + struct iceland_mc_reg_table *ni_table) +{ + uint8_t i, j; + + PP_ASSERT_WITH_CODE((table->last <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), + "Invalid VramInfo table.", return -EINVAL); + + for (i = 0; i < table->last; i++) { + ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + } + ni_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + ni_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + ni_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + + ni_table->num_entries = table->num_entries; + + return 0; +} + +static int iceland_set_mc_special_registers(struct pp_hwmgr *hwmgr, + struct iceland_mc_reg_table *table) +{ + uint8_t i, j, k; + uint32_t temp_reg; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + for (i = 0, j = table->last; i < table->last; i++) { + PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + switch (table->mc_reg_address[i].s1) { + + case mmMC_SEQ_MISC1: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + } + j++; + PP_ASSERT_WITH_CODE((j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + + if (!data->is_memory_gddr5) { + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + if (!data->is_memory_gddr5 && j < SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE) { + table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + } + + break; + + case mmMC_SEQ_RESERVE_M: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU71_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + break; + + default: + break; + } + + } + + table->last = j; + + return 0; +} + +static int iceland_set_valid_flag(struct iceland_mc_reg_table *table) +{ + uint8_t i, j; + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != + table->mc_reg_table_entry[j].mc_data[i]) { + table->validflag |= (1<<i); + break; + } + } + } + + return 0; +} + +static int iceland_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct iceland_smumgr *smu_data = (struct iceland_smumgr *)(hwmgr->smu_backend); + pp_atomctrl_mc_reg_table *table; + struct iceland_mc_reg_table *ni_table = &smu_data->mc_reg_table; + uint8_t module_index = iceland_get_memory_modile_index(hwmgr); + + table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + /* Program additional LP registers that are no longer programmed by VBIOS */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); + + memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table)); + + result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); + + if (0 == result) + result = iceland_copy_vbios_smc_reg_table(table, ni_table); + + if (0 == result) { + iceland_set_s0_mc_reg_index(ni_table); + result = iceland_set_mc_special_registers(hwmgr, ni_table); + } + + if (0 == result) + iceland_set_valid_flag(ni_table); + + kfree(table); + + return result; +} + +static bool iceland_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + const struct pp_smumgr_func iceland_smu_funcs = { .smu_init = &iceland_smu_init, .smu_fini = &smu7_smu_fini, diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c deleted file mode 100644 index c92ea38d2e15..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c +++ /dev/null @@ -1,2344 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ - -#include "pp_debug.h" -#include "polaris10_smc.h" -#include "smu7_dyn_defaults.h" - -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "atombios.h" -#include "polaris10_smumgr.h" -#include "pppcielanes.h" - -#include "smu_ucode_xfer_vi.h" -#include "smu74_discrete.h" -#include "smu/smu_7_1_3_d.h" -#include "smu/smu_7_1_3_sh_mask.h" -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" -#include "oss/oss_3_0_d.h" -#include "gca/gfx_8_0_d.h" -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" -#include "polaris10_pwrvirus.h" -#include "smu7_ppsmc.h" -#include "smu7_smumgr.h" - -#define POLARIS10_SMC_SIZE 0x20000 -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define VDDC_VDDCI_DELTA 200 -#define MC_CG_ARB_FREQ_F1 0x0b - -static const struct polaris10_pt_defaults polaris10_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { - /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */ - { 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, - { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, - { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } }, -}; - -static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] = { - {VCO_2_4, POSTDIV_DIV_BY_16, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160}, - {VCO_2_4, POSTDIV_DIV_BY_8, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_8, 112, 224, 160}, - {VCO_2_4, POSTDIV_DIV_BY_4, 75, 160, 112}, - {VCO_3_6, POSTDIV_DIV_BY_4, 112, 216, 160}, - {VCO_2_4, POSTDIV_DIV_BY_2, 75, 160, 108}, - {VCO_3_6, POSTDIV_DIV_BY_2, 112, 216, 160} }; - -static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, - uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) -{ - uint32_t i; - uint16_t vddci; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - *voltage = *mvdd = 0; - - /* clock - voltage dependency table is empty table */ - if (dep_table->count == 0) - return -EINVAL; - - for (i = 0; i < dep_table->count; i++) { - /* find first sclk bigger than request */ - if (dep_table->entries[i].clk >= clock) { - *voltage |= (dep_table->entries[i].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i].vddci) - *voltage |= (dep_table->entries[i].vddci * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - (uint16_t)VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i].mvdd * - VOLTAGE_SCALE; - - *voltage |= 1 << PHASES_SHIFT; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) - *voltage |= (data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE) << VDDCI_SHIFT; - else if (dep_table->entries[i-1].vddci) { - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i].vddc - - (uint16_t)VDDC_VDDCI_DELTA)); - *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - } - - if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) - *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; - else if (dep_table->entries[i].mvdd) - *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; - - return 0; -} - -static uint16_t scale_fan_gain_settings(uint16_t raw_setting) -{ - uint32_t tmp; - tmp = raw_setting * 4096 / 100; - return (uint16_t)tmp; -} - -static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; - struct pp_advance_fan_control_parameters *fan_table = - &hwmgr->thermal_controller.advanceFanControlParameters; - int i, j, k; - const uint16_t *pdef1; - const uint16_t *pdef2; - - table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); - table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); - - PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, - "Target Operating Temp is out of Range!", - ); - - table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( - cac_dtp_table->usTargetOperatingTemp * 256); - table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( - cac_dtp_table->usTemperatureLimitHotspot * 256); - table->FanGainEdge = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainEdge)); - table->FanGainHotspot = PP_HOST_TO_SMC_US( - scale_fan_gain_settings(fan_table->usFanGainHotspot)); - - pdef1 = defaults->BAPMTI_R; - pdef2 = defaults->BAPMTI_RC; - - for (i = 0; i < SMU74_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU74_DTE_SOURCES; j++) { - for (k = 0; k < SMU74_DTE_SINKS; k++) { - table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1); - table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2); - pdef1++; - pdef2++; - } - } - } - - return 0; -} - -static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; - smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; - - tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->TDC_VDDC_ThrottleReleaseLimitPerc; - smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; - - return 0; -} - -static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU74_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", - return -EINVAL); - else { - smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; - smu_data->power_tune_table.LPMLTemperatureMin = - (uint8_t)((temp >> 16) & 0xff); - smu_data->power_tune_table.LPMLTemperatureMax = - (uint8_t)((temp >> 8) & 0xff); - smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); - } - return 0; -} - -static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - int i; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; - - return 0; -} - -static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - -/* TO DO move to hwmgr */ - if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) - || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = - hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US( - hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity); - return 0; -} - -static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; - - hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); - - return 0; -} - -static int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed!", - return -EINVAL); - - if (polaris10_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed!", - return -EINVAL); - - if (polaris10_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed!", return -EINVAL); - - if (polaris10_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl, " - "LPMLTemperature Min and Max Failed!", - return -EINVAL); - - if (0 != polaris10_populate_temperature_scaler(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed!", - return -EINVAL); - - if (polaris10_populate_fuzzy_fan(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate Fuzzy Fan Control parameters Failed!", - return -EINVAL); - - if (polaris10_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed!", - return -EINVAL); - - if (polaris10_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate BapmVddCBaseLeakage Hi and Lo " - "Sidd Failed!", return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - (sizeof(struct SMU74_Discrete_PmFuses) - 92), SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed!", - return -EINVAL); - } - return 0; -} - -/** - * Mvdd table preparation for SMC. - * - * @param *hwmgr The address of the hardware manager. - * @param *table The SMC DPM table structure to be populated. - * @return 0 - */ -static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count, level; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - count = data->mvdd_voltage_table.count; - if (count > SMU_MAX_SMIO_LEVELS) - count = SMU_MAX_SMIO_LEVELS; - for (level = 0; level < count; level++) { - table->SmioTable2.Pattern[level].Voltage = - PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); - /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ - table->SmioTable2.Pattern[level].Smio = - (uint8_t) level; - table->Smio[level] |= - data->mvdd_voltage_table.entries[level].smio_low; - } - table->SmioMask2 = data->mvdd_voltage_table.mask_low; - - table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count); - } - - return 0; -} - -static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - uint32_t count, level; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - count = data->vddci_voltage_table.count; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - if (count > SMU_MAX_SMIO_LEVELS) - count = SMU_MAX_SMIO_LEVELS; - for (level = 0; level < count; ++level) { - table->SmioTable1.Pattern[level].Voltage = - PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE); - table->SmioTable1.Pattern[level].Smio = (uint8_t) level; - - table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low; - } - } - - table->SmioMask1 = data->vddci_voltage_table.mask_low; - - return 0; -} - -/** -* Preparation of vddc and vddgfx CAC tables for SMC. -* -* @param hwmgr the address of the hardware manager -* @param table the SMC DPM table structure to be populated -* @return always 0 -*/ -static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - uint32_t count; - uint8_t index; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_voltage_lookup_table *lookup_table = - table_info->vddc_lookup_table; - /* tables is already swapped, so in order to use the value from it, - * we need to swap it back. - * We are populating vddc CAC data to BapmVddc table - * in split and merged mode - */ - for (count = 0; count < lookup_table->count; count++) { - index = phm_get_voltage_index(lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddcVidLoSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_low); - table->BapmVddcVidHiSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_mid); - table->BapmVddcVidHiSidd2[count] = convert_to_vid(lookup_table->entries[index].us_cac_high); - } - - return 0; -} - -/** -* Preparation of voltage tables for SMC. -* -* @param hwmgr the address of the hardware manager -* @param table the SMC DPM table structure to be populated -* @return always 0 -*/ - -static int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - polaris10_populate_smc_vddci_table(hwmgr, table); - polaris10_populate_smc_mvdd_table(hwmgr, table); - polaris10_populate_cac_table(hwmgr, table); - - return 0; -} - -static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_Ulv *state) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; - state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * - VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - - if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) - state->VddcPhase = data->vddc_phase_shed_control ^ 0x3; - else - state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int polaris10_populate_ulv_state(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - return polaris10_populate_ulv_level(hwmgr, &table->Ulv); -} - -static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int i; - - /* Index (dpm_table->pcie_speed_table.count) - * is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( - dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = 1; - table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - -/* To Do move to hwmgr */ - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - - -static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t i, ref_clk; - - struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } }; - - ref_clk = smu7_get_xclk(hwmgr); - - if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) { - for (i = 0; i < NUM_SCLK_RANGE; i++) { - table->SclkFcwRangeTable[i].vco_setting = range_table_from_vbios.entry[i].ucVco_setting; - table->SclkFcwRangeTable[i].postdiv = range_table_from_vbios.entry[i].ucPostdiv; - table->SclkFcwRangeTable[i].fcw_pcc = range_table_from_vbios.entry[i].usFcw_pcc; - - table->SclkFcwRangeTable[i].fcw_trans_upper = range_table_from_vbios.entry[i].usFcw_trans_upper; - table->SclkFcwRangeTable[i].fcw_trans_lower = range_table_from_vbios.entry[i].usRcw_trans_lower; - - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); - } - return; - } - - for (i = 0; i < NUM_SCLK_RANGE; i++) { - smu_data->range_table[i].trans_lower_frequency = (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv; - smu_data->range_table[i].trans_upper_frequency = (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv; - - table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting; - table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv; - table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc; - - table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper; - table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower; - - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); - CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); - } -} - -/** -* Calculates the SCLK dividers using the provided engine clock -* -* @param hwmgr the address of the hardware manager -* @param clock the engine clock to use to populate the structure -* @param sclk the SMC SCLK structure to be populated -*/ -static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t clock, SMU_SclkSetting *sclk_setting) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - const SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct pp_atomctrl_clock_dividers_ai dividers; - uint32_t ref_clock; - uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq; - uint8_t i; - int result; - uint64_t temp; - - sclk_setting->SclkFrequency = clock; - /* get the engine clock dividers for this clock value */ - result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock, ÷rs); - if (result == 0) { - sclk_setting->Fcw_int = dividers.usSclk_fcw_int; - sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac; - sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int; - sclk_setting->PllRange = dividers.ucSclkPllRange; - sclk_setting->Sclk_slew_rate = 0x400; - sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac; - sclk_setting->Pcc_down_slew_rate = 0xffff; - sclk_setting->SSc_En = dividers.ucSscEnable; - sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int; - sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac; - sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac; - return result; - } - - ref_clock = smu7_get_xclk(hwmgr); - - for (i = 0; i < NUM_SCLK_RANGE; i++) { - if (clock > smu_data->range_table[i].trans_lower_frequency - && clock <= smu_data->range_table[i].trans_upper_frequency) { - sclk_setting->PllRange = i; - break; - } - } - - sclk_setting->Fcw_int = (uint16_t)((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); - temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; - temp <<= 0x10; - do_div(temp, ref_clock); - sclk_setting->Fcw_frac = temp & 0xffff; - - pcc_target_percent = 10; /* Hardcode 10% for now. */ - pcc_target_freq = clock - (clock * pcc_target_percent / 100); - sclk_setting->Pcc_fcw_int = (uint16_t)((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); - - ss_target_percent = 2; /* Hardcode 2% for now. */ - sclk_setting->SSc_En = 0; - if (ss_target_percent) { - sclk_setting->SSc_En = 1; - ss_target_freq = clock - (clock * ss_target_percent / 100); - sclk_setting->Fcw1_int = (uint16_t)((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); - temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; - temp <<= 0x10; - do_div(temp, ref_clock); - sclk_setting->Fcw1_frac = temp & 0xffff; - } - - return 0; -} - -/** -* Populates single SMC SCLK structure using the provided engine clock -* -* @param hwmgr the address of the hardware manager -* @param clock the engine clock to use to populate the structure -* @param sclk the SMC SCLK structure to be populated -*/ - -static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t clock, uint16_t sclk_al_threshold, - struct SMU74_Discrete_GraphicsLevel *level) -{ - int result; - /* PP_Clocks minClocks; */ - uint32_t mvdd; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - SMU_SclkSetting curr_sclk_setting = { 0 }; - - result = polaris10_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting); - - /* populate graphics levels */ - result = polaris10_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_sclk, clock, - &level->MinVoltage, &mvdd); - - PP_ASSERT_WITH_CODE((0 == result), - "can not find VDDC voltage value for " - "VDDC engine clock dependency table", - return result); - level->ActivityLevel = sclk_al_threshold; - - level->CcPwrDynRm = 0; - level->CcPwrDynRm1 = 0; - level->EnabledForActivity = 0; - level->EnabledForThrottle = 1; - level->UpHyst = 10; - level->DownHyst = 0; - level->VoltageDownHyst = 0; - level->PowerThrottle = 0; - data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) - level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, - hwmgr->display_config.min_core_set_clock_in_sr); - - /* Default to slow, highest DPM level will be - * set to PPSMC_DISPLAY_WATERMARK_LOW later. - */ - if (data->update_up_hyst) - level->UpHyst = (uint8_t)data->up_hyst; - if (data->update_down_hyst) - level->DownHyst = (uint8_t)data->down_hyst; - - level->SclkSetting = curr_sclk_setting; - - CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac); - CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate); - return 0; -} - -/** -* Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states -* -* @param hwmgr the address of the hardware manager -*/ -int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; - uint8_t pcie_entry_cnt = (uint8_t) hw_data->dpm_table.pcie_speed_table.count; - int result = 0; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) * - SMU74_MAX_LEVELS_GRAPHICS; - struct SMU74_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t i, max_entry; - uint8_t hightest_pcie_level_enabled = 0, - lowest_pcie_level_enabled = 0, - mid_pcie_level_enabled = 0, - count = 0; - - polaris10_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table)); - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - - result = polaris10_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - (uint16_t)smu_data->activity_target[i], - &(smu_data->smc_state_table.GraphicsLevel[i])); - if (result) - return result; - - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - levels[i].DeepSleepDivId = 0; - } - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SPLLShutdownSupport)) - smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0; - - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - - if (pcie_table != NULL) { - PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - max_entry = pcie_entry_cnt - 1; - for (i = 0; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = - (uint8_t) ((i < max_entry) ? i : max_entry); - } else { - while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (hightest_pcie_level_enabled + 1))) != 0)) - hightest_pcie_level_enabled++; - - while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << lowest_pcie_level_enabled)) == 0)) - lowest_pcie_level_enabled++; - - while ((count < hightest_pcie_level_enabled) && - ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) - count++; - - mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < - hightest_pcie_level_enabled ? - (lowest_pcie_level_enabled + 1 + count) : - hightest_pcie_level_enabled; - - /* set pcieDpmLevel to hightest_pcie_level_enabled */ - for (i = 2; i < dpm_table->sclk_table.count; i++) - levels[i].pcieDpmLevel = hightest_pcie_level_enabled; - - /* set pcieDpmLevel to lowest_pcie_level_enabled */ - levels[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled */ - levels[1].pcieDpmLevel = mid_pcie_level_enabled; - } - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - - -static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, - uint32_t clock, struct SMU74_Discrete_MemoryLevel *mem_level) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - int result = 0; - struct cgs_display_info info = {0, 0, NULL}; - uint32_t mclk_stutter_mode_threshold = 40000; - - cgs_get_active_displays_info(hwmgr->device, &info); - - if (table_info->vdd_dep_on_mclk) { - result = polaris10_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_mclk, clock, - &mem_level->MinVoltage, &mem_level->MinMvdd); - PP_ASSERT_WITH_CODE((0 == result), - "can not find MinVddc voltage value from memory " - "VDDC voltage dependency table", return result); - } - - mem_level->MclkFrequency = clock; - mem_level->EnabledForThrottle = 1; - mem_level->EnabledForActivity = 0; - mem_level->UpHyst = 0; - mem_level->DownHyst = 100; - mem_level->VoltageDownHyst = 0; - mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target; - mem_level->StutterEnable = false; - mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - data->display_timing.num_existing_displays = info.display_count; - - if (mclk_stutter_mode_threshold && - (clock <= mclk_stutter_mode_threshold) && - (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, - STUTTER_ENABLE) & 0x1)) - mem_level->StutterEnable = true; - - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); - } - return result; -} - -/** -* Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states -* -* @param hwmgr the address of the hardware manager -*/ -int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; - int result; - /* populate MCLK dpm table to SMU7 */ - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, MemoryLevel); - uint32_t array_size = sizeof(SMU74_Discrete_MemoryLevel) * - SMU74_MAX_LEVELS_MEMORY; - struct SMU74_Discrete_MemoryLevel *levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", - return -EINVAL); - result = polaris10_populate_single_memory_level(hwmgr, - dpm_table->mclk_table.dpm_levels[i].value, - &levels[i]); - if (i == dpm_table->mclk_table.count - 1) { - levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - levels[i].EnabledForActivity = 1; - } - if (result) - return result; - } - - /* In order to prevent MC activity from stutter mode to push DPM up, - * the UVD change complements this by putting the MCLK in - * a higher state by default such that we are not affected by - * up threshold or and MCLK DPM latency. - */ - levels[0].ActivityLevel = 0x1f; - CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = - (uint8_t)dpm_table->mclk_table.count; - hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - - /* level count will send to smc once at init smc table and never change */ - result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - (uint32_t)array_size, SMC_RAM_END); - - return result; -} - -/** -* Populates the SMC MVDD structure using the provided memory clock. -* -* @param hwmgr the address of the hardware manager -* @param mclk the MCLK value to be used in the decision if MVDD should be high or low. -* @param voltage the SMC VOLTAGE structure to be populated -*/ -static int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr, - uint32_t mclk, SMIO_Pattern *smio_pat) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { - if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { - smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; - break; - } - } - PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, - "MVDD Voltage is outside the supported range.", - return -EINVAL); - } else - return -EINVAL; - - return 0; -} - -static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - int result = 0; - uint32_t sclk_frequency; - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - SMIO_Pattern vol_level; - uint32_t mvdd; - uint16_t us_mvdd; - - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - /* Get MinVoltage and Frequency from DPM0, - * already converted to SMC_UL */ - sclk_frequency = data->vbios_boot_state.sclk_bootup_value; - result = polaris10_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_sclk, - sclk_frequency, - &table->ACPILevel.MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDC voltage value " - "in Clock Dependency Table", - ); - - result = polaris10_calculate_sclk_params(hwmgr, sclk_frequency, &(table->ACPILevel.SclkSetting)); - PP_ASSERT_WITH_CODE(result == 0, "Error retrieving Engine Clock dividers from VBIOS.", return result); - - table->ACPILevel.DeepSleepDivId = 0; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac); - CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate); - - - /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ - table->MemoryACPILevel.MclkFrequency = data->vbios_boot_state.mclk_bootup_value; - result = polaris10_get_dependency_volt_by_clk(hwmgr, - table_info->vdd_dep_on_mclk, - table->MemoryACPILevel.MclkFrequency, - &table->MemoryACPILevel.MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE((0 == result), - "Cannot find ACPI VDDCI voltage value " - "in Clock Dependency Table", - ); - - us_mvdd = 0; - if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || - (data->mclk_dpm_key_disabled)) - us_mvdd = data->vbios_boot_state.mvdd_bootup_value; - else { - if (!polaris10_populate_mvdd_value(hwmgr, - data->dpm_table.mclk_table.dpm_levels[0].value, - &vol_level)) - us_mvdd = vol_level.Voltage; - } - - if (0 == polaris10_populate_mvdd_value(hwmgr, 0, &vol_level)) - table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage); - else - table->MemoryACPILevel.MinMvdd = 0; - - table->MemoryACPILevel.StutterEnable = false; - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - table->MemoryACPILevel.ActivityLevel = - PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); - - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); - - return result; -} - -static int polaris10_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t vddci; - - table->VceLevelCount = (uint8_t)(mm_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = mm_table->entries[count].eclk; - table->VceLevel[count].MinVoltage = 0; - table->VceLevel[count].MinVoltage |= - (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; - else - vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; - - - table->VceLevel[count].MinVoltage |= - (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /*retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); - } - return result; -} - - -static int polaris10_populate_smc_samu_level(struct pp_hwmgr *hwmgr, - SMU74_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t vddci; - - table->SamuBootLevel = 0; - table->SamuLevelCount = (uint8_t)(mm_table->count); - - for (count = 0; count < table->SamuLevelCount; count++) { - /* not sure whether we need evclk or not */ - table->SamuLevel[count].MinVoltage = 0; - table->SamuLevel[count].Frequency = mm_table->entries[count].samclock; - table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; - else - vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; - - table->SamuLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->SamuLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for samu clock", return result); - - table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage); - } - return result; -} - -static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, - int32_t eng_clock, int32_t mem_clock, - SMU74_Discrete_MCArbDramTimingTableEntry *arb_regs) -{ - uint32_t dram_timing; - uint32_t dram_timing2; - uint32_t burst_time; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - eng_clock, mem_clock); - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); - arb_regs->McArbBurstTime = (uint8_t)burst_time; - - return 0; -} - -static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct SMU74_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - int result = 0; - - for (i = 0; i < hw_data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < hw_data->dpm_table.mclk_table.count; j++) { - result = polaris10_populate_memory_timing_parameters(hwmgr, - hw_data->dpm_table.sclk_table.dpm_levels[i].value, - hw_data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - if (result == 0) - result = atomctrl_set_ac_timing_ai(hwmgr, hw_data->dpm_table.mclk_table.dpm_levels[j].value, j); - if (result != 0) - return result; - } - } - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU74_Discrete_MCArbDramTimingTable), - SMC_RAM_END); - return result; -} - -static int polaris10_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - int result = -EINVAL; - uint8_t count; - struct pp_atomctrl_clock_dividers_vi dividers; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - table_info->mm_dep_table; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t vddci; - - table->UvdLevelCount = (uint8_t)(mm_table->count); - table->UvdBootLevel = 0; - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].MinVoltage = 0; - table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; - table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * - VOLTAGE_SCALE) << VDDC_SHIFT; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) - vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) - vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; - else - vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; - - table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; - table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].VclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Vclk clock", return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((0 == result), - "can not find divide id for Dclk clock", return result); - - table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); - } - - return result; -} - -static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table */ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(table->GraphicsBootLevel)); - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(table->MemoryBootLevel)); - - table->BootVddc = data->vbios_boot_state.vddc_bootup_value * - VOLTAGE_SCALE; - table->BootVddci = data->vbios_boot_state.vddci_bootup_value * - VOLTAGE_SCALE; - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * - VOLTAGE_SCALE; - - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); - CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); - CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); - - return 0; -} - -static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint8_t count, level; - - count = (uint8_t)(table_info->vdd_dep_on_sclk->count); - - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_sclk->entries[level].clk >= - hw_data->vbios_boot_state.sclk_bootup_value) { - smu_data->smc_state_table.GraphicsBootLevel = level; - break; - } - } - - count = (uint8_t)(table_info->vdd_dep_on_mclk->count); - for (level = 0; level < count; level++) { - if (table_info->vdd_dep_on_mclk->entries[level].clk >= - hw_data->vbios_boot_state.mclk_bootup_value) { - smu_data->smc_state_table.MemoryBootLevel = level; - break; - } - } - - return 0; -} - - -static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) -{ - uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - - stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; - - /* Read SMU_Eefuse to read and calculate RO and determine - * if the part is SS or FF. if RO >= 1660MHz, part is FF. - */ - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (67 * 4)); - efuse &= 0xFF000000; - efuse = efuse >> 24; - - if (hwmgr->chip_id == CHIP_POLARIS10) { - min = 1000; - max = 2300; - } else { - min = 1100; - max = 2100; - } - - ro = efuse * (max - min) / 255 + min; - - /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ - for (i = 0; i < sclk_table->count; i++) { - smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= - sclk_table->entries[i].cks_enable << i; - if (hwmgr->chip_id == CHIP_POLARIS10) { - volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * 136418 - (ro - 70) * 1000000) / \ - (2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000)); - volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * 3232 - (ro - 65) * 1000000) / \ - (2522480 - sclk_table->entries[i].clk/100 * 115764/100)); - } else { - volt_without_cks = (uint32_t)((2416794800U + (sclk_table->entries[i].clk/100) * 1476925/10 - (ro - 50) * 1000000) / \ - (2625416 - (sclk_table->entries[i].clk/100) * (12586807/10000))); - volt_with_cks = (uint32_t)((2999656000U - sclk_table->entries[i].clk/100 * 392803 - (ro - 44) * 1000000) / \ - (3422454 - sclk_table->entries[i].clk/100 * (18886376/10000))); - } - - if (volt_without_cks >= volt_with_cks) - volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + - sclk_table->entries[i].cks_voffset) * 100 + 624) / 625); - - smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; - } - - smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6; - /* Populate CKS Lookup Table */ - if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) - stretch_amount2 = 0; - else if (stretch_amount == 3 || stretch_amount == 4) - stretch_amount2 = 1; - else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - PP_ASSERT_WITH_CODE(false, - "Stretch Amount in PPTable not supported\n", - return -EINVAL); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); - value &= 0xFFFFFFFE; - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); - - return 0; -} - -/** -* Populates the SMC VRConfig field in DPM table. -* -* @param hwmgr the address of the hardware manager -* @param table the SMC DPM table structure to be populated -* @return always 0 -*/ -static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, - struct SMU74_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint16_t config; - - config = VR_MERGED_WITH_VDDC; - table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); - - /* Set Vddc Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - config = VR_SVI2_PLANE_1; - table->VRConfig |= config; - } else { - PP_ASSERT_WITH_CODE(false, - "VDDC should be on SVI2 control in merged mode!", - ); - } - /* Set Vddci Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - config = VR_SVI2_PLANE_2; /* only in merged mode */ - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - config = VR_SMIO_PATTERN_1; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); - } - /* Set Mvdd Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, smu_data->smu7_data.soft_regs_start + - offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1); - } else { - config = VR_STATIC_VOLTAGE; - table->VRConfig |= (config << VRCONF_MVDD_SHIFT); - } - - return 0; -} - - -static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); - int result = 0; - struct pp_atom_ctrl__avfs_parameters avfs_params = {0}; - AVFS_meanNsigma_t AVFS_meanNsigma = { {0} }; - AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} }; - uint32_t tmp, i; - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)hwmgr->pptable; - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - - - if (((struct smu7_smumgr *)smu_data)->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) - return result; - - result = atomctrl_get_avfs_information(hwmgr, &avfs_params); - - if (0 == result) { - table->BTCGB_VDROOP_TABLE[0].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); - table->BTCGB_VDROOP_TABLE[0].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1); - table->BTCGB_VDROOP_TABLE[0].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2); - table->BTCGB_VDROOP_TABLE[1].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0); - table->BTCGB_VDROOP_TABLE[1].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1); - table->BTCGB_VDROOP_TABLE[1].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2); - table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1); - table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2); - table->AVFSGB_VDROOP_TABLE[0].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b); - table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24; - table->AVFSGB_VDROOP_TABLE[0].m2_shift = 12; - table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1); - table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2); - table->AVFSGB_VDROOP_TABLE[1].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b); - table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24; - table->AVFSGB_VDROOP_TABLE[1].m2_shift = 12; - table->MaxVoltage = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv); - AVFS_meanNsigma.Aconstant[0] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0); - AVFS_meanNsigma.Aconstant[1] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1); - AVFS_meanNsigma.Aconstant[2] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2); - AVFS_meanNsigma.DC_tol_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma); - AVFS_meanNsigma.Platform_mean = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean); - AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor); - AVFS_meanNsigma.Platform_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma); - - for (i = 0; i < NUM_VFT_COLUMNS; i++) { - AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625); - AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100); - } - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma), - &tmp, SMC_RAM_END); - - smu7_copy_bytes_to_smc(hwmgr, - tmp, - (uint8_t *)&AVFS_meanNsigma, - sizeof(AVFS_meanNsigma_t), - SMC_RAM_END); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable), - &tmp, SMC_RAM_END); - smu7_copy_bytes_to_smc(hwmgr, - tmp, - (uint8_t *)&AVFS_SclkOffset, - sizeof(AVFS_Sclk_Offset_t), - SMC_RAM_END); - - data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) | - (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT); - data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false; - } - return result; -} - - -/** -* Initialize the ARB DRAM timing table's index field. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -static int polaris10_init_arb_table_index(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t tmp; - int result; - - /* This is a read-modify-write on the first byte of the ARB table. - * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure - * is the field 'current'. - * This solution is ugly, but we never write the whole table only - * individual fields in it. - * In reality this field should not be in that structure - * but in a soft register. - */ - result = smu7_read_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); - - if (result) - return result; - - tmp &= 0x00FFFFFF; - tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - - return smu7_write_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); -} - -static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (table_info && - table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && - table_info->cac_dtp_table->usPowerTuneDataSetID) - smu_data->power_tune_defaults = - &polaris10_power_tune_data_set_array - [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; - else - smu_data->power_tune_defaults = &polaris10_power_tune_data_set_array[0]; - -} - -static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct SMU74_Discrete_GraphicsLevel *levels = - data->smc_state_table.GraphicsLevel; - unsigned min_level = 1; - - hwmgr->default_gfx_power_profile.activity_threshold = - be16_to_cpu(levels[0].ActivityLevel); - hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst; - hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst; - hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; - - hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile; - hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; - - /* Workaround compute SDMA instability: disable lowest SCLK - * DPM level. Optimize compute power profile: Use only highest - * 2 power levels (if more than 2 are available), Hysteresis: - * 0ms up, 5ms down - */ - if (data->smc_state_table.GraphicsDpmLevelCount > 2) - min_level = data->smc_state_table.GraphicsDpmLevelCount - 2; - else if (data->smc_state_table.GraphicsDpmLevelCount == 2) - min_level = 1; - else - min_level = 0; - hwmgr->default_compute_power_profile.min_sclk = - be32_to_cpu(levels[min_level].SclkSetting.SclkFrequency); - hwmgr->default_compute_power_profile.up_hyst = 0; - hwmgr->default_compute_power_profile.down_hyst = 5; - - hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; - hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; -} - -/** -* Initializes the SMC table and uploads it -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); - uint8_t i; - struct pp_atomctrl_gpio_pin_assignment gpio_pin; - pp_atomctrl_clock_dividers_vi dividers; - - polaris10_initialize_power_tune_defaults(hwmgr); - - if (SMU7_VOLTAGE_CONTROL_NONE != hw_data->voltage_control) - polaris10_populate_smc_voltage_tables(hwmgr, table); - - table->SystemFlags = 0; - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (hw_data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - if (hw_data->ulv_supported && table_info->us_ulv_voltage_offset) { - result = polaris10_populate_ulv_state(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ULV state!", return result); - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, SMU7_CGULVPARAMETER_DFLT); - } - - result = polaris10_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Link Level!", return result); - - result = polaris10_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Graphics Level!", return result); - - result = polaris10_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Memory Level!", return result); - - result = polaris10_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize ACPI Level!", return result); - - result = polaris10_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize VCE Level!", return result); - - result = polaris10_populate_smc_samu_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize SAMU Level!", return result); - - /* Since only the initial state is completely set up at this point - * (the other states are just copies of the boot state) we only - * need to populate the ARB settings for the initial state. - */ - result = polaris10_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to Write ARB settings for the initial state.", return result); - - result = polaris10_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize UVD Level!", return result); - - result = polaris10_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot Level!", return result); - - result = polaris10_populate_smc_initailial_state(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to initialize Boot State!", return result); - - result = polaris10_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate BAPM Parameters!", return result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - result = polaris10_populate_clock_stretcher_data_table(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate Clock Stretcher Data Table!", - return result); - } - - result = polaris10_populate_avfs_parameters(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;); - - table->CurrSclkPllRange = 0xff; - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - table->TemperatureLimitHigh = - table_info->cac_dtp_table->usTargetOperatingTemp * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->TemperatureLimitLow = - (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - table->PCIeBootLinkLevel = 0; - table->PCIeGenInterval = 1; - table->VRConfig = 0; - - result = polaris10_populate_vr_config(hwmgr, table); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate VRConfig setting!", return result); - - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { - table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, - &gpio_pin)) { - table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } else { - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } - - /* Thermal Output GPIO */ - if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, - &gpio_pin)) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - - table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; - - /* For porlarity read GPIOPAD_A with assigned Gpio pin - * since VBIOS will program this register to set 'inactive state', - * driver can then determine 'active state' from this and - * program SMU with correct polarity - */ - table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) - & (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; - - /* if required, combine VRHot/PCC with thermal out GPIO */ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot) - && phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CombinePCCWithThermalSignal)) - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; - } else { - table->ThermOutGpio = 17; - table->ThermOutPolarity = 1; - table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; - } - - /* Populate BIF_SCLK levels into SMC DPM table */ - for (i = 0; i <= hw_data->dpm_table.pcie_speed_table.count; i++) { - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, smu_data->bif_sclk_table[i], ÷rs); - PP_ASSERT_WITH_CODE((result == 0), "Can not find DFS divide id for Sclk", return result); - - if (i == 0) - table->Ulv.BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider)); - else - table->LinkLevel[i-1].BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider)); - } - - for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++) - table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU74_Discrete_DpmTable) - 3 * sizeof(SMU74_PIDController), - SMC_RAM_END); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload dpm data to SMC memory!", return result); - - result = polaris10_init_arb_table_index(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to upload arb data to SMC memory!", return result); - - result = polaris10_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE(0 == result, - "Failed to populate PM fuses to SMC memory!", return result); - - polaris10_save_default_power_profile(hwmgr); - - return 0; -} - -static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return polaris10_program_memory_timing_parameters(hwmgr); - - return 0; -} - -int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) -{ - int ret; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) - return 0; - - ret = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting); - - ret = (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs) == 0) ? - 0 : -1; - - if (!ret) - /* If this param is not changed, this function could fire unnecessarily */ - smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY; - - return ret; -} - -/** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (smu_data->smu7_data.fan_table_start == 0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, - CG_FDO_CTRL1, FMAX_DUTY100); - - if (duty100 == 0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. - usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr-> - thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr-> - thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = smu7_get_xclk(hwmgr); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> - thermal_controller.advanceFanControlParameters.ulCycleDelay * - reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( - hwmgr->device, CGS_IND_REG__SMC, - CG_MULT_THERMAL_CTRL, TEMP_SEL); - - res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, - (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), - SMC_RAM_END); - - if (!res && hwmgr->thermal_controller. - advanceFanControlParameters.ucMinimumPWMLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanMinPwm, - hwmgr->thermal_controller. - advanceFanControlParameters.ucMinimumPWMLimit); - - if (!res && hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit) - res = smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SetFanSclkTarget, - hwmgr->thermal_controller. - advanceFanControlParameters.ulMinFanSCLKAcousticLimit); - - if (res) - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - - return 0; -} - -static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - smu_data->smc_state_table.UvdBootLevel = 0; - if (table_info->mm_dep_table->count > 0) - smu_data->smc_state_table.UvdBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, - UvdBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0x00FFFFFF; - mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); - return 0; -} - -static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smu_data->smc_state_table.VceBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - else - smu_data->smc_state_table.VceBootLevel = 0; - - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, VceBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFF00FFFF; - mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_VCEDPM_SetEnabledMask, - (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); - return 0; -} - -static int polaris10_update_samu_smc_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - - - smu_data->smc_state_table.SamuBootLevel = 0; - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, SamuBootLevel); - - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFFFFFF00; - mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SAMUDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); - return 0; -} - - -static int polaris10_update_bif_smc_table(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; - int max_entry, i; - - max_entry = (SMU74_MAX_LEVELS_LINK < pcie_table->count) ? - SMU74_MAX_LEVELS_LINK : - pcie_table->count; - /* Setup BIF_SCLK levels */ - for (i = 0; i < max_entry; i++) - smu_data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk; - return 0; -} - -int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - switch (type) { - case SMU_UVD_TABLE: - polaris10_update_uvd_smc_table(hwmgr); - break; - case SMU_VCE_TABLE: - polaris10_update_vce_smc_table(hwmgr); - break; - case SMU_SAMU_TABLE: - polaris10_update_samu_smc_table(hwmgr); - break; - case SMU_BIF_TABLE: - polaris10_update_bif_smc_table(hwmgr); - default: - break; - } - return 0; -} - -int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (hwmgr->gfx_arbiter.sclk_threshold != - data->low_sclk_interrupt_threshold)) { - data->low_sclk_interrupt_threshold = - hwmgr->gfx_arbiter.sclk_threshold; - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - PP_ASSERT_WITH_CODE((result == 0), - "Failed to update SCLK threshold!", return result); - - result = polaris10_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters!", - ); - - return result; -} - -uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU74_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU74_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU74_SoftRegisters, AverageGraphicsActivity); - case PreVBlankGap: - return offsetof(SMU74_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU74_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU74_SoftRegisters, UcodeLoadStatus); - } - case SMU_Discrete_DpmTable: - switch (member) { - case UvdBootLevel: - return offsetof(SMU74_Discrete_DpmTable, UvdBootLevel); - case VceBootLevel: - return offsetof(SMU74_Discrete_DpmTable, VceBootLevel); - case SamuBootLevel: - return offsetof(SMU74_Discrete_DpmTable, SamuBootLevel); - case LowSclkInterruptThreshold: - return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold); - } - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -uint32_t polaris10_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU74_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU74_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU74_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU74_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU74_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDGFX: - return SMU74_MAX_LEVELS_VDDGFX; - case SMU_MAX_LEVELS_VDDCI: - return SMU74_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU74_MAX_LEVELS_MVDD; - case SMU_UVD_MCLK_HANDSHAKE_DISABLE: - return SMU7_UVD_MCLK_HANDSHAKE_DISABLE; - } - - pr_warn("can't get the mac of %x\n", value); - return 0; -} - -/** -* Get the location of various tables inside the FW image. -* -* @param hwmgr the address of the powerplay hardware manager. -* @return always 0 -*/ -int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (0 == result) - smu_data->smu7_data.dpm_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (!result) { - data->soft_regs_start = tmp; - smu_data->smu7_data.soft_regs_start = tmp; - } - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.mc_reg_table_start = tmp; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.fan_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.arb_table_start = tmp; - - error |= (0 != result); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU7_FIRMWARE_HEADER_LOCATION + - offsetof(SMU74_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (!result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (0 != result); - - return error ? -1 : 0; -} - -bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request) -{ - struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *) - (hwmgr->smu_backend); - struct SMU74_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) * - SMU74_MAX_LEVELS_GRAPHICS; - uint32_t i; - - for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { - levels[i].ActivityLevel = - cpu_to_be16(request->activity_threshold); - levels[i].EnabledForActivity = 1; - levels[i].UpHyst = request->up_hyst; - levels[i].DownHyst = request->down_hyst; - } - - return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - array_size, SMC_RAM_END); -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c index 22b8ecbf7fce..bd6be7793ca7 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smumgr.c @@ -35,13 +35,47 @@ #include "gca/gfx_8_0_d.h" #include "bif/bif_5_0_d.h" #include "bif/bif_5_0_sh_mask.h" -#include "polaris10_pwrvirus.h" #include "ppatomctrl.h" #include "cgs_common.h" -#include "polaris10_smc.h" #include "smu7_ppsmc.h" #include "smu7_smumgr.h" +#include "smu7_dyn_defaults.h" + +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" +#include "atombios.h" +#include "pppcielanes.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + +#define POLARIS10_SMC_SIZE 0x20000 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define VDDC_VDDCI_DELTA 200 +#define MC_CG_ARB_FREQ_F1 0x0b + +static const struct polaris10_pt_defaults polaris10_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { + /* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT */ + { 1, 0xF, 0xFD, 0x19, 5, 45, 0, 0xB0000, + { 0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, + { 0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4 } }, +}; + +static const sclkFcwRange_t Range_Table[NUM_SCLK_RANGE] = { + {VCO_2_4, POSTDIV_DIV_BY_16, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_16, 112, 224, 160}, + {VCO_2_4, POSTDIV_DIV_BY_8, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_8, 112, 224, 160}, + {VCO_2_4, POSTDIV_DIV_BY_4, 75, 160, 112}, + {VCO_3_6, POSTDIV_DIV_BY_4, 112, 216, 160}, + {VCO_2_4, POSTDIV_DIV_BY_2, 75, 160, 108}, + {VCO_3_6, POSTDIV_DIV_BY_2, 112, 216, 160} }; + #define PPPOLARIS10_TARGETACTIVITY_DFLT 50 static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = { @@ -60,39 +94,6 @@ static const SMU74_Discrete_GraphicsLevel avfs_graphics_level_polaris10[8] = { static const SMU74_Discrete_MemoryLevel avfs_memory_level_polaris10 = { 0x100ea446, 0, 0x30750000, 0x01, 0x01, 0x01, 0x00, 0x00, 0x64, 0x00, 0x00, 0x1f00, 0x00, 0x00}; -static int polaris10_setup_pwr_virus(struct pp_hwmgr *hwmgr) -{ - int i; - int result = -EINVAL; - uint32_t reg, data; - - const PWR_Command_Table *pvirus = pwr_virus_table; - struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); - - for (i = 0; i < PWR_VIRUS_TABLE_SIZE; i++) { - switch (pvirus->command) { - case PwrCmdWrite: - reg = pvirus->reg; - data = pvirus->data; - cgs_write_register(hwmgr->device, reg, data); - break; - - case PwrCmdEnd: - result = 0; - break; - - default: - pr_info("Table Exit with Invalid Command!"); - smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; - result = -EINVAL; - break; - } - pvirus++; - } - - return result; -} - static int polaris10_perform_btc(struct pp_hwmgr *hwmgr) { int result = 0; @@ -190,7 +191,7 @@ polaris10_avfs_event_mgr(struct pp_hwmgr *hwmgr, bool SMU_VFT_INTACT) if (smu_data->avfs.avfs_btc_param > 1) { pr_info("[AVFS][Polaris10_AVFSEventMgr] AC BTC has not been successfully verified on Fiji. There may be in this setting."); smu_data->avfs.avfs_btc_status = AVFS_BTC_VIRUS_FAIL; - PP_ASSERT_WITH_CODE(0 == polaris10_setup_pwr_virus(hwmgr), + PP_ASSERT_WITH_CODE(0 == smu7_setup_pwr_virus(hwmgr), "[AVFS][Polaris10_AVFSEventMgr] Could not setup Pwr Virus for AVFS ", return -EINVAL); } @@ -382,6 +383,2195 @@ static int polaris10_smu_init(struct pp_hwmgr *hwmgr) return 0; } +static int polaris10_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table *dep_table, + uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) +{ + uint32_t i; + uint16_t vddci; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + *voltage = *mvdd = 0; + + /* clock - voltage dependency table is empty table */ + if (dep_table->count == 0) + return -EINVAL; + + for (i = 0; i < dep_table->count; i++) { + /* find first sclk bigger than request */ + if (dep_table->entries[i].clk >= clock) { + *voltage |= (dep_table->entries[i].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i].vddci) + *voltage |= (dep_table->entries[i].vddci * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + (uint16_t)VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i].mvdd * + VOLTAGE_SCALE; + + *voltage |= 1 << PHASES_SHIFT; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i-1].vddci) { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i].vddc - + (uint16_t)VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; + + return 0; +} + +static uint16_t scale_fan_gain_settings(uint16_t raw_setting) +{ + uint32_t tmp; + tmp = raw_setting * 4096 / 100; + return (uint16_t)tmp; +} + +static int polaris10_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; + struct pp_advance_fan_control_parameters *fan_table = + &hwmgr->thermal_controller.advanceFanControlParameters; + int i, j, k; + const uint16_t *pdef1; + const uint16_t *pdef2; + + table->DefaultTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); + table->TargetTdp = PP_HOST_TO_SMC_US((uint16_t)(cac_dtp_table->usTDP * 128)); + + PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, + "Target Operating Temp is out of Range!", + ); + + table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( + cac_dtp_table->usTargetOperatingTemp * 256); + table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitHotspot * 256); + table->FanGainEdge = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainEdge)); + table->FanGainHotspot = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHotspot)); + + pdef1 = defaults->BAPMTI_R; + pdef2 = defaults->BAPMTI_RC; + + for (i = 0; i < SMU74_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU74_DTE_SOURCES; j++) { + for (k = 0; k < SMU74_DTE_SINKS; k++) { + table->BAPMTI_R[i][j][k] = PP_HOST_TO_SMC_US(*pdef1); + table->BAPMTI_RC[i][j][k] = PP_HOST_TO_SMC_US(*pdef2); + pdef1++; + pdef2++; + } + } + } + + return 0; +} + +static int polaris10_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; + smu_data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int polaris10_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; + + tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->TDC_VDDC_ThrottleReleaseLimitPerc; + smu_data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; + + return 0; +} + +static int polaris10_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + const struct polaris10_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU74_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else { + smu_data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; + smu_data->power_tune_table.LPMLTemperatureMin = + (uint8_t)((temp >> 16) & 0xff); + smu_data->power_tune_table.LPMLTemperatureMax = + (uint8_t)((temp >> 8) & 0xff); + smu_data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); + } + return 0; +} + +static int polaris10_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + int i; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; + + return 0; +} + +static int polaris10_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + +/* TO DO move to hwmgr */ + if ((hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity & (1 << 15)) + || 0 == hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity) + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity = + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = PP_HOST_TO_SMC_US( + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity); + return 0; +} + +static int polaris10_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int polaris10_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + + hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); + + return 0; +} + +static int polaris10_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed!", + return -EINVAL); + + if (polaris10_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed!", + return -EINVAL); + + if (polaris10_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed!", return -EINVAL); + + if (polaris10_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl, " + "LPMLTemperature Min and Max Failed!", + return -EINVAL); + + if (0 != polaris10_populate_temperature_scaler(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed!", + return -EINVAL); + + if (polaris10_populate_fuzzy_fan(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate Fuzzy Fan Control parameters Failed!", + return -EINVAL); + + if (polaris10_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed!", + return -EINVAL); + + if (polaris10_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate BapmVddCBaseLeakage Hi and Lo " + "Sidd Failed!", return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + (sizeof(struct SMU74_Discrete_PmFuses) - 92), SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed!", + return -EINVAL); + } + return 0; +} + +static int polaris10_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count, level; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + count = data->mvdd_voltage_table.count; + if (count > SMU_MAX_SMIO_LEVELS) + count = SMU_MAX_SMIO_LEVELS; + for (level = 0; level < count; level++) { + table->SmioTable2.Pattern[level].Voltage = + PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ + table->SmioTable2.Pattern[level].Smio = + (uint8_t) level; + table->Smio[level] |= + data->mvdd_voltage_table.entries[level].smio_low; + } + table->SmioMask2 = data->mvdd_voltage_table.mask_low; + + table->MvddLevelCount = (uint32_t) PP_HOST_TO_SMC_UL(count); + } + + return 0; +} + +static int polaris10_populate_smc_vddci_table(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + uint32_t count, level; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + count = data->vddci_voltage_table.count; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + if (count > SMU_MAX_SMIO_LEVELS) + count = SMU_MAX_SMIO_LEVELS; + for (level = 0; level < count; ++level) { + table->SmioTable1.Pattern[level].Voltage = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[level].value * VOLTAGE_SCALE); + table->SmioTable1.Pattern[level].Smio = (uint8_t) level; + + table->Smio[level] |= data->vddci_voltage_table.entries[level].smio_low; + } + } + + table->SmioMask1 = data->vddci_voltage_table.mask_low; + + return 0; +} + +static int polaris10_populate_cac_table(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *lookup_table = + table_info->vddc_lookup_table; + /* tables is already swapped, so in order to use the value from it, + * we need to swap it back. + * We are populating vddc CAC data to BapmVddc table + * in split and merged mode + */ + for (count = 0; count < lookup_table->count; count++) { + index = phm_get_voltage_index(lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_low); + table->BapmVddcVidHiSidd[count] = convert_to_vid(lookup_table->entries[index].us_cac_mid); + table->BapmVddcVidHiSidd2[count] = convert_to_vid(lookup_table->entries[index].us_cac_high); + } + + return 0; +} + +static int polaris10_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + polaris10_populate_smc_vddci_table(hwmgr, table); + polaris10_populate_smc_mvdd_table(hwmgr, table); + polaris10_populate_cac_table(hwmgr, table); + + return 0; +} + +static int polaris10_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_Ulv *state) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; + state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * + VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); + + if (hwmgr->chip_id == CHIP_POLARIS12 || hwmgr->is_kicker) + state->VddcPhase = data->vddc_phase_shed_control ^ 0x3; + else + state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int polaris10_populate_ulv_state(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + return polaris10_populate_ulv_level(hwmgr, &table->Ulv); +} + +static int polaris10_populate_smc_link_level(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int i; + + /* Index (dpm_table->pcie_speed_table.count) + * is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( + dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + +/* To Do move to hwmgr */ + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + + +static void polaris10_get_sclk_range_table(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t i, ref_clk; + + struct pp_atom_ctrl_sclk_range_table range_table_from_vbios = { { {0} } }; + + ref_clk = smu7_get_xclk(hwmgr); + + if (0 == atomctrl_get_smc_sclk_range_table(hwmgr, &range_table_from_vbios)) { + for (i = 0; i < NUM_SCLK_RANGE; i++) { + table->SclkFcwRangeTable[i].vco_setting = range_table_from_vbios.entry[i].ucVco_setting; + table->SclkFcwRangeTable[i].postdiv = range_table_from_vbios.entry[i].ucPostdiv; + table->SclkFcwRangeTable[i].fcw_pcc = range_table_from_vbios.entry[i].usFcw_pcc; + + table->SclkFcwRangeTable[i].fcw_trans_upper = range_table_from_vbios.entry[i].usFcw_trans_upper; + table->SclkFcwRangeTable[i].fcw_trans_lower = range_table_from_vbios.entry[i].usRcw_trans_lower; + + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); + } + return; + } + + for (i = 0; i < NUM_SCLK_RANGE; i++) { + smu_data->range_table[i].trans_lower_frequency = (ref_clk * Range_Table[i].fcw_trans_lower) >> Range_Table[i].postdiv; + smu_data->range_table[i].trans_upper_frequency = (ref_clk * Range_Table[i].fcw_trans_upper) >> Range_Table[i].postdiv; + + table->SclkFcwRangeTable[i].vco_setting = Range_Table[i].vco_setting; + table->SclkFcwRangeTable[i].postdiv = Range_Table[i].postdiv; + table->SclkFcwRangeTable[i].fcw_pcc = Range_Table[i].fcw_pcc; + + table->SclkFcwRangeTable[i].fcw_trans_upper = Range_Table[i].fcw_trans_upper; + table->SclkFcwRangeTable[i].fcw_trans_lower = Range_Table[i].fcw_trans_lower; + + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_pcc); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_upper); + CONVERT_FROM_HOST_TO_SMC_US(table->SclkFcwRangeTable[i].fcw_trans_lower); + } +} + +static int polaris10_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, SMU_SclkSetting *sclk_setting) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + const SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct pp_atomctrl_clock_dividers_ai dividers; + uint32_t ref_clock; + uint32_t pcc_target_percent, pcc_target_freq, ss_target_percent, ss_target_freq; + uint8_t i; + int result; + uint64_t temp; + + sclk_setting->SclkFrequency = clock; + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_ai(hwmgr, clock, ÷rs); + if (result == 0) { + sclk_setting->Fcw_int = dividers.usSclk_fcw_int; + sclk_setting->Fcw_frac = dividers.usSclk_fcw_frac; + sclk_setting->Pcc_fcw_int = dividers.usPcc_fcw_int; + sclk_setting->PllRange = dividers.ucSclkPllRange; + sclk_setting->Sclk_slew_rate = 0x400; + sclk_setting->Pcc_up_slew_rate = dividers.usPcc_fcw_slew_frac; + sclk_setting->Pcc_down_slew_rate = 0xffff; + sclk_setting->SSc_En = dividers.ucSscEnable; + sclk_setting->Fcw1_int = dividers.usSsc_fcw1_int; + sclk_setting->Fcw1_frac = dividers.usSsc_fcw1_frac; + sclk_setting->Sclk_ss_slew_rate = dividers.usSsc_fcw_slew_frac; + return result; + } + + ref_clock = smu7_get_xclk(hwmgr); + + for (i = 0; i < NUM_SCLK_RANGE; i++) { + if (clock > smu_data->range_table[i].trans_lower_frequency + && clock <= smu_data->range_table[i].trans_upper_frequency) { + sclk_setting->PllRange = i; + break; + } + } + + sclk_setting->Fcw_int = (uint16_t)((clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); + temp = clock << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; + temp <<= 0x10; + do_div(temp, ref_clock); + sclk_setting->Fcw_frac = temp & 0xffff; + + pcc_target_percent = 10; /* Hardcode 10% for now. */ + pcc_target_freq = clock - (clock * pcc_target_percent / 100); + sclk_setting->Pcc_fcw_int = (uint16_t)((pcc_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); + + ss_target_percent = 2; /* Hardcode 2% for now. */ + sclk_setting->SSc_En = 0; + if (ss_target_percent) { + sclk_setting->SSc_En = 1; + ss_target_freq = clock - (clock * ss_target_percent / 100); + sclk_setting->Fcw1_int = (uint16_t)((ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv) / ref_clock); + temp = ss_target_freq << table->SclkFcwRangeTable[sclk_setting->PllRange].postdiv; + temp <<= 0x10; + do_div(temp, ref_clock); + sclk_setting->Fcw1_frac = temp & 0xffff; + } + + return 0; +} + +static int polaris10_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint16_t sclk_al_threshold, + struct SMU74_Discrete_GraphicsLevel *level) +{ + int result; + /* PP_Clocks minClocks; */ + uint32_t mvdd; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + SMU_SclkSetting curr_sclk_setting = { 0 }; + + result = polaris10_calculate_sclk_params(hwmgr, clock, &curr_sclk_setting); + + /* populate graphics levels */ + result = polaris10_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, clock, + &level->MinVoltage, &mvdd); + + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for " + "VDDC engine clock dependency table", + return result); + level->ActivityLevel = sclk_al_threshold; + + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + level->EnabledForThrottle = 1; + level->UpHyst = 10; + level->DownHyst = 0; + level->VoltageDownHyst = 0; + level->PowerThrottle = 0; + data->display_timing.min_clock_in_sr = hwmgr->display_config.min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) + level->DeepSleepDivId = smu7_get_sleep_divider_id_from_clock(clock, + hwmgr->display_config.min_core_set_clock_in_sr); + + /* Default to slow, highest DPM level will be + * set to PPSMC_DISPLAY_WATERMARK_LOW later. + */ + if (data->update_up_hyst) + level->UpHyst = (uint8_t)data->up_hyst; + if (data->update_down_hyst) + level->DownHyst = (uint8_t)data->down_hyst; + + level->SclkSetting = curr_sclk_setting; + + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkSetting.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw_frac); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_up_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Pcc_down_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_int); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Fcw1_frac); + CONVERT_FROM_HOST_TO_SMC_US(level->SclkSetting.Sclk_ss_slew_rate); + return 0; +} + +static int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + uint8_t pcie_entry_cnt = (uint8_t) hw_data->dpm_table.pcie_speed_table.count; + int result = 0; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) * + SMU74_MAX_LEVELS_GRAPHICS; + struct SMU74_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t i, max_entry; + uint8_t hightest_pcie_level_enabled = 0, + lowest_pcie_level_enabled = 0, + mid_pcie_level_enabled = 0, + count = 0; + + polaris10_get_sclk_range_table(hwmgr, &(smu_data->smc_state_table)); + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + + result = polaris10_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + (uint16_t)smu_data->activity_target[i], + &(smu_data->smc_state_table.GraphicsLevel[i])); + if (result) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + levels[i].DeepSleepDivId = 0; + } + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SPLLShutdownSupport)) + smu_data->smc_state_table.GraphicsLevel[0].SclkSetting.SSc_En = 0; + + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + hw_data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + max_entry = pcie_entry_cnt - 1; + for (i = 0; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = + (uint8_t) ((i < max_entry) ? i : max_entry); + } else { + while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (hightest_pcie_level_enabled + 1))) != 0)) + hightest_pcie_level_enabled++; + + while (hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << lowest_pcie_level_enabled)) == 0)) + lowest_pcie_level_enabled++; + + while ((count < hightest_pcie_level_enabled) && + ((hw_data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (lowest_pcie_level_enabled + 1 + count))) == 0)) + count++; + + mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1 + count) < + hightest_pcie_level_enabled ? + (lowest_pcie_level_enabled + 1 + count) : + hightest_pcie_level_enabled; + + /* set pcieDpmLevel to hightest_pcie_level_enabled */ + for (i = 2; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = hightest_pcie_level_enabled; + + /* set pcieDpmLevel to lowest_pcie_level_enabled */ + levels[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled */ + levels[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + + +static int polaris10_populate_single_memory_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU74_Discrete_MemoryLevel *mem_level) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result = 0; + struct cgs_display_info info = {0, 0, NULL}; + uint32_t mclk_stutter_mode_threshold = 40000; + + cgs_get_active_displays_info(hwmgr->device, &info); + + if (table_info->vdd_dep_on_mclk) { + result = polaris10_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, clock, + &mem_level->MinVoltage, &mem_level->MinMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory " + "VDDC voltage dependency table", return result); + } + + mem_level->MclkFrequency = clock; + mem_level->EnabledForThrottle = 1; + mem_level->EnabledForActivity = 0; + mem_level->UpHyst = 0; + mem_level->DownHyst = 100; + mem_level->VoltageDownHyst = 0; + mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target; + mem_level->StutterEnable = false; + mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + data->display_timing.num_existing_displays = info.display_count; + + if (mclk_stutter_mode_threshold && + (clock <= mclk_stutter_mode_threshold) && + (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE) & 0x1)) + mem_level->StutterEnable = true; + + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); + } + return result; +} + +static int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &hw_data->dpm_table; + int result; + /* populate MCLK dpm table to SMU7 */ + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, MemoryLevel); + uint32_t array_size = sizeof(SMU74_Discrete_MemoryLevel) * + SMU74_MAX_LEVELS_MEMORY; + struct SMU74_Discrete_MemoryLevel *levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", + return -EINVAL); + result = polaris10_populate_single_memory_level(hwmgr, + dpm_table->mclk_table.dpm_levels[i].value, + &levels[i]); + if (i == dpm_table->mclk_table.count - 1) { + levels[i].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + levels[i].EnabledForActivity = 1; + } + if (result) + return result; + } + + /* In order to prevent MC activity from stutter mode to push DPM up, + * the UVD change complements this by putting the MCLK in + * a higher state by default such that we are not affected by + * up threshold or and MCLK DPM latency. + */ + levels[0].ActivityLevel = 0x1f; + CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = + (uint8_t)dpm_table->mclk_table.count; + hw_data->dpm_level_enable_mask.mclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + + /* level count will send to smc once at init smc table and never change */ + result = smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + (uint32_t)array_size, SMC_RAM_END); + + return result; +} + +static int polaris10_populate_mvdd_value(struct pp_hwmgr *hwmgr, + uint32_t mclk, SMIO_Pattern *smio_pat) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { + smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", + return -EINVAL); + } else + return -EINVAL; + + return 0; +} + +static int polaris10_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + int result = 0; + uint32_t sclk_frequency; + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + SMIO_Pattern vol_level; + uint32_t mvdd; + uint16_t us_mvdd; + + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + /* Get MinVoltage and Frequency from DPM0, + * already converted to SMC_UL */ + sclk_frequency = data->vbios_boot_state.sclk_bootup_value; + result = polaris10_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, + sclk_frequency, + &table->ACPILevel.MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDC voltage value " + "in Clock Dependency Table", + ); + + result = polaris10_calculate_sclk_params(hwmgr, sclk_frequency, &(table->ACPILevel.SclkSetting)); + PP_ASSERT_WITH_CODE(result == 0, "Error retrieving Engine Clock dividers from VBIOS.", return result); + + table->ACPILevel.DeepSleepDivId = 0; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkSetting.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw_frac); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_fcw_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_up_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Pcc_down_slew_rate); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_int); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Fcw1_frac); + CONVERT_FROM_HOST_TO_SMC_US(table->ACPILevel.SclkSetting.Sclk_ss_slew_rate); + + + /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ + table->MemoryACPILevel.MclkFrequency = data->vbios_boot_state.mclk_bootup_value; + result = polaris10_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, + table->MemoryACPILevel.MclkFrequency, + &table->MemoryACPILevel.MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDCI voltage value " + "in Clock Dependency Table", + ); + + us_mvdd = 0; + if ((SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) || + (data->mclk_dpm_key_disabled)) + us_mvdd = data->vbios_boot_state.mvdd_bootup_value; + else { + if (!polaris10_populate_mvdd_value(hwmgr, + data->dpm_table.mclk_table.dpm_levels[0].value, + &vol_level)) + us_mvdd = vol_level.Voltage; + } + + if (0 == polaris10_populate_mvdd_value(hwmgr, 0, &vol_level)) + table->MemoryACPILevel.MinMvdd = PP_HOST_TO_SMC_UL(vol_level.Voltage); + else + table->MemoryACPILevel.MinMvdd = 0; + + table->MemoryACPILevel.StutterEnable = false; + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + table->MemoryACPILevel.ActivityLevel = + PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); + + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); + + return result; +} + +static int polaris10_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t vddci; + + table->VceLevelCount = (uint8_t)(mm_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage = 0; + table->VceLevel[count].MinVoltage |= + (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; + else + vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; + + + table->VceLevel[count].MinVoltage |= + (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /*retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); + } + return result; +} + + +static int polaris10_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU74_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t vddci; + + table->SamuBootLevel = 0; + table->SamuLevelCount = (uint8_t)(mm_table->count); + + for (count = 0; count < table->SamuLevelCount; count++) { + /* not sure whether we need evclk or not */ + table->SamuLevel[count].MinVoltage = 0; + table->SamuLevel[count].Frequency = mm_table->entries[count].samclock; + table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; + else + vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; + + table->SamuLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->SamuLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for samu clock", return result); + + table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage); + } + return result; +} + +static int polaris10_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, + int32_t eng_clock, int32_t mem_clock, + SMU74_Discrete_MCArbDramTimingTableEntry *arb_regs) +{ + uint32_t dram_timing; + uint32_t dram_timing2; + uint32_t burst_time; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + eng_clock, mem_clock); + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); + arb_regs->McArbBurstTime = (uint8_t)burst_time; + + return 0; +} + +static int polaris10_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct SMU74_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + int result = 0; + + for (i = 0; i < hw_data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < hw_data->dpm_table.mclk_table.count; j++) { + result = polaris10_populate_memory_timing_parameters(hwmgr, + hw_data->dpm_table.sclk_table.dpm_levels[i].value, + hw_data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + if (result == 0) + result = atomctrl_set_ac_timing_ai(hwmgr, hw_data->dpm_table.mclk_table.dpm_levels[j].value, j); + if (result != 0) + return result; + } + } + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU74_Discrete_MCArbDramTimingTable), + SMC_RAM_END); + return result; +} + +static int polaris10_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t vddci; + + table->UvdLevelCount = (uint8_t)(mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].MinVoltage = 0; + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) + vddci = (uint32_t)phm_find_closest_vddci(&(data->vddci_voltage_table), + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + else if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) + vddci = mm_table->entries[count].vddc - VDDC_VDDCI_DELTA; + else + vddci = (data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE) << VDDCI_SHIFT; + + table->UvdLevel[count].MinVoltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); + } + + return result; +} + +static int polaris10_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table */ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(table->GraphicsBootLevel)); + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(table->MemoryBootLevel)); + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value * + VOLTAGE_SCALE; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return 0; +} + +static int polaris10_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint8_t count, level; + + count = (uint8_t)(table_info->vdd_dep_on_sclk->count); + + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_sclk->entries[level].clk >= + hw_data->vbios_boot_state.sclk_bootup_value) { + smu_data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(table_info->vdd_dep_on_mclk->count); + for (level = 0; level < count; level++) { + if (table_info->vdd_dep_on_mclk->entries[level].clk >= + hw_data->vbios_boot_state.mclk_bootup_value) { + smu_data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int polaris10_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + uint32_t ro, efuse, volt_without_cks, volt_with_cks, value, max, min; + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + uint8_t i, stretch_amount, stretch_amount2, volt_offset = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + + stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; + + /* Read SMU_Eefuse to read and calculate RO and determine + * if the part is SS or FF. if RO >= 1660MHz, part is FF. + */ + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (67 * 4)); + efuse &= 0xFF000000; + efuse = efuse >> 24; + + if (hwmgr->chip_id == CHIP_POLARIS10) { + min = 1000; + max = 2300; + } else { + min = 1100; + max = 2100; + } + + ro = efuse * (max - min) / 255 + min; + + /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ + for (i = 0; i < sclk_table->count; i++) { + smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= + sclk_table->entries[i].cks_enable << i; + if (hwmgr->chip_id == CHIP_POLARIS10) { + volt_without_cks = (uint32_t)((2753594000U + (sclk_table->entries[i].clk/100) * 136418 - (ro - 70) * 1000000) / \ + (2424180 - (sclk_table->entries[i].clk/100) * 1132925/1000)); + volt_with_cks = (uint32_t)((2797202000U + sclk_table->entries[i].clk/100 * 3232 - (ro - 65) * 1000000) / \ + (2522480 - sclk_table->entries[i].clk/100 * 115764/100)); + } else { + volt_without_cks = (uint32_t)((2416794800U + (sclk_table->entries[i].clk/100) * 1476925/10 - (ro - 50) * 1000000) / \ + (2625416 - (sclk_table->entries[i].clk/100) * (12586807/10000))); + volt_with_cks = (uint32_t)((2999656000U - sclk_table->entries[i].clk/100 * 392803 - (ro - 44) * 1000000) / \ + (3422454 - sclk_table->entries[i].clk/100 * (18886376/10000))); + } + + if (volt_without_cks >= volt_with_cks) + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + + sclk_table->entries[i].cks_voffset) * 100 + 624) / 625); + + smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; + } + + smu_data->smc_state_table.LdoRefSel = (table_info->cac_dtp_table->ucCKS_LDO_REFSEL != 0) ? table_info->cac_dtp_table->ucCKS_LDO_REFSEL : 6; + /* Populate CKS Lookup Table */ + if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) + stretch_amount2 = 0; + else if (stretch_amount == 3 || stretch_amount == 4) + stretch_amount2 = 1; + else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + PP_ASSERT_WITH_CODE(false, + "Stretch Amount in PPTable not supported\n", + return -EINVAL); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); + value &= 0xFFFFFFFE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); + + return 0; +} + +static int polaris10_populate_vr_config(struct pp_hwmgr *hwmgr, + struct SMU74_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint16_t config; + + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); + + /* Set Vddc Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + PP_ASSERT_WITH_CODE(false, + "VDDC should be on SVI2 control in merged mode!", + ); + } + /* Set Vddci Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } + /* Set Mvdd Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, smu_data->smu7_data.soft_regs_start + + offsetof(SMU74_SoftRegisters, AllowMvddSwitch), 0x1); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } + + return 0; +} + + +static int polaris10_populate_avfs_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + int result = 0; + struct pp_atom_ctrl__avfs_parameters avfs_params = {0}; + AVFS_meanNsigma_t AVFS_meanNsigma = { {0} }; + AVFS_Sclk_Offset_t AVFS_SclkOffset = { {0} }; + uint32_t tmp, i; + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + + + if (((struct smu7_smumgr *)smu_data)->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) + return result; + + result = atomctrl_get_avfs_information(hwmgr, &avfs_params); + + if (0 == result) { + table->BTCGB_VDROOP_TABLE[0].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a0); + table->BTCGB_VDROOP_TABLE[0].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a1); + table->BTCGB_VDROOP_TABLE[0].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSON_a2); + table->BTCGB_VDROOP_TABLE[1].a0 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a0); + table->BTCGB_VDROOP_TABLE[1].a1 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a1); + table->BTCGB_VDROOP_TABLE[1].a2 = PP_HOST_TO_SMC_UL(avfs_params.ulGB_VDROOP_TABLE_CKSOFF_a2); + table->AVFSGB_VDROOP_TABLE[0].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_m1); + table->AVFSGB_VDROOP_TABLE[0].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSON_m2); + table->AVFSGB_VDROOP_TABLE[0].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSON_b); + table->AVFSGB_VDROOP_TABLE[0].m1_shift = 24; + table->AVFSGB_VDROOP_TABLE[0].m2_shift = 12; + table->AVFSGB_VDROOP_TABLE[1].m1 = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_m1); + table->AVFSGB_VDROOP_TABLE[1].m2 = PP_HOST_TO_SMC_US(avfs_params.usAVFSGB_FUSE_TABLE_CKSOFF_m2); + table->AVFSGB_VDROOP_TABLE[1].b = PP_HOST_TO_SMC_UL(avfs_params.ulAVFSGB_FUSE_TABLE_CKSOFF_b); + table->AVFSGB_VDROOP_TABLE[1].m1_shift = 24; + table->AVFSGB_VDROOP_TABLE[1].m2_shift = 12; + table->MaxVoltage = PP_HOST_TO_SMC_US(avfs_params.usMaxVoltage_0_25mv); + AVFS_meanNsigma.Aconstant[0] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant0); + AVFS_meanNsigma.Aconstant[1] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant1); + AVFS_meanNsigma.Aconstant[2] = PP_HOST_TO_SMC_UL(avfs_params.ulAVFS_meanNsigma_Acontant2); + AVFS_meanNsigma.DC_tol_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_DC_tol_sigma); + AVFS_meanNsigma.Platform_mean = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_mean); + AVFS_meanNsigma.PSM_Age_CompFactor = PP_HOST_TO_SMC_US(avfs_params.usPSM_Age_ComFactor); + AVFS_meanNsigma.Platform_sigma = PP_HOST_TO_SMC_US(avfs_params.usAVFS_meanNsigma_Platform_sigma); + + for (i = 0; i < NUM_VFT_COLUMNS; i++) { + AVFS_meanNsigma.Static_Voltage_Offset[i] = (uint8_t)(sclk_table->entries[i].cks_voffset * 100 / 625); + AVFS_SclkOffset.Sclk_Offset[i] = PP_HOST_TO_SMC_US((uint16_t)(sclk_table->entries[i].sclk_offset) / 100); + } + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsMeanNSigma), + &tmp, SMC_RAM_END); + + smu7_copy_bytes_to_smc(hwmgr, + tmp, + (uint8_t *)&AVFS_meanNsigma, + sizeof(AVFS_meanNsigma_t), + SMC_RAM_END); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU74_Firmware_Header, AvfsSclkOffsetTable), + &tmp, SMC_RAM_END); + smu7_copy_bytes_to_smc(hwmgr, + tmp, + (uint8_t *)&AVFS_SclkOffset, + sizeof(AVFS_Sclk_Offset_t), + SMC_RAM_END); + + data->avfs_vdroop_override_setting = (avfs_params.ucEnableGB_VDROOP_TABLE_CKSON << BTCGB0_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_VDROOP_TABLE_CKSOFF << BTCGB1_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_FUSE_TABLE_CKSON << AVFSGB0_Vdroop_Enable_SHIFT) | + (avfs_params.ucEnableGB_FUSE_TABLE_CKSOFF << AVFSGB1_Vdroop_Enable_SHIFT); + data->apply_avfs_cks_off_voltage = (avfs_params.ucEnableApplyAVFS_CKS_OFF_Voltage == 1) ? true : false; + } + return result; +} + +static int polaris10_init_arb_table_index(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t tmp; + int result; + + /* This is a read-modify-write on the first byte of the ARB table. + * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure + * is the field 'current'. + * This solution is ugly, but we never write the whole table only + * individual fields in it. + * In reality this field should not be in that structure + * but in a soft register. + */ + result = smu7_read_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); + + if (result) + return result; + + tmp &= 0x00FFFFFF; + tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; + + return smu7_write_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); +} + +static void polaris10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (table_info && + table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && + table_info->cac_dtp_table->usPowerTuneDataSetID) + smu_data->power_tune_defaults = + &polaris10_power_tune_data_set_array + [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; + else + smu_data->power_tune_defaults = &polaris10_power_tune_data_set_array[0]; + +} + +static void polaris10_save_default_power_profile(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct SMU74_Discrete_GraphicsLevel *levels = + data->smc_state_table.GraphicsLevel; + unsigned min_level = 1; + + hwmgr->default_gfx_power_profile.activity_threshold = + be16_to_cpu(levels[0].ActivityLevel); + hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst; + hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst; + hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; + + hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; + + /* Workaround compute SDMA instability: disable lowest SCLK + * DPM level. Optimize compute power profile: Use only highest + * 2 power levels (if more than 2 are available), Hysteresis: + * 0ms up, 5ms down + */ + if (data->smc_state_table.GraphicsDpmLevelCount > 2) + min_level = data->smc_state_table.GraphicsDpmLevelCount - 2; + else if (data->smc_state_table.GraphicsDpmLevelCount == 2) + min_level = 1; + else + min_level = 0; + hwmgr->default_compute_power_profile.min_sclk = + be32_to_cpu(levels[min_level].SclkSetting.SclkFrequency); + hwmgr->default_compute_power_profile.up_hyst = 0; + hwmgr->default_compute_power_profile.down_hyst = 5; + + hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; +} + +static int polaris10_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *hw_data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct SMU74_Discrete_DpmTable *table = &(smu_data->smc_state_table); + uint8_t i; + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + pp_atomctrl_clock_dividers_vi dividers; + + polaris10_initialize_power_tune_defaults(hwmgr); + + if (SMU7_VOLTAGE_CONTROL_NONE != hw_data->voltage_control) + polaris10_populate_smc_voltage_tables(hwmgr, table); + + table->SystemFlags = 0; + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (hw_data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (hw_data->ulv_supported && table_info->us_ulv_voltage_offset) { + result = polaris10_populate_ulv_state(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, SMU7_CGULVPARAMETER_DFLT); + } + + result = polaris10_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result); + + result = polaris10_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result); + + result = polaris10_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result); + + result = polaris10_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result); + + result = polaris10_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result); + + result = polaris10_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize SAMU Level!", return result); + + /* Since only the initial state is completely set up at this point + * (the other states are just copies of the boot state) we only + * need to populate the ARB settings for the initial state. + */ + result = polaris10_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result); + + result = polaris10_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result); + + result = polaris10_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result); + + result = polaris10_populate_smc_initailial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot State!", return result); + + result = polaris10_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate BAPM Parameters!", return result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = polaris10_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate Clock Stretcher Data Table!", + return result); + } + + result = polaris10_populate_avfs_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, "Failed to populate AVFS Parameters!", return result;); + + table->CurrSclkPllRange = 0xff; + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + table_info->cac_dtp_table->usTargetOperatingTemp * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + table->PCIeBootLinkLevel = 0; + table->PCIeGenInterval = 1; + table->VRConfig = 0; + + result = polaris10_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate VRConfig setting!", return result); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, + &gpio_pin)) { + table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } else { + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + /* Thermal Output GPIO */ + if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, + &gpio_pin)) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; + + /* For porlarity read GPIOPAD_A with assigned Gpio pin + * since VBIOS will program this register to set 'inactive state', + * driver can then determine 'active state' from this and + * program SMU with correct polarity + */ + table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) + & (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_RegulatorHot) + && phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_CombinePCCWithThermalSignal)) + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } else { + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + /* Populate BIF_SCLK levels into SMC DPM table */ + for (i = 0; i <= hw_data->dpm_table.pcie_speed_table.count; i++) { + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, smu_data->bif_sclk_table[i], ÷rs); + PP_ASSERT_WITH_CODE((result == 0), "Can not find DFS divide id for Sclk", return result); + + if (i == 0) + table->Ulv.BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider)); + else + table->LinkLevel[i-1].BifSclkDfs = PP_HOST_TO_SMC_US((USHORT)(dividers.pll_post_divider)); + } + + for (i = 0; i < SMU74_MAX_ENTRIES_SMIO; i++) + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_UL(table->CurrSclkPllRange); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU74_Discrete_DpmTable) - 3 * sizeof(SMU74_PIDController), + SMC_RAM_END); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result); + + result = polaris10_init_arb_table_index(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload arb data to SMC memory!", return result); + + result = polaris10_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate PM fuses to SMC memory!", return result); + + polaris10_save_default_power_profile(hwmgr); + + return 0; +} + +static int polaris10_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return polaris10_program_memory_timing_parameters(hwmgr); + + return 0; +} + +int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr) +{ + int ret; + struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (smu_data->avfs.avfs_btc_status == AVFS_BTC_NOTSUPPORTED) + return 0; + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetGBDroopSettings, data->avfs_vdroop_override_setting); + + ret = (smum_send_msg_to_smc(hwmgr, PPSMC_MSG_EnableAvfs) == 0) ? + 0 : -1; + + if (!ret) + /* If this param is not changed, this function could fire unnecessarily */ + smu_data->avfs.avfs_btc_status = AVFS_BTC_COMPLETED_PREVIOUSLY; + + return ret; +} + +static int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + SMU74_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (smu_data->smu7_data.fan_table_start == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. + usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - + hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr-> + thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = smu7_get_xclk(hwmgr); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> + thermal_controller.advanceFanControlParameters.ulCycleDelay * + reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( + hwmgr->device, CGS_IND_REG__SMC, + CG_MULT_THERMAL_CTRL, TEMP_SEL); + + res = smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.fan_table_start, + (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), + SMC_RAM_END); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanMinPwm, + hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SetFanSclkTarget, + hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit); + + if (res) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + return 0; +} + +static int polaris10_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + smu_data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + smu_data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + offsetof(SMU74_Discrete_DpmTable, + UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); + return 0; +} + +static int polaris10_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smu_data->smc_state_table.VceBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + else + smu_data->smc_state_table.VceBootLevel = 0; + + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); + return 0; +} + +static int polaris10_update_samu_smc_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + + + smu_data->smc_state_table.SamuBootLevel = 0; + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, SamuBootLevel); + + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFFFFFF00; + mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SAMUDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); + return 0; +} + + +static int polaris10_update_bif_smc_table(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + int max_entry, i; + + max_entry = (SMU74_MAX_LEVELS_LINK < pcie_table->count) ? + SMU74_MAX_LEVELS_LINK : + pcie_table->count; + /* Setup BIF_SCLK levels */ + for (i = 0; i < max_entry; i++) + smu_data->bif_sclk_table[i] = pcie_table->entries[i].pcie_sclk; + return 0; +} + +static int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + polaris10_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + polaris10_update_vce_smc_table(hwmgr); + break; + case SMU_SAMU_TABLE: + polaris10_update_samu_smc_table(hwmgr); + break; + case SMU_BIF_TABLE: + polaris10_update_bif_smc_table(hwmgr); + default: + break; + } + return 0; +} + +static int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (hwmgr->gfx_arbiter.sclk_threshold != + data->low_sclk_interrupt_threshold)) { + data->low_sclk_interrupt_threshold = + hwmgr->gfx_arbiter.sclk_threshold; + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + PP_ASSERT_WITH_CODE((result == 0), + "Failed to update SCLK threshold!", return result); + + result = polaris10_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters!", + ); + + return result; +} + +static uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU74_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU74_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU74_SoftRegisters, AverageGraphicsActivity); + case PreVBlankGap: + return offsetof(SMU74_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU74_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU74_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU74_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + case SMU_Discrete_DpmTable: + switch (member) { + case UvdBootLevel: + return offsetof(SMU74_Discrete_DpmTable, UvdBootLevel); + case VceBootLevel: + return offsetof(SMU74_Discrete_DpmTable, VceBootLevel); + case SamuBootLevel: + return offsetof(SMU74_Discrete_DpmTable, SamuBootLevel); + case LowSclkInterruptThreshold: + return offsetof(SMU74_Discrete_DpmTable, LowSclkInterruptThreshold); + } + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t polaris10_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU74_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU74_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU74_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU74_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU74_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDGFX: + return SMU74_MAX_LEVELS_VDDGFX; + case SMU_MAX_LEVELS_VDDCI: + return SMU74_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU74_MAX_LEVELS_MVDD; + case SMU_UVD_MCLK_HANDSHAKE_DISABLE: + return SMU7_UVD_MCLK_HANDSHAKE_DISABLE; + } + + pr_warn("can't get the mac of %x\n", value); + return 0; +} + +static int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (0 == result) + smu_data->smu7_data.dpm_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (!result) { + data->soft_regs_start = tmp; + smu_data->smu7_data.soft_regs_start = tmp; + } + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.mc_reg_table_start = tmp; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.fan_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.arb_table_start = tmp; + + error |= (0 != result); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU74_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (!result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? -1 : 0; +} + +static bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *) + (hwmgr->smu_backend); + struct SMU74_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU74_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU74_Discrete_GraphicsLevel) * + SMU74_MAX_LEVELS_GRAPHICS; + uint32_t i; + + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + levels[i].ActivityLevel = + cpu_to_be16(request->activity_threshold); + levels[i].EnabledForActivity = 1; + levels[i].UpHyst = request->up_hyst; + levels[i].DownHyst = request->down_hyst; + } + + return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + array_size, SMC_RAM_END); +} + const struct pp_smumgr_func polaris10_smu_funcs = { .smu_init = polaris10_smu_init, .smu_fini = smu7_smu_fini, diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c index 2ae05bbdb974..7f5359a97ef2 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.c @@ -25,12 +25,13 @@ #include "pp_debug.h" #include "smumgr.h" #include "smu_ucode_xfer_vi.h" -#include "smu/smu_7_1_3_d.h" -#include "smu/smu_7_1_3_sh_mask.h" #include "ppatomctrl.h" #include "cgs_common.h" #include "smu7_ppsmc.h" #include "smu7_smumgr.h" +#include "smu7_common.h" + +#include "polaris10_pwrvirus.h" #define SMU7_SMC_SIZE 0x20000 @@ -513,7 +514,7 @@ static int smu7_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, uint32_t length PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); - PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be dividable by 4.", return -EINVAL); + PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL); return 0; } @@ -540,6 +541,47 @@ int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr) return result; } +static void execute_pwr_table(struct pp_hwmgr *hwmgr, const PWR_Command_Table *pvirus, int size) +{ + int i; + uint32_t reg, data; + + for (i = 0; i < size; i++) { + reg = pvirus->reg; + data = pvirus->data; + if (reg != 0xffffffff) + cgs_write_register(hwmgr->device, reg, data); + else + break; + pvirus++; + } +} + +static void execute_pwr_dfy_table(struct pp_hwmgr *hwmgr, const PWR_DFY_Section *section) +{ + int i; + + cgs_write_register(hwmgr->device, mmCP_DFY_CNTL, section->dfy_cntl); + cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_HI, section->dfy_addr_hi); + cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_LO, section->dfy_addr_lo); + for (i = 0; i < section->dfy_size; i++) + cgs_write_register(hwmgr->device, mmCP_DFY_DATA_0, section->dfy_data[i]); +} + +int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr) +{ + execute_pwr_table(hwmgr, pwr_virus_table_pre, ARRAY_SIZE(pwr_virus_table_pre)); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section1); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section2); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section3); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section4); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section5); + execute_pwr_dfy_table(hwmgr, &pwr_virus_section6); + execute_pwr_table(hwmgr, pwr_virus_table_post, ARRAY_SIZE(pwr_virus_table_post)); + + return 0; +} + int smu7_init(struct pp_hwmgr *hwmgr) { struct smu7_smumgr *smu_data; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h index 0b63c5c1043c..c87263bc0caa 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smu7_smumgr.h @@ -88,4 +88,6 @@ int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr); int smu7_init(struct pp_hwmgr *hwmgr); int smu7_smu_fini(struct pp_hwmgr *hwmgr); -#endif
\ No newline at end of file +int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr); + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c deleted file mode 100644 index 1f720ccdaf99..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.c +++ /dev/null @@ -1,3261 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * - */ - -#include "pp_debug.h" -#include "tonga_smc.h" -#include "smu7_dyn_defaults.h" - -#include "smu7_hwmgr.h" -#include "hardwaremanager.h" -#include "ppatomctrl.h" -#include "cgs_common.h" -#include "atombios.h" -#include "tonga_smumgr.h" -#include "pppcielanes.h" -#include "pp_endian.h" -#include "smu7_ppsmc.h" - -#include "smu72_discrete.h" - -#include "smu/smu_7_1_2_d.h" -#include "smu/smu_7_1_2_sh_mask.h" - -#include "gmc/gmc_8_1_d.h" -#include "gmc/gmc_8_1_sh_mask.h" - -#include "bif/bif_5_0_d.h" -#include "bif/bif_5_0_sh_mask.h" - -#include "dce/dce_10_0_d.h" -#include "dce/dce_10_0_sh_mask.h" - - -#define VOLTAGE_SCALE 4 -#define POWERTUNE_DEFAULT_SET_MAX 1 -#define VOLTAGE_VID_OFFSET_SCALE1 625 -#define VOLTAGE_VID_OFFSET_SCALE2 100 -#define MC_CG_ARB_FREQ_F1 0x0b -#define VDDC_VDDCI_DELTA 200 - - -static const struct tonga_pt_defaults tonga_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { -/* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, - * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT - */ - {1, 0xF, 0xFD, 0x19, - 5, 45, 0, 0xB0000, - {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, - 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, - {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, - 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4} - }, -}; - -/* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */ -static const uint16_t tonga_clock_stretcher_lookup_table[2][4] = { - {600, 1050, 3, 0}, - {600, 1050, 6, 1} -}; - -/* [FF, SS] type, [] 4 voltage ranges, - * and [Floor Freq, Boundary Freq, VID min , VID max] - */ -static const uint32_t tonga_clock_stretcher_ddt_table[2][4][4] = { - { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, - { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } -}; - -/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */ -static const uint8_t tonga_clock_stretch_amount_conversion[2][6] = { - {0, 1, 3, 2, 4, 5}, - {0, 2, 4, 5, 6, 5} -}; - -/* PPGen has the gain setting generated in x * 100 unit - * This function is to convert the unit to x * 4096(0x1000) unit. - * This is the unit expected by SMC firmware - */ - - -static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, - phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table, - uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) -{ - uint32_t i = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - /* clock - voltage dependency table is empty table */ - if (allowed_clock_voltage_table->count == 0) - return -EINVAL; - - for (i = 0; i < allowed_clock_voltage_table->count; i++) { - /* find first sclk bigger than request */ - if (allowed_clock_voltage_table->entries[i].clk >= clock) { - voltage->VddGfx = phm_get_voltage_index( - pptable_info->vddgfx_lookup_table, - allowed_clock_voltage_table->entries[i].vddgfx); - voltage->Vddc = phm_get_voltage_index( - pptable_info->vddc_lookup_table, - allowed_clock_voltage_table->entries[i].vddc); - - if (allowed_clock_voltage_table->entries[i].vddci) - voltage->Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, allowed_clock_voltage_table->entries[i].vddci); - else - voltage->Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - allowed_clock_voltage_table->entries[i].vddc - VDDC_VDDCI_DELTA); - - - if (allowed_clock_voltage_table->entries[i].mvdd) - *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd; - - voltage->Phases = 1; - return 0; - } - } - - /* sclk is bigger than max sclk in the dependence table */ - voltage->VddGfx = phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - allowed_clock_voltage_table->entries[i-1].vddgfx); - voltage->Vddc = phm_get_voltage_index(pptable_info->vddc_lookup_table, - allowed_clock_voltage_table->entries[i-1].vddc); - - if (allowed_clock_voltage_table->entries[i-1].vddci) - voltage->Vddci = phm_get_voltage_id(&data->vddci_voltage_table, - allowed_clock_voltage_table->entries[i-1].vddci); - - if (allowed_clock_voltage_table->entries[i-1].mvdd) - *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd; - - return 0; -} - - -/** - * Vddc table preparation for SMC. - * - * @param hwmgr the address of the hardware manager - * @param table the SMC DPM table structure to be populated - * @return always 0 - */ -static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - unsigned int count; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - table->VddcLevelCount = data->vddc_voltage_table.count; - for (count = 0; count < table->VddcLevelCount; count++) { - table->VddcTable[count] = - PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE); - } - CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); - } - return 0; -} - -/** - * VddGfx table preparation for SMC. - * - * @param hwmgr the address of the hardware manager - * @param table the SMC DPM table structure to be populated - * @return always 0 - */ -static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - unsigned int count; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { - table->VddGfxLevelCount = data->vddgfx_voltage_table.count; - for (count = 0; count < data->vddgfx_voltage_table.count; count++) { - table->VddGfxTable[count] = - PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE); - } - CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount); - } - return 0; -} - -/** - * Vddci table preparation for SMC. - * - * @param *hwmgr The address of the hardware manager. - * @param *table The SMC DPM table structure to be populated. - * @return 0 - */ -static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - - table->VddciLevelCount = data->vddci_voltage_table.count; - for (count = 0; count < table->VddciLevelCount; count++) { - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - table->VddciTable[count] = - PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - table->SmioTable1.Pattern[count].Voltage = - PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); - /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */ - table->SmioTable1.Pattern[count].Smio = - (uint8_t) count; - table->Smio[count] |= - data->vddci_voltage_table.entries[count].smio_low; - table->VddciTable[count] = - PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); - } - } - - table->SmioMask1 = data->vddci_voltage_table.mask_low; - CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); - - return 0; -} - -/** - * Mvdd table preparation for SMC. - * - * @param *hwmgr The address of the hardware manager. - * @param *table The SMC DPM table structure to be populated. - * @return 0 - */ -static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t count; - - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - table->MvddLevelCount = data->mvdd_voltage_table.count; - for (count = 0; count < table->MvddLevelCount; count++) { - table->SmioTable2.Pattern[count].Voltage = - PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); - /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ - table->SmioTable2.Pattern[count].Smio = - (uint8_t) count; - table->Smio[count] |= - data->mvdd_voltage_table.entries[count].smio_low; - } - table->SmioMask2 = data->mvdd_voltage_table.mask_low; - - CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); - } - - return 0; -} - -/** - * Preparation of vddc and vddgfx CAC tables for SMC. - * - * @param hwmgr the address of the hardware manager - * @param table the SMC DPM table structure to be populated - * @return always 0 - */ -static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - uint32_t count; - uint8_t index = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table = - pptable_info->vddgfx_lookup_table; - struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table = - pptable_info->vddc_lookup_table; - - /* table is already swapped, so in order to use the value from it - * we need to swap it back. - */ - uint32_t vddc_level_count = PP_SMC_TO_HOST_UL(table->VddcLevelCount); - uint32_t vddgfx_level_count = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount); - - for (count = 0; count < vddc_level_count; count++) { - /* We are populating vddc CAC data to BapmVddc table in split and merged mode */ - index = phm_get_voltage_index(vddc_lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddcVidLoSidd[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); - table->BapmVddcVidHiSidd[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); - table->BapmVddcVidHiSidd2[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); - } - - if ((data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2)) { - /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */ - for (count = 0; count < vddgfx_level_count; count++) { - index = phm_get_voltage_index(vddgfx_lookup_table, - convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid)); - table->BapmVddGfxVidHiSidd2[count] = - convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high); - } - } else { - for (count = 0; count < vddc_level_count; count++) { - index = phm_get_voltage_index(vddc_lookup_table, - data->vddc_voltage_table.entries[count].value); - table->BapmVddGfxVidLoSidd[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); - table->BapmVddGfxVidHiSidd[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); - table->BapmVddGfxVidHiSidd2[count] = - convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); - } - } - - return 0; -} - -/** - * Preparation of voltage tables for SMC. - * - * @param hwmgr the address of the hardware manager - * @param table the SMC DPM table structure to be populated - * @return always 0 - */ - -static int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result; - - result = tonga_populate_smc_vddc_table(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate VDDC voltage table to SMC", - return -EINVAL); - - result = tonga_populate_smc_vdd_ci_table(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate VDDCI voltage table to SMC", - return -EINVAL); - - result = tonga_populate_smc_vdd_gfx_table(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate VDDGFX voltage table to SMC", - return -EINVAL); - - result = tonga_populate_smc_mvdd_table(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate MVDD voltage table to SMC", - return -EINVAL); - - result = tonga_populate_cac_tables(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "can not populate CAC voltage tables to SMC", - return -EINVAL); - - return 0; -} - -static int tonga_populate_ulv_level(struct pp_hwmgr *hwmgr, - struct SMU72_Discrete_Ulv *state) -{ - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - state->CcPwrDynRm = 0; - state->CcPwrDynRm1 = 0; - - state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; - state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * - VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); - - state->VddcPhase = 1; - - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); - CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); - - return 0; -} - -static int tonga_populate_ulv_state(struct pp_hwmgr *hwmgr, - struct SMU72_Discrete_DpmTable *table) -{ - return tonga_populate_ulv_level(hwmgr, &table->Ulv); -} - -static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t i; - - /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ - for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { - table->LinkLevel[i].PcieGenSpeed = - (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; - table->LinkLevel[i].PcieLaneCount = - (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); - table->LinkLevel[i].EnabledForActivity = - 1; - table->LinkLevel[i].SPC = - (uint8_t)(data->pcie_spc_cap & 0xff); - table->LinkLevel[i].DownThreshold = - PP_HOST_TO_SMC_UL(5); - table->LinkLevel[i].UpThreshold = - PP_HOST_TO_SMC_UL(30); - } - - smu_data->smc_state_table.LinkLevelCount = - (uint8_t)dpm_table->pcie_speed_table.count; - data->dpm_level_enable_mask.pcie_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); - - return 0; -} - -/** - * Calculates the SCLK dividers using the provided engine clock - * - * @param hwmgr the address of the hardware manager - * @param engine_clock the engine clock to use to populate the structure - * @param sclk the SMC SCLK structure to be populated - */ -static int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr, - uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - pp_atomctrl_clock_dividers_vi dividers; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - uint32_t reference_clock; - uint32_t reference_divider; - uint32_t fbdiv; - int result; - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", return result); - - /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ - reference_clock = atomctrl_get_reference_clock(hwmgr); - - reference_divider = 1 + dividers.uc_pll_ref_div; - - /* low 14 bits is fraction and high 12 bits is divider*/ - fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; - - /* SPLL_FUNC_CNTL setup*/ - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, - CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); - - /* SPLL_FUNC_CNTL_3 setup*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, - CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); - - /* set to use fractional accumulation*/ - spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, - CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { - pp_atomctrl_internal_ss_info ss_info; - - uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; - if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { - /* - * ss_info.speed_spectrum_percentage -- in unit of 0.01% - * ss_info.speed_spectrum_rate -- in unit of khz - */ - /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ - uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); - - /* clkv = 2 * D * fbdiv / NS */ - uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); - - cg_spll_spread_spectrum = - PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); - cg_spll_spread_spectrum = - PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); - cg_spll_spread_spectrum_2 = - PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); - } - } - - sclk->SclkFrequency = engine_clock; - sclk->CgSpllFuncCntl3 = spll_func_cntl_3; - sclk->CgSpllFuncCntl4 = spll_func_cntl_4; - sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; - sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; - sclk->SclkDid = (uint8_t)dividers.pll_post_divider; - - return 0; -} - -/** - * Populates single SMC SCLK structure using the provided engine clock - * - * @param hwmgr the address of the hardware manager - * @param engine_clock the engine clock to use to populate the structure - * @param sclk the SMC SCLK structure to be populated - */ -static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint16_t sclk_activity_level_threshold, - SMU72_Discrete_GraphicsLevel *graphic_level) -{ - int result; - uint32_t mvdd; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level); - - /* populate graphics levels*/ - result = tonga_get_dependency_volt_by_clk(hwmgr, - pptable_info->vdd_dep_on_sclk, engine_clock, - &graphic_level->MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE((!result), - "can not find VDDC voltage value for VDDC " - "engine clock dependency table", return result); - - /* SCLK frequency in units of 10KHz*/ - graphic_level->SclkFrequency = engine_clock; - /* Indicates maximum activity level for this performance level. 50% for now*/ - graphic_level->ActivityLevel = sclk_activity_level_threshold; - - graphic_level->CcPwrDynRm = 0; - graphic_level->CcPwrDynRm1 = 0; - /* this level can be used if activity is high enough.*/ - graphic_level->EnabledForActivity = 0; - /* this level can be used for throttling.*/ - graphic_level->EnabledForThrottle = 1; - graphic_level->UpHyst = 0; - graphic_level->DownHyst = 0; - graphic_level->VoltageDownHyst = 0; - graphic_level->PowerThrottle = 0; - - data->display_timing.min_clock_in_sr = - hwmgr->display_config.min_core_set_clock_in_sr; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkDeepSleep)) - graphic_level->DeepSleepDivId = - smu7_get_sleep_divider_id_from_clock(engine_clock, - data->display_timing.min_clock_in_sr); - - /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ - graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - if (!result) { - /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/ - /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/ - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); - } - - return result; -} - -/** - * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states - * - * @param hwmgr the address of the hardware manager - */ -int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - struct phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table; - uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count; - uint32_t level_array_address = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); - - uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) * - SMU72_MAX_LEVELS_GRAPHICS; - - SMU72_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; - - uint32_t i, max_entry; - uint8_t highest_pcie_level_enabled = 0; - uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; - uint8_t count = 0; - int result = 0; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->sclk_table.count; i++) { - result = tonga_populate_single_graphic_level(hwmgr, - dpm_table->sclk_table.dpm_levels[i].value, - (uint16_t)smu_data->activity_target[i], - &(smu_data->smc_state_table.GraphicsLevel[i])); - if (result != 0) - return result; - - /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ - if (i > 1) - smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; - } - - /* Only enable level 0 for now. */ - smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; - - /* set highest level watermark to high */ - if (dpm_table->sclk_table.count > 1) - smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = - PPSMC_DISPLAY_WATERMARK_HIGH; - - smu_data->smc_state_table.GraphicsDpmLevelCount = - (uint8_t)dpm_table->sclk_table.count; - data->dpm_level_enable_mask.sclk_dpm_enable_mask = - phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); - - if (pcie_table != NULL) { - PP_ASSERT_WITH_CODE((pcie_entry_count >= 1), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - max_entry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/ - for (i = 0; i < dpm_table->sclk_table.count; i++) { - smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = - (uint8_t) ((i < max_entry) ? i : max_entry); - } - } else { - if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask) - pr_err("Pcie Dpm Enablemask is 0 !"); - - while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1<<(highest_pcie_level_enabled+1))) != 0)) { - highest_pcie_level_enabled++; - } - - while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1<<lowest_pcie_level_enabled)) == 0)) { - lowest_pcie_level_enabled++; - } - - while ((count < highest_pcie_level_enabled) && - ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & - (1<<(lowest_pcie_level_enabled+1+count))) == 0)) { - count++; - } - mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? - (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; - - - /* set pcieDpmLevel to highest_pcie_level_enabled*/ - for (i = 2; i < dpm_table->sclk_table.count; i++) - smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; - - /* set pcieDpmLevel to lowest_pcie_level_enabled*/ - smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; - - /* set pcieDpmLevel to mid_pcie_level_enabled*/ - smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; - } - /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr, level_array_address, - (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -/** - * Populates the SMC MCLK structure using the provided memory clock - * - * @param hwmgr the address of the hardware manager - * @param memory_clock the memory clock to use to populate the structure - * @param sclk the SMC SCLK structure to be populated - */ -static int tonga_calculate_mclk_params( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU72_Discrete_MemoryLevel *mclk, - bool strobe_mode, - bool dllStateOn - ) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; - uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; - uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; - uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; - uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; - uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; - uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; - - pp_atomctrl_memory_clock_param mpll_param; - int result; - - result = atomctrl_get_memory_pll_dividers_si(hwmgr, - memory_clock, &mpll_param, strobe_mode); - PP_ASSERT_WITH_CODE( - !result, - "Error retrieving Memory Clock Parameters from VBIOS.", - return result); - - /* MPLL_FUNC_CNTL setup*/ - mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, - mpll_param.bw_ctrl); - - /* MPLL_FUNC_CNTL_1 setup*/ - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKF, - mpll_param.mpll_fb_divider.cl_kf); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, CLKFRAC, - mpll_param.mpll_fb_divider.clk_frac); - mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, - MPLL_FUNC_CNTL_1, VCO_MODE, - mpll_param.vco_mode); - - /* MPLL_AD_FUNC_CNTL setup*/ - mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, - MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, - mpll_param.mpll_post_divider); - - if (data->is_memory_gddr5) { - /* MPLL_DQ_FUNC_CNTL setup*/ - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_SEL, - mpll_param.yclk_sel); - mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, - MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, - mpll_param.mpll_post_divider); - } - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { - /* - ************************************ - Fref = Reference Frequency - NF = Feedback divider ratio - NR = Reference divider ratio - Fnom = Nominal VCO output frequency = Fref * NF / NR - Fs = Spreading Rate - D = Percentage down-spread / 2 - Fint = Reference input frequency to PFD = Fref / NR - NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) - CLKS = NS - 1 = ISS_STEP_NUM[11:0] - NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) - CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] - ************************************* - */ - pp_atomctrl_internal_ss_info ss_info; - uint32_t freq_nom; - uint32_t tmp; - uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); - - /* for GDDR5 for all modes and DDR3 */ - if (1 == mpll_param.qdr) - freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); - else - freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); - - /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ - tmp = (freq_nom / reference_clock); - tmp = tmp * tmp; - - if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { - /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ - /* ss.Info.speed_spectrum_rate -- in unit of khz */ - /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ - /* = reference_clock * 5 / speed_spectrum_rate */ - uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; - - /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ - /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ - uint32_t clkv = - (uint32_t)((((131 * ss_info.speed_spectrum_percentage * - ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); - - mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); - mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); - } - } - - /* MCLK_PWRMGT_CNTL setup */ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); - - /* Save the result data to outpupt memory level structure */ - mclk->MclkFrequency = memory_clock; - mclk->MpllFuncCntl = mpll_func_cntl; - mclk->MpllFuncCntl_1 = mpll_func_cntl_1; - mclk->MpllFuncCntl_2 = mpll_func_cntl_2; - mclk->MpllAdFuncCntl = mpll_ad_func_cntl; - mclk->MpllDqFuncCntl = mpll_dq_func_cntl; - mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; - mclk->DllCntl = dll_cntl; - mclk->MpllSs1 = mpll_ss1; - mclk->MpllSs2 = mpll_ss2; - - return 0; -} - -static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock, - bool strobe_mode) -{ - uint8_t mc_para_index; - - if (strobe_mode) { - if (memory_clock < 12500) - mc_para_index = 0x00; - else if (memory_clock > 47500) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); - } else { - if (memory_clock < 65000) - mc_para_index = 0x00; - else if (memory_clock > 135000) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); - } - - return mc_para_index; -} - -static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) -{ - uint8_t mc_para_index; - - if (memory_clock < 10000) - mc_para_index = 0; - else if (memory_clock >= 80000) - mc_para_index = 0x0f; - else - mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); - - return mc_para_index; -} - - -static int tonga_populate_single_memory_level( - struct pp_hwmgr *hwmgr, - uint32_t memory_clock, - SMU72_Discrete_MemoryLevel *memory_level - ) -{ - uint32_t mvdd = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - int result = 0; - bool dll_state_on; - struct cgs_display_info info = {0}; - uint32_t mclk_edc_wr_enable_threshold = 40000; - uint32_t mclk_stutter_mode_threshold = 30000; - uint32_t mclk_edc_enable_threshold = 40000; - uint32_t mclk_strobe_mode_threshold = 40000; - - if (NULL != pptable_info->vdd_dep_on_mclk) { - result = tonga_get_dependency_volt_by_clk(hwmgr, - pptable_info->vdd_dep_on_mclk, - memory_clock, - &memory_level->MinVoltage, &mvdd); - PP_ASSERT_WITH_CODE( - !result, - "can not find MinVddc voltage value from memory VDDC " - "voltage dependency table", - return result); - } - - if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE) - memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value; - else - memory_level->MinMvdd = mvdd; - - memory_level->EnabledForThrottle = 1; - memory_level->EnabledForActivity = 0; - memory_level->UpHyst = 0; - memory_level->DownHyst = 100; - memory_level->VoltageDownHyst = 0; - - /* Indicates maximum activity level for this performance level.*/ - memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target; - memory_level->StutterEnable = 0; - memory_level->StrobeEnable = 0; - memory_level->EdcReadEnable = 0; - memory_level->EdcWriteEnable = 0; - memory_level->RttEnable = 0; - - /* default set to low watermark. Highest level will be set to high later.*/ - memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - - cgs_get_active_displays_info(hwmgr->device, &info); - data->display_timing.num_existing_displays = info.display_count; - - if ((mclk_stutter_mode_threshold != 0) && - (memory_clock <= mclk_stutter_mode_threshold) && - (!data->is_uvd_enabled) - && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1) - && (data->display_timing.num_existing_displays <= 2) - && (data->display_timing.num_existing_displays != 0)) - memory_level->StutterEnable = 1; - - /* decide strobe mode*/ - memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && - (memory_clock <= mclk_strobe_mode_threshold); - - /* decide EDC mode and memory clock ratio*/ - if (data->is_memory_gddr5) { - memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock, - memory_level->StrobeEnable); - - if ((mclk_edc_enable_threshold != 0) && - (memory_clock > mclk_edc_enable_threshold)) { - memory_level->EdcReadEnable = 1; - } - - if ((mclk_edc_wr_enable_threshold != 0) && - (memory_clock > mclk_edc_wr_enable_threshold)) { - memory_level->EdcWriteEnable = 1; - } - - if (memory_level->StrobeEnable) { - if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >= - ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) { - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - } else { - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; - } - - } else { - dll_state_on = data->dll_default_on; - } - } else { - memory_level->StrobeRatio = - tonga_get_ddr3_mclk_frequency_ratio(memory_clock); - dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; - } - - result = tonga_calculate_mclk_params(hwmgr, - memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); - - if (!result) { - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd); - /* MCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); - /* Indicates maximum activity level for this performance level.*/ - CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); - CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); - } - - return result; -} - -int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - struct smu7_dpm_table *dpm_table = &data->dpm_table; - int result; - - /* populate MCLK dpm table to SMU7 */ - uint32_t level_array_address = - smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, MemoryLevel); - uint32_t level_array_size = - sizeof(SMU72_Discrete_MemoryLevel) * - SMU72_MAX_LEVELS_MEMORY; - SMU72_Discrete_MemoryLevel *levels = - smu_data->smc_state_table.MemoryLevel; - uint32_t i; - - memset(levels, 0x00, level_array_size); - - for (i = 0; i < dpm_table->mclk_table.count; i++) { - PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), - "can not populate memory level as memory clock is zero", - return -EINVAL); - result = tonga_populate_single_memory_level( - hwmgr, - dpm_table->mclk_table.dpm_levels[i].value, - &(smu_data->smc_state_table.MemoryLevel[i])); - if (result) - return result; - } - - /* Only enable level 0 for now.*/ - smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; - - /* - * in order to prevent MC activity from stutter mode to push DPM up. - * the UVD change complements this by putting the MCLK in a higher state - * by default such that we are not effected by up threshold or and MCLK DPM latency. - */ - smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); - - smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; - data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); - /* set highest level watermark to high*/ - smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; - - /* level count will send to smc once at init smc table and never change*/ - result = smu7_copy_bytes_to_smc(hwmgr, - level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, - SMC_RAM_END); - - return result; -} - -static int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr, - uint32_t mclk, SMIO_Pattern *smio_pattern) -{ - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint32_t i = 0; - - if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { - /* find mvdd value which clock is more than request */ - for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { - if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { - /* Always round to higher voltage. */ - smio_pattern->Voltage = - data->mvdd_voltage_table.entries[i].value; - break; - } - } - - PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, - "MVDD Voltage is outside the supported range.", - return -EINVAL); - } else { - return -EINVAL; - } - - return 0; -} - - -static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct pp_atomctrl_clock_dividers_vi dividers; - - SMIO_Pattern voltage_level; - uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; - uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; - uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; - uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; - - /* The ACPI state should not do DPM on DC (or ever).*/ - table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; - - table->ACPILevel.MinVoltage = - smu_data->smc_state_table.GraphicsLevel[0].MinVoltage; - - /* assign zero for now*/ - table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); - - /* get the engine clock dividers for this clock value*/ - result = atomctrl_get_engine_pll_dividers_vi(hwmgr, - table->ACPILevel.SclkFrequency, ÷rs); - - PP_ASSERT_WITH_CODE(result == 0, - "Error retrieving Engine Clock dividers from VBIOS.", - return result); - - /* divider ID for required SCLK*/ - table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; - table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; - table->ACPILevel.DeepSleepDivId = 0; - - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_PWRON, 0); - spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, - SPLL_RESET, 1); - spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, - SCLK_MUX_SEL, 4); - - table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; - table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; - table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; - table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; - table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; - table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; - table->ACPILevel.CcPwrDynRm = 0; - table->ACPILevel.CcPwrDynRm1 = 0; - - - /* For various features to be enabled/disabled while this level is active.*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); - /* SCLK frequency in units of 10KHz*/ - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); - CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); - - /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ - table->MemoryACPILevel.MinVoltage = - smu_data->smc_state_table.MemoryLevel[0].MinVoltage; - - /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/ - - if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level)) - table->MemoryACPILevel.MinMvdd = - PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); - else - table->MemoryACPILevel.MinMvdd = 0; - - /* Force reset on DLL*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); - - /* Disable DLL in ACPIState*/ - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); - mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, - MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); - - /* Enable DLL bypass signal*/ - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK0_BYPASS, 0); - dll_cntl = PHM_SET_FIELD(dll_cntl, - DLL_CNTL, MRDCK1_BYPASS, 0); - - table->MemoryACPILevel.DllCntl = - PP_HOST_TO_SMC_UL(dll_cntl); - table->MemoryACPILevel.MclkPwrmgtCntl = - PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); - table->MemoryACPILevel.MpllAdFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); - table->MemoryACPILevel.MpllDqFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); - table->MemoryACPILevel.MpllFuncCntl_1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); - table->MemoryACPILevel.MpllFuncCntl_2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); - table->MemoryACPILevel.MpllSs1 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); - table->MemoryACPILevel.MpllSs2 = - PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); - - table->MemoryACPILevel.EnabledForThrottle = 0; - table->MemoryACPILevel.EnabledForActivity = 0; - table->MemoryACPILevel.UpHyst = 0; - table->MemoryACPILevel.DownHyst = 100; - table->MemoryACPILevel.VoltageDownHyst = 0; - /* Indicates maximum activity level for this performance level.*/ - table->MemoryACPILevel.ActivityLevel = - PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); - - table->MemoryACPILevel.StutterEnable = 0; - table->MemoryACPILevel.StrobeEnable = 0; - table->MemoryACPILevel.EdcReadEnable = 0; - table->MemoryACPILevel.EdcWriteEnable = 0; - table->MemoryACPILevel.RttEnable = 0; - - return result; -} - -static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - - uint8_t count; - pp_atomctrl_clock_dividers_vi dividers; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - pptable_info->mm_dep_table; - - table->UvdLevelCount = (uint8_t) (mm_table->count); - table->UvdBootLevel = 0; - - for (count = 0; count < table->UvdLevelCount; count++) { - table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; - table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; - table->UvdLevel[count].MinVoltage.Vddc = - phm_get_voltage_index(pptable_info->vddc_lookup_table, - mm_table->entries[count].vddc); - table->UvdLevel[count].MinVoltage.VddGfx = - (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? - phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - mm_table->entries[count].vddgfx) : 0; - table->UvdLevel[count].MinVoltage.Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - table->UvdLevel[count].MinVoltage.Phases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi( - hwmgr, - table->UvdLevel[count].VclkFrequency, - ÷rs); - - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for Vclk clock", - return result); - - table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; - - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->UvdLevel[count].DclkFrequency, ÷rs); - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for Dclk clock", - return result); - - table->UvdLevel[count].DclkDivider = - (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); - CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); - } - - return result; - -} - -static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - - uint8_t count; - pp_atomctrl_clock_dividers_vi dividers; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - pptable_info->mm_dep_table; - - table->VceLevelCount = (uint8_t) (mm_table->count); - table->VceBootLevel = 0; - - for (count = 0; count < table->VceLevelCount; count++) { - table->VceLevel[count].Frequency = - mm_table->entries[count].eclk; - table->VceLevel[count].MinVoltage.Vddc = - phm_get_voltage_index(pptable_info->vddc_lookup_table, - mm_table->entries[count].vddc); - table->VceLevel[count].MinVoltage.VddGfx = - (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? - phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - mm_table->entries[count].vddgfx) : 0; - table->VceLevel[count].MinVoltage.Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - table->VceLevel[count].MinVoltage.Phases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->VceLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for VCE engine clock", - return result); - - table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); - } - - return result; -} - -static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - uint8_t count; - pp_atomctrl_clock_dividers_vi dividers; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - pptable_info->mm_dep_table; - - table->AcpLevelCount = (uint8_t) (mm_table->count); - table->AcpBootLevel = 0; - - for (count = 0; count < table->AcpLevelCount; count++) { - table->AcpLevel[count].Frequency = - pptable_info->mm_dep_table->entries[count].aclk; - table->AcpLevel[count].MinVoltage.Vddc = - phm_get_voltage_index(pptable_info->vddc_lookup_table, - mm_table->entries[count].vddc); - table->AcpLevel[count].MinVoltage.VddGfx = - (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? - phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - mm_table->entries[count].vddgfx) : 0; - table->AcpLevel[count].MinVoltage.Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - table->AcpLevel[count].MinVoltage.Phases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->AcpLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for engine clock", return result); - - table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); - } - - return result; -} - -static int tonga_populate_smc_samu_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - uint8_t count; - pp_atomctrl_clock_dividers_vi dividers; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct phm_ppt_v1_information *pptable_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = - pptable_info->mm_dep_table; - - table->SamuBootLevel = 0; - table->SamuLevelCount = (uint8_t) (mm_table->count); - - for (count = 0; count < table->SamuLevelCount; count++) { - /* not sure whether we need evclk or not */ - table->SamuLevel[count].Frequency = - pptable_info->mm_dep_table->entries[count].samclock; - table->SamuLevel[count].MinVoltage.Vddc = - phm_get_voltage_index(pptable_info->vddc_lookup_table, - mm_table->entries[count].vddc); - table->SamuLevel[count].MinVoltage.VddGfx = - (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? - phm_get_voltage_index(pptable_info->vddgfx_lookup_table, - mm_table->entries[count].vddgfx) : 0; - table->SamuLevel[count].MinVoltage.Vddci = - phm_get_voltage_id(&data->vddci_voltage_table, - mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); - table->SamuLevel[count].MinVoltage.Phases = 1; - - /* retrieve divider value for VBIOS */ - result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, - table->SamuLevel[count].Frequency, ÷rs); - PP_ASSERT_WITH_CODE((!result), - "can not find divide id for samu clock", return result); - - table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; - - CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); - } - - return result; -} - -static int tonga_populate_memory_timing_parameters( - struct pp_hwmgr *hwmgr, - uint32_t engine_clock, - uint32_t memory_clock, - struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs - ) -{ - uint32_t dramTiming; - uint32_t dramTiming2; - uint32_t burstTime; - int result; - - result = atomctrl_set_engine_dram_timings_rv770(hwmgr, - engine_clock, memory_clock); - - PP_ASSERT_WITH_CODE(result == 0, - "Error calling VBIOS to set DRAM_TIMING.", return result); - - dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); - dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); - burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); - - arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); - arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); - arb_regs->McArbBurstTime = (uint8_t)burstTime; - - return 0; -} - -/** - * Setup parameters for the MC ARB. - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - * This function is to be called from the SetPowerState table. - */ -static int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - int result = 0; - SMU72_Discrete_MCArbDramTimingTable arb_regs; - uint32_t i, j; - - memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable)); - - for (i = 0; i < data->dpm_table.sclk_table.count; i++) { - for (j = 0; j < data->dpm_table.mclk_table.count; j++) { - result = tonga_populate_memory_timing_parameters - (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, - data->dpm_table.mclk_table.dpm_levels[j].value, - &arb_regs.entries[i][j]); - - if (result) - break; - } - } - - if (!result) { - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.arb_table_start, - (uint8_t *)&arb_regs, - sizeof(SMU72_Discrete_MCArbDramTimingTable), - SMC_RAM_END - ); - } - - return result; -} - -static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - table->GraphicsBootLevel = 0; - table->MemoryBootLevel = 0; - - /* find boot level from dpm table*/ - result = phm_find_boot_level(&(data->dpm_table.sclk_table), - data->vbios_boot_state.sclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); - - if (result != 0) { - smu_data->smc_state_table.GraphicsBootLevel = 0; - pr_err("[powerplay] VBIOS did not find boot engine " - "clock value in dependency table. " - "Using Graphics DPM level 0 !"); - result = 0; - } - - result = phm_find_boot_level(&(data->dpm_table.mclk_table), - data->vbios_boot_state.mclk_bootup_value, - (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); - - if (result != 0) { - smu_data->smc_state_table.MemoryBootLevel = 0; - pr_err("[powerplay] VBIOS did not find boot " - "engine clock value in dependency table." - "Using Memory DPM level 0 !"); - result = 0; - } - - table->BootVoltage.Vddc = - phm_get_voltage_id(&(data->vddc_voltage_table), - data->vbios_boot_state.vddc_bootup_value); - table->BootVoltage.VddGfx = - phm_get_voltage_id(&(data->vddgfx_voltage_table), - data->vbios_boot_state.vddgfx_bootup_value); - table->BootVoltage.Vddci = - phm_get_voltage_id(&(data->vddci_voltage_table), - data->vbios_boot_state.vddci_bootup_value); - table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; - - CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); - - return result; -} - -static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) -{ - uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, - volt_with_cks, value; - uint16_t clock_freq_u16; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, - volt_offset = 0; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = - table_info->vdd_dep_on_sclk; - uint32_t hw_revision, dev_id; - struct cgs_system_info sys_info = {0}; - - stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; - - sys_info.size = sizeof(struct cgs_system_info); - - sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV; - cgs_query_system_info(hwmgr->device, &sys_info); - hw_revision = (uint32_t)sys_info.value; - - sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; - cgs_query_system_info(hwmgr->device, &sys_info); - dev_id = (uint32_t)sys_info.value; - - /* Read SMU_Eefuse to read and calculate RO and determine - * if the part is SS or FF. if RO >= 1660MHz, part is FF. - */ - efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (146 * 4)); - efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixSMU_EFUSE_0 + (148 * 4)); - efuse &= 0xFF000000; - efuse = efuse >> 24; - efuse2 &= 0xF; - - if (efuse2 == 1) - ro = (2300 - 1350) * efuse / 255 + 1350; - else - ro = (2500 - 1000) * efuse / 255 + 1000; - - if (ro >= 1660) - type = 0; - else - type = 1; - - /* Populate Stretch amount */ - smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; - - - /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ - for (i = 0; i < sclk_table->count; i++) { - smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= - sclk_table->entries[i].cks_enable << i; - if (ASICID_IS_TONGA_P(dev_id, hw_revision)) { - volt_without_cks = (uint32_t)((7732 + 60 - ro - 20838 * - (sclk_table->entries[i].clk/100) / 10000) * 1000 / - (8730 - (5301 * (sclk_table->entries[i].clk/100) / 1000))); - volt_with_cks = (uint32_t)((5250 + 51 - ro - 2404 * - (sclk_table->entries[i].clk/100) / 100000) * 1000 / - (6146 - (3193 * (sclk_table->entries[i].clk/100) / 1000))); - } else { - volt_without_cks = (uint32_t)((14041 * - (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / - (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); - volt_with_cks = (uint32_t)((13946 * - (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / - (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); - } - if (volt_without_cks >= volt_with_cks) - volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + - sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); - smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; - } - - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - STRETCH_ENABLE, 0x0); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - masterReset, 0x1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - staticEnable, 0x1); - PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, - masterReset, 0x0); - - /* Populate CKS Lookup Table */ - if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) - stretch_amount2 = 0; - else if (stretch_amount == 3 || stretch_amount == 4) - stretch_amount2 = 1; - else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher); - PP_ASSERT_WITH_CODE(false, - "Stretch Amount in PPTable not supported\n", - return -EINVAL); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL); - value &= 0xFFC2FF87; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = - tonga_clock_stretcher_lookup_table[stretch_amount2][0]; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = - tonga_clock_stretcher_lookup_table[stretch_amount2][1]; - clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. - GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. - SclkFrequency) / 100); - if (tonga_clock_stretcher_lookup_table[stretch_amount2][0] < - clock_freq_u16 && - tonga_clock_stretcher_lookup_table[stretch_amount2][1] > - clock_freq_u16) { - /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ - value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; - /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ - value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; - /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ - value |= (tonga_clock_stretch_amount_conversion - [tonga_clock_stretcher_lookup_table[stretch_amount2][3]] - [stretch_amount]) << 3; - } - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. - CKS_LOOKUPTableEntry[0].minFreq); - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. - CKS_LOOKUPTableEntry[0].maxFreq); - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = - tonga_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; - smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= - (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL, value); - - /* Populate DDT Lookup Table */ - for (i = 0; i < 4; i++) { - /* Assign the minimum and maximum VID stored - * in the last row of Clock Stretcher Voltage Table. - */ - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].minVID = - (uint8_t) tonga_clock_stretcher_ddt_table[type][i][2]; - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].maxVID = - (uint8_t) tonga_clock_stretcher_ddt_table[type][i][3]; - /* Loop through each SCLK and check the frequency - * to see if it lies within the frequency for clock stretcher. - */ - for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { - cks_setting = 0; - clock_freq = PP_SMC_TO_HOST_UL( - smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); - /* Check the allowed frequency against the sclk level[j]. - * Sclk's endianness has already been converted, - * and it's in 10Khz unit, - * as opposed to Data table, which is in Mhz unit. - */ - if (clock_freq >= tonga_clock_stretcher_ddt_table[type][i][0] * 100) { - cks_setting |= 0x2; - if (clock_freq < tonga_clock_stretcher_ddt_table[type][i][1] * 100) - cks_setting |= 0x1; - } - smu_data->smc_state_table.ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); - } - CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. - ClockStretcherDataTable. - ClockStretcherDataTableEntry[i].setting); - } - - value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL); - value &= 0xFFFFFFFE; - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixPWR_CKS_CNTL, value); - - return 0; -} - -/** - * Populates the SMC VRConfig field in DPM table. - * - * @param hwmgr the address of the hardware manager - * @param table the SMC DPM table structure to be populated - * @return always 0 - */ -static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr, - SMU72_Discrete_DpmTable *table) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint16_t config; - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { - /* Splitted mode */ - config = VR_SVI2_PLANE_1; - table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT); - - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - config = VR_SVI2_PLANE_2; - table->VRConfig |= config; - } else { - pr_err("VDDC and VDDGFX should " - "be both on SVI2 control in splitted mode !\n"); - } - } else { - /* Merged mode */ - config = VR_MERGED_WITH_VDDC; - table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT); - - /* Set Vddc Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { - config = VR_SVI2_PLANE_1; - table->VRConfig |= config; - } else { - pr_err("VDDC should be on " - "SVI2 control in merged mode !\n"); - } - } - - /* Set Vddci Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { - config = VR_SVI2_PLANE_2; /* only in merged mode */ - table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT); - } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { - config = VR_SMIO_PATTERN_1; - table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT); - } - - /* Set Mvdd Voltage Controller */ - if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { - config = VR_SMIO_PATTERN_2; - table->VRConfig |= (config<<VRCONF_MVDD_SHIFT); - } - - return 0; -} - - -/** - * Initialize the ARB DRAM timing table's index field. - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - */ -static int tonga_init_arb_table_index(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t tmp; - int result; - - /* - * This is a read-modify-write on the first byte of the ARB table. - * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure - * is the field 'current'. - * This solution is ugly, but we never write the whole table only - * individual fields in it. - * In reality this field should not be in that structure - * but in a soft register. - */ - result = smu7_read_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); - - if (result != 0) - return result; - - tmp &= 0x00FFFFFF; - tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; - - return smu7_write_smc_sram_dword(hwmgr, - smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); -} - - -static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; - SMU72_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; - int i, j, k; - const uint16_t *pdef1, *pdef2; - - dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( - (uint16_t)(cac_dtp_table->usTDP * 256)); - dpm_table->TargetTdp = PP_HOST_TO_SMC_US( - (uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); - - PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, - "Target Operating Temp is out of Range !", - ); - - dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); - dpm_table->GpuTjHyst = 8; - - dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; - - dpm_table->BAPM_TEMP_GRADIENT = - PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); - pdef1 = defaults->bapmti_r; - pdef2 = defaults->bapmti_rc; - - for (i = 0; i < SMU72_DTE_ITERATIONS; i++) { - for (j = 0; j < SMU72_DTE_SOURCES; j++) { - for (k = 0; k < SMU72_DTE_SINKS; k++) { - dpm_table->BAPMTI_R[i][j][k] = - PP_HOST_TO_SMC_US(*pdef1); - dpm_table->BAPMTI_RC[i][j][k] = - PP_HOST_TO_SMC_US(*pdef2); - pdef1++; - pdef2++; - } - } - } - - return 0; -} - -static int tonga_populate_svi_load_line(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; - - smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; - smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddC; - smu_data->power_tune_table.SviLoadLineTrimVddC = 3; - smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; - - return 0; -} - -static int tonga_populate_tdc_limit(struct pp_hwmgr *hwmgr) -{ - uint16_t tdc_limit; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - /* TDC number of fraction bits are changed from 8 to 7 - * for Fiji as requested by SMC team - */ - tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 256); - smu_data->power_tune_table.TDC_VDDC_PkgLimit = - CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); - smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = - defaults->tdc_vddc_throttle_release_limit_perc; - smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; - - return 0; -} - -static int tonga_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; - uint32_t temp; - - if (smu7_read_smc_sram_dword(hwmgr, - fuse_table_offset + - offsetof(SMU72_Discrete_PmFuses, TdcWaterfallCtl), - (uint32_t *)&temp, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to read PmFuses.DW6 " - "(SviLoadLineEn) from SMC Failed !", - return -EINVAL); - else - smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; - - return 0; -} - -static int tonga_populate_temperature_scaler(struct pp_hwmgr *hwmgr) -{ - int i; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; - - return 0; -} - -static int tonga_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - - if ((hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity & (1 << 15)) || - (hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity == 0)) - hwmgr->thermal_controller.advanceFanControlParameters. - usFanOutputSensitivity = hwmgr->thermal_controller. - advanceFanControlParameters.usDefaultFanOutputSensitivity; - - smu_data->power_tune_table.FuzzyFan_PwmSetDelta = - PP_HOST_TO_SMC_US(hwmgr->thermal_controller. - advanceFanControlParameters.usFanOutputSensitivity); - return 0; -} - -static int tonga_populate_gnb_lpml(struct pp_hwmgr *hwmgr) -{ - int i; - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - - /* Currently not used. Set all to zero. */ - for (i = 0; i < 16; i++) - smu_data->power_tune_table.GnbLPML[i] = 0; - - return 0; -} - -static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; - uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; - struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; - - hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); - lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); - - smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = - CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); - smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = - CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); - - return 0; -} - -static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t pm_fuse_table_offset; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_PowerContainment)) { - if (smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, PmFuseTable), - &pm_fuse_table_offset, SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to get pm_fuse_table_offset Failed !", - return -EINVAL); - - /* DW6 */ - if (tonga_populate_svi_load_line(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate SviLoadLine Failed !", - return -EINVAL); - /* DW7 */ - if (tonga_populate_tdc_limit(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TDCLimit Failed !", - return -EINVAL); - /* DW8 */ - if (tonga_populate_dw8(hwmgr, pm_fuse_table_offset)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate TdcWaterfallCtl Failed !", - return -EINVAL); - - /* DW9-DW12 */ - if (tonga_populate_temperature_scaler(hwmgr) != 0) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate LPMLTemperatureScaler Failed !", - return -EINVAL); - - /* DW13-DW14 */ - if (tonga_populate_fuzzy_fan(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate Fuzzy Fan " - "Control parameters Failed !", - return -EINVAL); - - /* DW15-DW18 */ - if (tonga_populate_gnb_lpml(hwmgr)) - PP_ASSERT_WITH_CODE(false, - "Attempt to populate GnbLPML Failed !", - return -EINVAL); - - /* DW20 */ - if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr)) - PP_ASSERT_WITH_CODE( - false, - "Attempt to populate BapmVddCBaseLeakage " - "Hi and Lo Sidd Failed !", - return -EINVAL); - - if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, - (uint8_t *)&smu_data->power_tune_table, - sizeof(struct SMU72_Discrete_PmFuses), SMC_RAM_END)) - PP_ASSERT_WITH_CODE(false, - "Attempt to download PmFuseTable Failed !", - return -EINVAL); - } - return 0; -} - -static int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr, - SMU72_Discrete_MCRegisters *mc_reg_table) -{ - const struct tonga_smumgr *smu_data = (struct tonga_smumgr *)hwmgr->smu_backend; - - uint32_t i, j; - - for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { - if (smu_data->mc_reg_table.validflag & 1<<j) { - PP_ASSERT_WITH_CODE( - i < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE, - "Index of mc_reg_table->address[] array " - "out of boundary", - return -EINVAL); - mc_reg_table->address[i].s0 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); - mc_reg_table->address[i].s1 = - PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); - i++; - } - } - - mc_reg_table->last = (uint8_t)i; - - return 0; -} - -/*convert register values from driver to SMC format */ -static void tonga_convert_mc_registers( - const struct tonga_mc_reg_entry *entry, - SMU72_Discrete_MCRegisterSet *data, - uint32_t num_entries, uint32_t valid_flag) -{ - uint32_t i, j; - - for (i = 0, j = 0; j < num_entries; j++) { - if (valid_flag & 1<<j) { - data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); - i++; - } - } -} - -static int tonga_convert_mc_reg_table_entry_to_smc( - struct pp_hwmgr *hwmgr, - const uint32_t memory_clock, - SMU72_Discrete_MCRegisterSet *mc_reg_table_data - ) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t i = 0; - - for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { - if (memory_clock <= - smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { - break; - } - } - - if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) - --i; - - tonga_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], - mc_reg_table_data, smu_data->mc_reg_table.last, - smu_data->mc_reg_table.validflag); - - return 0; -} - -static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, - SMU72_Discrete_MCRegisters *mc_regs) -{ - int result = 0; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - int res; - uint32_t i; - - for (i = 0; i < data->dpm_table.mclk_table.count; i++) { - res = tonga_convert_mc_reg_table_entry_to_smc( - hwmgr, - data->dpm_table.mclk_table.dpm_levels[i].value, - &mc_regs->data[i] - ); - - if (0 != res) - result = res; - } - - return result; -} - -static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - uint32_t address; - int32_t result; - - if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) - return 0; - - - memset(&smu_data->mc_regs, 0, sizeof(SMU72_Discrete_MCRegisters)); - - result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); - - if (result != 0) - return result; - - - address = smu_data->smu7_data.mc_reg_table_start + - (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]); - - return smu7_copy_bytes_to_smc( - hwmgr, address, - (uint8_t *)&smu_data->mc_regs.data[0], - sizeof(SMU72_Discrete_MCRegisterSet) * - data->dpm_table.mclk_table.count, - SMC_RAM_END); -} - -static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - - memset(&smu_data->mc_regs, 0x00, sizeof(SMU72_Discrete_MCRegisters)); - result = tonga_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize MCRegTable for the MC register addresses !", - return result;); - - result = tonga_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize MCRegTable for driver state !", - return result;); - - return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, - (uint8_t *)&smu_data->mc_regs, sizeof(SMU72_Discrete_MCRegisters), SMC_RAM_END); -} - -static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - if (table_info && - table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && - table_info->cac_dtp_table->usPowerTuneDataSetID) - smu_data->power_tune_defaults = - &tonga_power_tune_data_set_array - [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; - else - smu_data->power_tune_defaults = &tonga_power_tune_data_set_array[0]; -} - -static void tonga_save_default_power_profile(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *data = (struct tonga_smumgr *)(hwmgr->smu_backend); - struct SMU72_Discrete_GraphicsLevel *levels = - data->smc_state_table.GraphicsLevel; - unsigned min_level = 1; - - hwmgr->default_gfx_power_profile.activity_threshold = - be16_to_cpu(levels[0].ActivityLevel); - hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst; - hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst; - hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; - - hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile; - hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; - - /* Workaround compute SDMA instability: disable lowest SCLK - * DPM level. Optimize compute power profile: Use only highest - * 2 power levels (if more than 2 are available), Hysteresis: - * 0ms up, 5ms down - */ - if (data->smc_state_table.GraphicsDpmLevelCount > 2) - min_level = data->smc_state_table.GraphicsDpmLevelCount - 2; - else if (data->smc_state_table.GraphicsDpmLevelCount == 2) - min_level = 1; - else - min_level = 0; - hwmgr->default_compute_power_profile.min_sclk = - be32_to_cpu(levels[min_level].SclkFrequency); - hwmgr->default_compute_power_profile.up_hyst = 0; - hwmgr->default_compute_power_profile.down_hyst = 5; - - hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; - hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; -} - -/** - * Initializes the SMC table and uploads it - * - * @param hwmgr the address of the powerplay hardware manager. - * @param pInput the pointer to input data (PowerState) - * @return always 0 - */ -int tonga_init_smc_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - SMU72_Discrete_DpmTable *table = &(smu_data->smc_state_table); - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - uint8_t i; - pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; - - - memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); - - tonga_initialize_power_tune_defaults(hwmgr); - - if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) - tonga_populate_smc_voltage_tables(hwmgr, table); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; - - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StepVddc)) - table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; - - if (data->is_memory_gddr5) - table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; - - i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN); - - if (i == 1 || i == 0) - table->SystemFlags |= 0x40; - - if (data->ulv_supported && table_info->us_ulv_voltage_offset) { - result = tonga_populate_ulv_state(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ULV state !", - return result;); - - cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, - ixCG_ULV_PARAMETER, 0x40035); - } - - result = tonga_populate_smc_link_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Link Level !", return result); - - result = tonga_populate_all_graphic_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Graphics Level !", return result); - - result = tonga_populate_all_memory_levels(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Memory Level !", return result); - - result = tonga_populate_smc_acpi_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ACPI Level !", return result); - - result = tonga_populate_smc_vce_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize VCE Level !", return result); - - result = tonga_populate_smc_acp_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize ACP Level !", return result); - - result = tonga_populate_smc_samu_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize SAMU Level !", return result); - - /* Since only the initial state is completely set up at this - * point (the other states are just copies of the boot state) we only - * need to populate the ARB settings for the initial state. - */ - result = tonga_program_memory_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to Write ARB settings for the initial state.", - return result;); - - result = tonga_populate_smc_uvd_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize UVD Level !", return result); - - result = tonga_populate_smc_boot_level(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to initialize Boot Level !", return result); - - tonga_populate_bapm_parameters_in_dpm_table(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate BAPM Parameters !", return result); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ClockStretcher)) { - result = tonga_populate_clock_stretcher_data_table(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate Clock Stretcher Data Table !", - return result;); - } - table->GraphicsVoltageChangeEnable = 1; - table->GraphicsThermThrottleEnable = 1; - table->GraphicsInterval = 1; - table->VoltageInterval = 1; - table->ThermalInterval = 1; - table->TemperatureLimitHigh = - table_info->cac_dtp_table->usTargetOperatingTemp * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->TemperatureLimitLow = - (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * - SMU7_Q88_FORMAT_CONVERSION_UNIT; - table->MemoryVoltageChangeEnable = 1; - table->MemoryInterval = 1; - table->VoltageResponseTime = 0; - table->PhaseResponseTime = 0; - table->MemoryThermThrottleEnable = 1; - - /* - * Cail reads current link status and reports it as cap (we cannot - * change this due to some previous issues we had) - * SMC drops the link status to lowest level after enabling - * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again - * but this time Cail reads current link status which was set to low by - * SMC and reports it as cap to powerplay - * To avoid it, we set PCIeBootLinkLevel to highest dpm level - */ - PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), - "There must be 1 or more PCIE levels defined in PPTable.", - return -EINVAL); - - table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count); - - table->PCIeGenInterval = 1; - - result = tonga_populate_vr_config(hwmgr, table); - PP_ASSERT_WITH_CODE(!result, - "Failed to populate VRConfig setting !", return result); - - table->ThermGpio = 17; - table->SclkStepSize = 0x4000; - - if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, - &gpio_pin_assignment)) { - table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } else { - table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, - &gpio_pin_assignment)) { - table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } else { - table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - } - - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_Falcon_QuickTransition); - - if (0) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_AutomaticDCTransition); - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_Falcon_QuickTransition); - } - - if (atomctrl_get_pp_assign_pin(hwmgr, - THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment)) { - phm_cap_set(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - - table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; - - table->ThermOutPolarity = - (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & - (1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1 : 0; - - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; - - /* if required, combine VRHot/PCC with thermal out GPIO*/ - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_RegulatorHot) && - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_CombinePCCWithThermalSignal)){ - table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; - } - } else { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_ThermalOutGPIO); - - table->ThermOutGpio = 17; - table->ThermOutPolarity = 1; - table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; - } - - for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++) - table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); - - CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); - CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); - CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); - CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); - CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); - CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); - CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); - - /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + offsetof(SMU72_Discrete_DpmTable, SystemFlags), - (uint8_t *)&(table->SystemFlags), - sizeof(SMU72_Discrete_DpmTable) - 3 * sizeof(SMU72_PIDController), - SMC_RAM_END); - - PP_ASSERT_WITH_CODE(!result, - "Failed to upload dpm data to SMC memory !", return result;); - - result = tonga_init_arb_table_index(hwmgr); - PP_ASSERT_WITH_CODE(!result, - "Failed to upload arb data to SMC memory !", return result); - - tonga_populate_pm_fuses(hwmgr); - PP_ASSERT_WITH_CODE((!result), - "Failed to populate initialize pm fuses !", return result); - - result = tonga_populate_initial_mc_reg_table(hwmgr); - PP_ASSERT_WITH_CODE((!result), - "Failed to populate initialize MC Reg table !", return result); - - tonga_save_default_power_profile(hwmgr); - - return 0; -} - -/** -* Set up the fan table to control the fan using the SMC. -* @param hwmgr the address of the powerplay hardware manager. -* @param pInput the pointer to input data -* @param pOutput the pointer to output data -* @param pStorage the pointer to temporary storage -* @param Result the last failure code -* @return result from set temperature range routine -*/ -int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; - uint32_t duty100; - uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; - uint16_t fdo_min, slope1, slope2; - uint32_t reference_clock; - int res; - uint64_t tmp64; - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl)) - return 0; - - if (hwmgr->thermal_controller.fanInfo.bNoFan) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - if (0 == smu_data->smu7_data.fan_table_start) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, - CG_FDO_CTRL1, FMAX_DUTY100); - - if (0 == duty100) { - phm_cap_unset(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_MicrocodeFanControl); - return 0; - } - - tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; - do_div(tmp64, 10000); - fdo_min = (uint16_t)tmp64; - - t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; - t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; - - pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; - pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; - - slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); - slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); - - fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); - fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); - fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); - - fan_table.Slope1 = cpu_to_be16(slope1); - fan_table.Slope2 = cpu_to_be16(slope2); - - fan_table.FdoMin = cpu_to_be16(fdo_min); - - fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); - - fan_table.HystUp = cpu_to_be16(1); - - fan_table.HystSlope = cpu_to_be16(1); - - fan_table.TempRespLim = cpu_to_be16(5); - - reference_clock = smu7_get_xclk(hwmgr); - - fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); - - fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); - - fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); - - fan_table.FanControl_GL_Flag = 1; - - res = smu7_copy_bytes_to_smc(hwmgr, - smu_data->smu7_data.fan_table_start, - (uint8_t *)&fan_table, - (uint32_t)sizeof(fan_table), - SMC_RAM_END); - - return 0; -} - - -static int tonga_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - if (data->need_update_smu7_dpm_table & - (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) - return tonga_program_memory_timing_parameters(hwmgr); - - return 0; -} - -int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - - int result = 0; - uint32_t low_sclk_interrupt_threshold = 0; - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_SclkThrottleLowNotification) - && (hwmgr->gfx_arbiter.sclk_threshold != - data->low_sclk_interrupt_threshold)) { - data->low_sclk_interrupt_threshold = - hwmgr->gfx_arbiter.sclk_threshold; - low_sclk_interrupt_threshold = - data->low_sclk_interrupt_threshold; - - CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); - - result = smu7_copy_bytes_to_smc( - hwmgr, - smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, - LowSclkInterruptThreshold), - (uint8_t *)&low_sclk_interrupt_threshold, - sizeof(uint32_t), - SMC_RAM_END); - } - - result = tonga_update_and_upload_mc_reg_table(hwmgr); - - PP_ASSERT_WITH_CODE((!result), - "Failed to upload MC reg table !", - return result); - - result = tonga_program_mem_timing_parameters(hwmgr); - PP_ASSERT_WITH_CODE((result == 0), - "Failed to program memory timing parameters !", - ); - - return result; -} - -uint32_t tonga_get_offsetof(uint32_t type, uint32_t member) -{ - switch (type) { - case SMU_SoftRegisters: - switch (member) { - case HandshakeDisables: - return offsetof(SMU72_SoftRegisters, HandshakeDisables); - case VoltageChangeTimeout: - return offsetof(SMU72_SoftRegisters, VoltageChangeTimeout); - case AverageGraphicsActivity: - return offsetof(SMU72_SoftRegisters, AverageGraphicsActivity); - case PreVBlankGap: - return offsetof(SMU72_SoftRegisters, PreVBlankGap); - case VBlankTimeout: - return offsetof(SMU72_SoftRegisters, VBlankTimeout); - case UcodeLoadStatus: - return offsetof(SMU72_SoftRegisters, UcodeLoadStatus); - } - case SMU_Discrete_DpmTable: - switch (member) { - case UvdBootLevel: - return offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); - case VceBootLevel: - return offsetof(SMU72_Discrete_DpmTable, VceBootLevel); - case SamuBootLevel: - return offsetof(SMU72_Discrete_DpmTable, SamuBootLevel); - case LowSclkInterruptThreshold: - return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold); - } - } - pr_warn("can't get the offset of type %x member %x\n", type, member); - return 0; -} - -uint32_t tonga_get_mac_definition(uint32_t value) -{ - switch (value) { - case SMU_MAX_LEVELS_GRAPHICS: - return SMU72_MAX_LEVELS_GRAPHICS; - case SMU_MAX_LEVELS_MEMORY: - return SMU72_MAX_LEVELS_MEMORY; - case SMU_MAX_LEVELS_LINK: - return SMU72_MAX_LEVELS_LINK; - case SMU_MAX_ENTRIES_SMIO: - return SMU72_MAX_ENTRIES_SMIO; - case SMU_MAX_LEVELS_VDDC: - return SMU72_MAX_LEVELS_VDDC; - case SMU_MAX_LEVELS_VDDGFX: - return SMU72_MAX_LEVELS_VDDGFX; - case SMU_MAX_LEVELS_VDDCI: - return SMU72_MAX_LEVELS_VDDCI; - case SMU_MAX_LEVELS_MVDD: - return SMU72_MAX_LEVELS_MVDD; - } - pr_warn("can't get the mac value %x\n", value); - - return 0; -} - - -static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - smu_data->smc_state_table.UvdBootLevel = 0; - if (table_info->mm_dep_table->count > 0) - smu_data->smc_state_table.UvdBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0x00FFFFFF; - mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, - mm_boot_level_offset, mm_boot_level_value); - - if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_UVDDPM) || - phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_UVDDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); - return 0; -} - -static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = - (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - struct phm_ppt_v1_information *table_info = - (struct phm_ppt_v1_information *)(hwmgr->pptable); - - - smu_data->smc_state_table.VceBootLevel = - (uint8_t) (table_info->mm_dep_table->count - 1); - - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, VceBootLevel); - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFF00FFFF; - mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_VCEDPM_SetEnabledMask, - (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); - return 0; -} - -static int tonga_update_samu_smc_table(struct pp_hwmgr *hwmgr) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - uint32_t mm_boot_level_offset, mm_boot_level_value; - - smu_data->smc_state_table.SamuBootLevel = 0; - mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, SamuBootLevel); - - mm_boot_level_offset /= 4; - mm_boot_level_offset *= 4; - mm_boot_level_value = cgs_read_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset); - mm_boot_level_value &= 0xFFFFFF00; - mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0; - cgs_write_ind_register(hwmgr->device, - CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); - - if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, - PHM_PlatformCaps_StablePState)) - smum_send_msg_to_smc_with_parameter(hwmgr, - PPSMC_MSG_SAMUDPM_SetEnabledMask, - (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); - return 0; -} - -int tonga_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) -{ - switch (type) { - case SMU_UVD_TABLE: - tonga_update_uvd_smc_table(hwmgr); - break; - case SMU_VCE_TABLE: - tonga_update_vce_smc_table(hwmgr); - break; - case SMU_SAMU_TABLE: - tonga_update_samu_smc_table(hwmgr); - break; - default: - break; - } - return 0; -} - - -/** - * Get the location of various tables inside the FW image. - * - * @param hwmgr the address of the powerplay hardware manager. - * @return always 0 - */ -int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) -{ - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - - uint32_t tmp; - int result; - bool error = false; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, DpmTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.dpm_table_start = tmp; - - error |= (result != 0); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, SoftRegisters), - &tmp, SMC_RAM_END); - - if (!result) { - data->soft_regs_start = tmp; - smu_data->smu7_data.soft_regs_start = tmp; - } - - error |= (result != 0); - - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, mcRegisterTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.mc_reg_table_start = tmp; - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, FanTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.fan_table_start = tmp; - - error |= (result != 0); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, mcArbDramTimingTable), - &tmp, SMC_RAM_END); - - if (!result) - smu_data->smu7_data.arb_table_start = tmp; - - error |= (result != 0); - - result = smu7_read_smc_sram_dword(hwmgr, - SMU72_FIRMWARE_HEADER_LOCATION + - offsetof(SMU72_Firmware_Header, Version), - &tmp, SMC_RAM_END); - - if (!result) - hwmgr->microcode_version_info.SMC = tmp; - - error |= (result != 0); - - return error ? 1 : 0; -} - -/*---------------------------MC----------------------------*/ - -static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr) -{ - return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); -} - -static bool tonga_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) -{ - bool result = true; - - switch (in_reg) { - case mmMC_SEQ_RAS_TIMING: - *out_reg = mmMC_SEQ_RAS_TIMING_LP; - break; - - case mmMC_SEQ_DLL_STBY: - *out_reg = mmMC_SEQ_DLL_STBY_LP; - break; - - case mmMC_SEQ_G5PDX_CMD0: - *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; - break; - - case mmMC_SEQ_G5PDX_CMD1: - *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; - break; - - case mmMC_SEQ_G5PDX_CTRL: - *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; - break; - - case mmMC_SEQ_CAS_TIMING: - *out_reg = mmMC_SEQ_CAS_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING: - *out_reg = mmMC_SEQ_MISC_TIMING_LP; - break; - - case mmMC_SEQ_MISC_TIMING2: - *out_reg = mmMC_SEQ_MISC_TIMING2_LP; - break; - - case mmMC_SEQ_PMG_DVS_CMD: - *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; - break; - - case mmMC_SEQ_PMG_DVS_CTL: - *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; - break; - - case mmMC_SEQ_RD_CTL_D0: - *out_reg = mmMC_SEQ_RD_CTL_D0_LP; - break; - - case mmMC_SEQ_RD_CTL_D1: - *out_reg = mmMC_SEQ_RD_CTL_D1_LP; - break; - - case mmMC_SEQ_WR_CTL_D0: - *out_reg = mmMC_SEQ_WR_CTL_D0_LP; - break; - - case mmMC_SEQ_WR_CTL_D1: - *out_reg = mmMC_SEQ_WR_CTL_D1_LP; - break; - - case mmMC_PMG_CMD_EMRS: - *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; - break; - - case mmMC_PMG_CMD_MRS: - *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; - break; - - case mmMC_PMG_CMD_MRS1: - *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; - break; - - case mmMC_SEQ_PMG_TIMING: - *out_reg = mmMC_SEQ_PMG_TIMING_LP; - break; - - case mmMC_PMG_CMD_MRS2: - *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; - break; - - case mmMC_SEQ_WR_CTL_2: - *out_reg = mmMC_SEQ_WR_CTL_2_LP; - break; - - default: - result = false; - break; - } - - return result; -} - -static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table *table) -{ - uint32_t i; - uint16_t address; - - for (i = 0; i < table->last; i++) { - table->mc_reg_address[i].s0 = - tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1, - &address) ? - address : - table->mc_reg_address[i].s1; - } - return 0; -} - -static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, - struct tonga_mc_reg_table *ni_table) -{ - uint8_t i, j; - - PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), - "Invalid VramInfo table.", return -EINVAL); - - for (i = 0; i < table->last; i++) - ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; - - ni_table->last = table->last; - - for (i = 0; i < table->num_entries; i++) { - ni_table->mc_reg_table_entry[i].mclk_max = - table->mc_reg_table_entry[i].mclk_max; - for (j = 0; j < table->last; j++) { - ni_table->mc_reg_table_entry[i].mc_data[j] = - table->mc_reg_table_entry[i].mc_data[j]; - } - } - - ni_table->num_entries = table->num_entries; - - return 0; -} - -/** - * VBIOS omits some information to reduce size, we need to recover them here. - * 1. when we see mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to - * mmMC_PMG_CMD_EMRS /_LP[15:0]. Bit[15:0] MRS, need to be update - * mmMC_PMG_CMD_MRS/_LP[15:0] - * 2. when we see mmMC_SEQ_RESERVE_M, bit[15:0] EMRS2, need to be write to - * mmMC_PMG_CMD_MRS1/_LP[15:0]. - * 3. need to set these data for each clock range - * @param hwmgr the address of the powerplay hardware manager. - * @param table the address of MCRegTable - * @return always 0 - */ -static int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr, - struct tonga_mc_reg_table *table) -{ - uint8_t i, j, k; - uint32_t temp_reg; - struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); - - for (i = 0, j = table->last; i < table->last; i++) { - PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - switch (table->mc_reg_address[i].s1) { - - case mmMC_SEQ_MISC1: - temp_reg = cgs_read_register(hwmgr->device, - mmMC_PMG_CMD_EMRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - ((temp_reg & 0xffff0000)) | - ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); - } - j++; - PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - - if (!data->is_memory_gddr5) - table->mc_reg_table_entry[k].mc_data[j] |= 0x100; - } - j++; - PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - - if (!data->is_memory_gddr5) { - table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; - table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; - for (k = 0; k < table->num_entries; k++) - table->mc_reg_table_entry[k].mc_data[j] = - (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; - j++; - PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - } - - break; - - case mmMC_SEQ_RESERVE_M: - temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); - table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; - table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; - for (k = 0; k < table->num_entries; k++) { - table->mc_reg_table_entry[k].mc_data[j] = - (temp_reg & 0xffff0000) | - (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); - } - j++; - PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), - "Invalid VramInfo table.", return -EINVAL); - break; - - default: - break; - } - - } - - table->last = j; - - return 0; -} - -static int tonga_set_valid_flag(struct tonga_mc_reg_table *table) -{ - uint8_t i, j; - - for (i = 0; i < table->last; i++) { - for (j = 1; j < table->num_entries; j++) { - if (table->mc_reg_table_entry[j-1].mc_data[i] != - table->mc_reg_table_entry[j].mc_data[i]) { - table->validflag |= (1<<i); - break; - } - } - } - - return 0; -} - -int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) -{ - int result; - struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); - pp_atomctrl_mc_reg_table *table; - struct tonga_mc_reg_table *ni_table = &smu_data->mc_reg_table; - uint8_t module_index = tonga_get_memory_modile_index(hwmgr); - - table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); - - if (table == NULL) - return -ENOMEM; - - /* Program additional LP registers that are no longer programmed by VBIOS */ - cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, - cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, - cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, - cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); - cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); - cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, - cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); - cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, - cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); - - memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table)); - - result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); - - if (!result) - result = tonga_copy_vbios_smc_reg_table(table, ni_table); - - if (!result) { - tonga_set_s0_mc_reg_index(ni_table); - result = tonga_set_mc_special_registers(hwmgr, ni_table); - } - - if (!result) - tonga_set_valid_flag(ni_table); - - kfree(table); - - return result; -} - -bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr) -{ - return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, - CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) - ? true : false; -} - -int tonga_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request) -{ - struct tonga_smumgr *smu_data = (struct tonga_smumgr *) - (hwmgr->smu_backend); - struct SMU72_Discrete_GraphicsLevel *levels = - smu_data->smc_state_table.GraphicsLevel; - uint32_t array = smu_data->smu7_data.dpm_table_start + - offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); - uint32_t array_size = sizeof(struct SMU72_Discrete_GraphicsLevel) * - SMU72_MAX_LEVELS_GRAPHICS; - uint32_t i; - - for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { - levels[i].ActivityLevel = - cpu_to_be16(request->activity_threshold); - levels[i].EnabledForActivity = 1; - levels[i].UpHyst = request->up_hyst; - levels[i].DownHyst = request->down_hyst; - } - - return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, - array_size, SMC_RAM_END); -} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.h b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.h deleted file mode 100644 index 9d6a78a65976..000000000000 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smc.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2015 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ -#ifndef _TONGA_SMC_H -#define _TONGA_SMC_H - -#include "smumgr.h" -#include "smu72.h" - - -#define ASICID_IS_TONGA_P(wDID, bRID) \ - (((wDID == 0x6930) && ((bRID == 0xF0) || (bRID == 0xF1) || (bRID == 0xFF))) \ - || ((wDID == 0x6920) && ((bRID == 0) || (bRID == 1)))) - - -struct tonga_pt_defaults { - uint8_t svi_load_line_en; - uint8_t svi_load_line_vddC; - uint8_t tdc_vddc_throttle_release_limit_perc; - uint8_t tdc_mawt; - uint8_t tdc_waterfall_ctl; - uint8_t dte_ambient_temp_base; - uint32_t display_cac; - uint32_t bapm_temp_gradient; - uint16_t bapmti_r[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; - uint16_t bapmti_rc[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; -}; - -int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); -int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr); -int tonga_init_smc_table(struct pp_hwmgr *hwmgr); -int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); -int tonga_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type); -int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr); -uint32_t tonga_get_offsetof(uint32_t type, uint32_t member); -uint32_t tonga_get_mac_definition(uint32_t value); -int tonga_process_firmware_header(struct pp_hwmgr *hwmgr); -int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); -bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr); -int tonga_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request); -#endif - diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c index d22cf218cf18..0a8e48bff219 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c @@ -33,9 +33,69 @@ #include "smu/smu_7_1_2_d.h" #include "smu/smu_7_1_2_sh_mask.h" #include "cgs_common.h" -#include "tonga_smc.h" #include "smu7_smumgr.h" +#include "smu7_dyn_defaults.h" + +#include "smu7_hwmgr.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" + +#include "atombios.h" + +#include "pppcielanes.h" +#include "pp_endian.h" + +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" + +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" + +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" + + +#define VOLTAGE_SCALE 4 +#define POWERTUNE_DEFAULT_SET_MAX 1 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 +#define MC_CG_ARB_FREQ_F1 0x0b +#define VDDC_VDDCI_DELTA 200 + + +static const struct tonga_pt_defaults tonga_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { +/* sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc, TDC_MAWt, + * TdcWaterfallCtl, DTEAmbientTempBase, DisplayCac, BAPM_TEMP_GRADIENT + */ + {1, 0xF, 0xFD, 0x19, + 5, 45, 0, 0xB0000, + {0x79, 0x253, 0x25D, 0xAE, 0x72, 0x80, 0x83, 0x86, 0x6F, 0xC8, + 0xC9, 0xC9, 0x2F, 0x4D, 0x61}, + {0x17C, 0x172, 0x180, 0x1BC, 0x1B3, 0x1BD, 0x206, 0x200, 0x203, + 0x25D, 0x25A, 0x255, 0x2C3, 0x2C5, 0x2B4} + }, +}; + +/* [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */ +static const uint16_t tonga_clock_stretcher_lookup_table[2][4] = { + {600, 1050, 3, 0}, + {600, 1050, 6, 1} +}; + +/* [FF, SS] type, [] 4 voltage ranges, + * and [Floor Freq, Boundary Freq, VID min , VID max] + */ +static const uint32_t tonga_clock_stretcher_ddt_table[2][4][4] = { + { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, + { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } +}; + +/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] */ +static const uint8_t tonga_clock_stretch_amount_conversion[2][6] = { + {0, 1, 3, 2, 4, 5}, + {0, 2, 4, 5, 6, 5} +}; static int tonga_start_in_protection_mode(struct pp_hwmgr *hwmgr) { @@ -95,7 +155,6 @@ static int tonga_start_in_protection_mode(struct pp_hwmgr *hwmgr) return 0; } - static int tonga_start_in_non_protection_mode(struct pp_hwmgr *hwmgr) { int result = 0; @@ -160,13 +219,6 @@ static int tonga_start_smu(struct pp_hwmgr *hwmgr) return result; } -/** - * Write a 32bit value to the SMC SRAM space. - * ALL PARAMETERS ARE IN HOST BYTE ORDER. - * @param smumgr the address of the powerplay hardware manager. - * @param smcAddress the address in the SMC RAM to access. - * @param value to write to the SMC SRAM. - */ static int tonga_smu_init(struct pp_hwmgr *hwmgr) { struct tonga_smumgr *tonga_priv = NULL; @@ -187,6 +239,3053 @@ static int tonga_smu_init(struct pp_hwmgr *hwmgr) return 0; } + +static int tonga_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table, + uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) +{ + uint32_t i = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + /* clock - voltage dependency table is empty table */ + if (allowed_clock_voltage_table->count == 0) + return -EINVAL; + + for (i = 0; i < allowed_clock_voltage_table->count; i++) { + /* find first sclk bigger than request */ + if (allowed_clock_voltage_table->entries[i].clk >= clock) { + voltage->VddGfx = phm_get_voltage_index( + pptable_info->vddgfx_lookup_table, + allowed_clock_voltage_table->entries[i].vddgfx); + voltage->Vddc = phm_get_voltage_index( + pptable_info->vddc_lookup_table, + allowed_clock_voltage_table->entries[i].vddc); + + if (allowed_clock_voltage_table->entries[i].vddci) + voltage->Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, allowed_clock_voltage_table->entries[i].vddci); + else + voltage->Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + allowed_clock_voltage_table->entries[i].vddc - VDDC_VDDCI_DELTA); + + + if (allowed_clock_voltage_table->entries[i].mvdd) + *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd; + + voltage->Phases = 1; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + voltage->VddGfx = phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + allowed_clock_voltage_table->entries[i-1].vddgfx); + voltage->Vddc = phm_get_voltage_index(pptable_info->vddc_lookup_table, + allowed_clock_voltage_table->entries[i-1].vddc); + + if (allowed_clock_voltage_table->entries[i-1].vddci) + voltage->Vddci = phm_get_voltage_id(&data->vddci_voltage_table, + allowed_clock_voltage_table->entries[i-1].vddci); + + if (allowed_clock_voltage_table->entries[i-1].mvdd) + *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd; + + return 0; +} + +static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + unsigned int count; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + table->VddcLevelCount = data->vddc_voltage_table.count; + for (count = 0; count < table->VddcLevelCount; count++) { + table->VddcTable[count] = + PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); + } + return 0; +} + +static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + unsigned int count; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { + table->VddGfxLevelCount = data->vddgfx_voltage_table.count; + for (count = 0; count < data->vddgfx_voltage_table.count; count++) { + table->VddGfxTable[count] = + PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount); + } + return 0; +} + +static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + + table->VddciLevelCount = data->vddci_voltage_table.count; + for (count = 0; count < table->VddciLevelCount; count++) { + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + table->VddciTable[count] = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + table->SmioTable1.Pattern[count].Voltage = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */ + table->SmioTable1.Pattern[count].Smio = + (uint8_t) count; + table->Smio[count] |= + data->vddci_voltage_table.entries[count].smio_low; + table->VddciTable[count] = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + } + + table->SmioMask1 = data->vddci_voltage_table.mask_low; + CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); + + return 0; +} + +static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t count; + + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + table->MvddLevelCount = data->mvdd_voltage_table.count; + for (count = 0; count < table->MvddLevelCount; count++) { + table->SmioTable2.Pattern[count].Voltage = + PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ + table->SmioTable2.Pattern[count].Smio = + (uint8_t) count; + table->Smio[count] |= + data->mvdd_voltage_table.entries[count].smio_low; + } + table->SmioMask2 = data->mvdd_voltage_table.mask_low; + + CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); + } + + return 0; +} + +static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table = + pptable_info->vddgfx_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table = + pptable_info->vddc_lookup_table; + + /* table is already swapped, so in order to use the value from it + * we need to swap it back. + */ + uint32_t vddc_level_count = PP_SMC_TO_HOST_UL(table->VddcLevelCount); + uint32_t vddgfx_level_count = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount); + + for (count = 0; count < vddc_level_count; count++) { + /* We are populating vddc CAC data to BapmVddc table in split and merged mode */ + index = phm_get_voltage_index(vddc_lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); + table->BapmVddcVidHiSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); + table->BapmVddcVidHiSidd2[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); + } + + if ((data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2)) { + /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */ + for (count = 0; count < vddgfx_level_count; count++) { + index = phm_get_voltage_index(vddgfx_lookup_table, + convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid)); + table->BapmVddGfxVidHiSidd2[count] = + convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high); + } + } else { + for (count = 0; count < vddc_level_count; count++) { + index = phm_get_voltage_index(vddc_lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddGfxVidLoSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); + table->BapmVddGfxVidHiSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); + table->BapmVddGfxVidHiSidd2[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); + } + } + + return 0; +} + +static int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result; + + result = tonga_populate_smc_vddc_table(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate VDDC voltage table to SMC", + return -EINVAL); + + result = tonga_populate_smc_vdd_ci_table(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate VDDCI voltage table to SMC", + return -EINVAL); + + result = tonga_populate_smc_vdd_gfx_table(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate VDDGFX voltage table to SMC", + return -EINVAL); + + result = tonga_populate_smc_mvdd_table(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate MVDD voltage table to SMC", + return -EINVAL); + + result = tonga_populate_cac_tables(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "can not populate CAC voltage tables to SMC", + return -EINVAL); + + return 0; +} + +static int tonga_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU72_Discrete_Ulv *state) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; + state->VddcOffsetVid = (uint8_t)(table_info->us_ulv_voltage_offset * + VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1); + + state->VddcPhase = 1; + + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + + return 0; +} + +static int tonga_populate_ulv_state(struct pp_hwmgr *hwmgr, + struct SMU72_Discrete_DpmTable *table) +{ + return tonga_populate_ulv_level(hwmgr, &table->Ulv); +} + +static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t i; + + /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = + (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = + 1; + table->LinkLevel[i].SPC = + (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = + PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = + PP_HOST_TO_SMC_UL(30); + } + + smu_data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t reference_clock; + uint32_t reference_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ + reference_clock = atomctrl_get_reference_clock(hwmgr); + + reference_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider*/ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup*/ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + pp_atomctrl_internal_ss_info ss_info; + + uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; + if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { + /* + * ss_info.speed_spectrum_percentage -- in unit of 0.01% + * ss_info.speed_spectrum_rate -- in unit of khz + */ + /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ + uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); + + /* clkv = 2 * D * fbdiv / NS */ + uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); + + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = + PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); + } + } + + sclk->SclkFrequency = engine_clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint16_t sclk_activity_level_threshold, + SMU72_Discrete_GraphicsLevel *graphic_level) +{ + int result; + uint32_t mvdd; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level); + + /* populate graphics levels*/ + result = tonga_get_dependency_volt_by_clk(hwmgr, + pptable_info->vdd_dep_on_sclk, engine_clock, + &graphic_level->MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((!result), + "can not find VDDC voltage value for VDDC " + "engine clock dependency table", return result); + + /* SCLK frequency in units of 10KHz*/ + graphic_level->SclkFrequency = engine_clock; + /* Indicates maximum activity level for this performance level. 50% for now*/ + graphic_level->ActivityLevel = sclk_activity_level_threshold; + + graphic_level->CcPwrDynRm = 0; + graphic_level->CcPwrDynRm1 = 0; + /* this level can be used if activity is high enough.*/ + graphic_level->EnabledForActivity = 0; + /* this level can be used for throttling.*/ + graphic_level->EnabledForThrottle = 1; + graphic_level->UpHyst = 0; + graphic_level->DownHyst = 0; + graphic_level->VoltageDownHyst = 0; + graphic_level->PowerThrottle = 0; + + data->display_timing.min_clock_in_sr = + hwmgr->display_config.min_core_set_clock_in_sr; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) + graphic_level->DeepSleepDivId = + smu7_get_sleep_divider_id_from_clock(engine_clock, + data->display_timing.min_clock_in_sr); + + /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ + graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + if (!result) { + /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/ + /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/ + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); + } + + return result; +} + +static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + struct phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table; + uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count; + uint32_t level_array_address = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); + + uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) * + SMU72_MAX_LEVELS_GRAPHICS; + + SMU72_Discrete_GraphicsLevel *levels = smu_data->smc_state_table.GraphicsLevel; + + uint32_t i, max_entry; + uint8_t highest_pcie_level_enabled = 0; + uint8_t lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0; + uint8_t count = 0; + int result = 0; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = tonga_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + (uint16_t)smu_data->activity_target[i], + &(smu_data->smc_state_table.GraphicsLevel[i])); + if (result != 0) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + smu_data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; + } + + /* Only enable level 0 for now. */ + smu_data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + + /* set highest level watermark to high */ + if (dpm_table->sclk_table.count > 1) + smu_data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + smu_data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + phm_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((pcie_entry_count >= 1), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + max_entry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/ + for (i = 0; i < dpm_table->sclk_table.count; i++) { + smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = + (uint8_t) ((i < max_entry) ? i : max_entry); + } + } else { + if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask) + pr_err("Pcie Dpm Enablemask is 0 !"); + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<<(highest_pcie_level_enabled+1))) != 0)) { + highest_pcie_level_enabled++; + } + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<<lowest_pcie_level_enabled)) == 0)) { + lowest_pcie_level_enabled++; + } + + while ((count < highest_pcie_level_enabled) && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<<(lowest_pcie_level_enabled+1+count))) == 0)) { + count++; + } + mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? + (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; + + + /* set pcieDpmLevel to highest_pcie_level_enabled*/ + for (i = 2; i < dpm_table->sclk_table.count; i++) + smu_data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; + + /* set pcieDpmLevel to lowest_pcie_level_enabled*/ + smu_data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled*/ + smu_data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change*/ + result = smu7_copy_bytes_to_smc(hwmgr, level_array_address, + (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int tonga_calculate_mclk_params( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU72_Discrete_MemoryLevel *mclk, + bool strobe_mode, + bool dllStateOn + ) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; + uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; + uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; + uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; + uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; + uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; + uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; + + pp_atomctrl_memory_clock_param mpll_param; + int result; + + result = atomctrl_get_memory_pll_dividers_si(hwmgr, + memory_clock, &mpll_param, strobe_mode); + PP_ASSERT_WITH_CODE( + !result, + "Error retrieving Memory Clock Parameters from VBIOS.", + return result); + + /* MPLL_FUNC_CNTL setup*/ + mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, + mpll_param.bw_ctrl); + + /* MPLL_FUNC_CNTL_1 setup*/ + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKF, + mpll_param.mpll_fb_divider.cl_kf); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKFRAC, + mpll_param.mpll_fb_divider.clk_frac); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, VCO_MODE, + mpll_param.vco_mode); + + /* MPLL_AD_FUNC_CNTL setup*/ + mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, + MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, + mpll_param.mpll_post_divider); + + if (data->is_memory_gddr5) { + /* MPLL_DQ_FUNC_CNTL setup*/ + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_SEL, + mpll_param.yclk_sel); + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, + mpll_param.mpll_post_divider); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { + /* + ************************************ + Fref = Reference Frequency + NF = Feedback divider ratio + NR = Reference divider ratio + Fnom = Nominal VCO output frequency = Fref * NF / NR + Fs = Spreading Rate + D = Percentage down-spread / 2 + Fint = Reference input frequency to PFD = Fref / NR + NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) + CLKS = NS - 1 = ISS_STEP_NUM[11:0] + NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) + CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] + ************************************* + */ + pp_atomctrl_internal_ss_info ss_info; + uint32_t freq_nom; + uint32_t tmp; + uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); + + /* for GDDR5 for all modes and DDR3 */ + if (1 == mpll_param.qdr) + freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); + else + freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); + + /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ + tmp = (freq_nom / reference_clock); + tmp = tmp * tmp; + + if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { + /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ + /* ss.Info.speed_spectrum_rate -- in unit of khz */ + /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ + /* = reference_clock * 5 / speed_spectrum_rate */ + uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; + + /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ + /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ + uint32_t clkv = + (uint32_t)((((131 * ss_info.speed_spectrum_percentage * + ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); + + mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); + mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); + } + } + + /* MCLK_PWRMGT_CNTL setup */ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); + + /* Save the result data to outpupt memory level structure */ + mclk->MclkFrequency = memory_clock; + mclk->MpllFuncCntl = mpll_func_cntl; + mclk->MpllFuncCntl_1 = mpll_func_cntl_1; + mclk->MpllFuncCntl_2 = mpll_func_cntl_2; + mclk->MpllAdFuncCntl = mpll_ad_func_cntl; + mclk->MpllDqFuncCntl = mpll_dq_func_cntl; + mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; + mclk->DllCntl = dll_cntl; + mclk->MpllSs1 = mpll_ss1; + mclk->MpllSs2 = mpll_ss2; + + return 0; +} + +static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock, + bool strobe_mode) +{ + uint8_t mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) + mc_para_index = 0x00; + else if (memory_clock > 47500) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); + } else { + if (memory_clock < 65000) + mc_para_index = 0x00; + else if (memory_clock > 135000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); + } + + return mc_para_index; +} + +static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) +{ + uint8_t mc_para_index; + + if (memory_clock < 10000) + mc_para_index = 0; + else if (memory_clock >= 80000) + mc_para_index = 0x0f; + else + mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); + + return mc_para_index; +} + + +static int tonga_populate_single_memory_level( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU72_Discrete_MemoryLevel *memory_level + ) +{ + uint32_t mvdd = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result = 0; + bool dll_state_on; + struct cgs_display_info info = {0}; + uint32_t mclk_edc_wr_enable_threshold = 40000; + uint32_t mclk_stutter_mode_threshold = 30000; + uint32_t mclk_edc_enable_threshold = 40000; + uint32_t mclk_strobe_mode_threshold = 40000; + + if (NULL != pptable_info->vdd_dep_on_mclk) { + result = tonga_get_dependency_volt_by_clk(hwmgr, + pptable_info->vdd_dep_on_mclk, + memory_clock, + &memory_level->MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE( + !result, + "can not find MinVddc voltage value from memory VDDC " + "voltage dependency table", + return result); + } + + if (data->mvdd_control == SMU7_VOLTAGE_CONTROL_NONE) + memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value; + else + memory_level->MinMvdd = mvdd; + + memory_level->EnabledForThrottle = 1; + memory_level->EnabledForActivity = 0; + memory_level->UpHyst = 0; + memory_level->DownHyst = 100; + memory_level->VoltageDownHyst = 0; + + /* Indicates maximum activity level for this performance level.*/ + memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target; + memory_level->StutterEnable = 0; + memory_level->StrobeEnable = 0; + memory_level->EdcReadEnable = 0; + memory_level->EdcWriteEnable = 0; + memory_level->RttEnable = 0; + + /* default set to low watermark. Highest level will be set to high later.*/ + memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + cgs_get_active_displays_info(hwmgr->device, &info); + data->display_timing.num_existing_displays = info.display_count; + + if ((mclk_stutter_mode_threshold != 0) && + (memory_clock <= mclk_stutter_mode_threshold) && + (!data->is_uvd_enabled) + && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1) + && (data->display_timing.num_existing_displays <= 2) + && (data->display_timing.num_existing_displays != 0)) + memory_level->StutterEnable = 1; + + /* decide strobe mode*/ + memory_level->StrobeEnable = (mclk_strobe_mode_threshold != 0) && + (memory_clock <= mclk_strobe_mode_threshold); + + /* decide EDC mode and memory clock ratio*/ + if (data->is_memory_gddr5) { + memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock, + memory_level->StrobeEnable); + + if ((mclk_edc_enable_threshold != 0) && + (memory_clock > mclk_edc_enable_threshold)) { + memory_level->EdcReadEnable = 1; + } + + if ((mclk_edc_wr_enable_threshold != 0) && + (memory_clock > mclk_edc_wr_enable_threshold)) { + memory_level->EdcWriteEnable = 1; + } + + if (memory_level->StrobeEnable) { + if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >= + ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) { + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } else { + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; + } + + } else { + dll_state_on = data->dll_default_on; + } + } else { + memory_level->StrobeRatio = + tonga_get_ddr3_mclk_frequency_ratio(memory_clock); + dll_state_on = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } + + result = tonga_calculate_mclk_params(hwmgr, + memory_clock, memory_level, memory_level->StrobeEnable, dll_state_on); + + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd); + /* MCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); + /* Indicates maximum activity level for this performance level.*/ + CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); + } + + return result; +} + +int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + struct smu7_dpm_table *dpm_table = &data->dpm_table; + int result; + + /* populate MCLK dpm table to SMU7 */ + uint32_t level_array_address = + smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, MemoryLevel); + uint32_t level_array_size = + sizeof(SMU72_Discrete_MemoryLevel) * + SMU72_MAX_LEVELS_MEMORY; + SMU72_Discrete_MemoryLevel *levels = + smu_data->smc_state_table.MemoryLevel; + uint32_t i; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", + return -EINVAL); + result = tonga_populate_single_memory_level( + hwmgr, + dpm_table->mclk_table.dpm_levels[i].value, + &(smu_data->smc_state_table.MemoryLevel[i])); + if (result) + return result; + } + + /* Only enable level 0 for now.*/ + smu_data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + + /* + * in order to prevent MC activity from stutter mode to push DPM up. + * the UVD change complements this by putting the MCLK in a higher state + * by default such that we are not effected by up threshold or and MCLK DPM latency. + */ + smu_data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.MemoryLevel[0].ActivityLevel); + + smu_data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = phm_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + /* set highest level watermark to high*/ + smu_data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change*/ + result = smu7_copy_bytes_to_smc(hwmgr, + level_array_address, (uint8_t *)levels, (uint32_t)level_array_size, + SMC_RAM_END); + + return result; +} + +static int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr, + uint32_t mclk, SMIO_Pattern *smio_pattern) +{ + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (SMU7_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { + /* Always round to higher voltage. */ + smio_pattern->Voltage = + data->mvdd_voltage_table.entries[i].value; + break; + } + } + + PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", + return -EINVAL); + } else { + return -EINVAL; + } + + return 0; +} + + +static int tonga_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + + SMIO_Pattern voltage_level; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + + /* The ACPI state should not do DPM on DC (or ever).*/ + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + table->ACPILevel.MinVoltage = + smu_data->smc_state_table.GraphicsLevel[0].MinVoltage; + + /* assign zero for now*/ + table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + /* divider ID for required SCLK*/ + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, + SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + + /* For various features to be enabled/disabled while this level is active.*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + /* SCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ + table->MemoryACPILevel.MinVoltage = + smu_data->smc_state_table.MemoryLevel[0].MinVoltage; + + /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/ + + if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level)) + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinMvdd = 0; + + /* Force reset on DLL*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); + + /* Disable DLL in ACPIState*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); + + /* Enable DLL bypass signal*/ + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK0_BYPASS, 0); + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK1_BYPASS, 0); + + table->MemoryACPILevel.DllCntl = + PP_HOST_TO_SMC_UL(dll_cntl); + table->MemoryACPILevel.MclkPwrmgtCntl = + PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); + table->MemoryACPILevel.MpllAdFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); + table->MemoryACPILevel.MpllDqFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl_1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); + table->MemoryACPILevel.MpllFuncCntl_2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); + table->MemoryACPILevel.MpllSs1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); + table->MemoryACPILevel.MpllSs2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + /* Indicates maximum activity level for this performance level.*/ + table->MemoryACPILevel.ActivityLevel = + PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); + + table->MemoryACPILevel.StutterEnable = 0; + table->MemoryACPILevel.StrobeEnable = 0; + table->MemoryACPILevel.EdcReadEnable = 0; + table->MemoryACPILevel.EdcWriteEnable = 0; + table->MemoryACPILevel.RttEnable = 0; + + return result; +} + +static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + pptable_info->mm_dep_table; + + table->UvdLevelCount = (uint8_t) (mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage.Vddc = + phm_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->UvdLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? + phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->UvdLevel[count].MinVoltage.Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + table->UvdLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi( + hwmgr, + table->UvdLevel[count].VclkFrequency, + ÷rs); + + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for Vclk clock", + return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for Dclk clock", + return result); + + table->UvdLevel[count].DclkDivider = + (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + } + + return result; + +} + +static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + pptable_info->mm_dep_table; + + table->VceLevelCount = (uint8_t) (mm_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = + mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage.Vddc = + phm_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->VceLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? + phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->VceLevel[count].MinVoltage.Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + table->VceLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + } + + return result; +} + +static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + pptable_info->mm_dep_table; + + table->AcpLevelCount = (uint8_t) (mm_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = + pptable_info->mm_dep_table->entries[count].aclk; + table->AcpLevel[count].MinVoltage.Vddc = + phm_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->AcpLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? + phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->AcpLevel[count].MinVoltage.Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + table->AcpLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + } + + return result; +} + +static int tonga_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + pptable_info->mm_dep_table; + + table->SamuBootLevel = 0; + table->SamuLevelCount = (uint8_t) (mm_table->count); + + for (count = 0; count < table->SamuLevelCount; count++) { + /* not sure whether we need evclk or not */ + table->SamuLevel[count].Frequency = + pptable_info->mm_dep_table->entries[count].samclock; + table->SamuLevel[count].MinVoltage.Vddc = + phm_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->SamuLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == SMU7_VOLTAGE_CONTROL_BY_SVID2) ? + phm_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->SamuLevel[count].MinVoltage.Vddci = + phm_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - VDDC_VDDCI_DELTA); + table->SamuLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->SamuLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((!result), + "can not find divide id for samu clock", return result); + + table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); + } + + return result; +} + +static int tonga_populate_memory_timing_parameters( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock, + struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs + ) +{ + uint32_t dramTiming; + uint32_t dramTiming2; + uint32_t burstTime; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + engine_clock, memory_clock); + + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + + return 0; +} + +static int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + int result = 0; + SMU72_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + + memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = tonga_populate_memory_timing_parameters + (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + + if (result) + break; + } + } + + if (!result) { + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU72_Discrete_MCArbDramTimingTable), + SMC_RAM_END + ); + } + + return result; +} + +static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table*/ + result = phm_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.GraphicsBootLevel)); + + if (result != 0) { + smu_data->smc_state_table.GraphicsBootLevel = 0; + pr_err("[powerplay] VBIOS did not find boot engine " + "clock value in dependency table. " + "Using Graphics DPM level 0 !"); + result = 0; + } + + result = phm_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(smu_data->smc_state_table.MemoryBootLevel)); + + if (result != 0) { + smu_data->smc_state_table.MemoryBootLevel = 0; + pr_err("[powerplay] VBIOS did not find boot " + "engine clock value in dependency table." + "Using Memory DPM level 0 !"); + result = 0; + } + + table->BootVoltage.Vddc = + phm_get_voltage_id(&(data->vddc_voltage_table), + data->vbios_boot_state.vddc_bootup_value); + table->BootVoltage.VddGfx = + phm_get_voltage_id(&(data->vddgfx_voltage_table), + data->vbios_boot_state.vddgfx_bootup_value); + table->BootVoltage.Vddci = + phm_get_voltage_id(&(data->vddci_voltage_table), + data->vbios_boot_state.vddci_bootup_value); + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return result; +} + +static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, + volt_with_cks, value; + uint16_t clock_freq_u16; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, + volt_offset = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + uint32_t hw_revision, dev_id; + struct cgs_system_info sys_info = {0}; + + stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; + + sys_info.size = sizeof(struct cgs_system_info); + + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV; + cgs_query_system_info(hwmgr->device, &sys_info); + hw_revision = (uint32_t)sys_info.value; + + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV; + cgs_query_system_info(hwmgr->device, &sys_info); + dev_id = (uint32_t)sys_info.value; + + /* Read SMU_Eefuse to read and calculate RO and determine + * if the part is SS or FF. if RO >= 1660MHz, part is FF. + */ + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (146 * 4)); + efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (148 * 4)); + efuse &= 0xFF000000; + efuse = efuse >> 24; + efuse2 &= 0xF; + + if (efuse2 == 1) + ro = (2300 - 1350) * efuse / 255 + 1350; + else + ro = (2500 - 1000) * efuse / 255 + 1000; + + if (ro >= 1660) + type = 0; + else + type = 1; + + /* Populate Stretch amount */ + smu_data->smc_state_table.ClockStretcherAmount = stretch_amount; + + + /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ + for (i = 0; i < sclk_table->count; i++) { + smu_data->smc_state_table.Sclk_CKS_masterEn0_7 |= + sclk_table->entries[i].cks_enable << i; + if (ASICID_IS_TONGA_P(dev_id, hw_revision)) { + volt_without_cks = (uint32_t)((7732 + 60 - ro - 20838 * + (sclk_table->entries[i].clk/100) / 10000) * 1000 / + (8730 - (5301 * (sclk_table->entries[i].clk/100) / 1000))); + volt_with_cks = (uint32_t)((5250 + 51 - ro - 2404 * + (sclk_table->entries[i].clk/100) / 100000) * 1000 / + (6146 - (3193 * (sclk_table->entries[i].clk/100) / 1000))); + } else { + volt_without_cks = (uint32_t)((14041 * + (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / + (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); + volt_with_cks = (uint32_t)((13946 * + (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / + (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); + } + if (volt_without_cks >= volt_with_cks) + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + + sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); + smu_data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; + } + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + STRETCH_ENABLE, 0x0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + staticEnable, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x0); + + /* Populate CKS Lookup Table */ + if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) + stretch_amount2 = 0; + else if (stretch_amount == 3 || stretch_amount == 4) + stretch_amount2 = 1; + else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + PP_ASSERT_WITH_CODE(false, + "Stretch Amount in PPTable not supported\n", + return -EINVAL); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL); + value &= 0xFFC2FF87; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = + tonga_clock_stretcher_lookup_table[stretch_amount2][0]; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = + tonga_clock_stretcher_lookup_table[stretch_amount2][1]; + clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(smu_data->smc_state_table. + GraphicsLevel[smu_data->smc_state_table.GraphicsDpmLevelCount - 1]. + SclkFrequency) / 100); + if (tonga_clock_stretcher_lookup_table[stretch_amount2][0] < + clock_freq_u16 && + tonga_clock_stretcher_lookup_table[stretch_amount2][1] > + clock_freq_u16) { + /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ + value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; + /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ + value |= (tonga_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; + /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ + value |= (tonga_clock_stretch_amount_conversion + [tonga_clock_stretcher_lookup_table[stretch_amount2][3]] + [stretch_amount]) << 3; + } + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].minFreq); + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].maxFreq); + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = + tonga_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; + smu_data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= + (tonga_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL, value); + + /* Populate DDT Lookup Table */ + for (i = 0; i < 4; i++) { + /* Assign the minimum and maximum VID stored + * in the last row of Clock Stretcher Voltage Table. + */ + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].minVID = + (uint8_t) tonga_clock_stretcher_ddt_table[type][i][2]; + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].maxVID = + (uint8_t) tonga_clock_stretcher_ddt_table[type][i][3]; + /* Loop through each SCLK and check the frequency + * to see if it lies within the frequency for clock stretcher. + */ + for (j = 0; j < smu_data->smc_state_table.GraphicsDpmLevelCount; j++) { + cks_setting = 0; + clock_freq = PP_SMC_TO_HOST_UL( + smu_data->smc_state_table.GraphicsLevel[j].SclkFrequency); + /* Check the allowed frequency against the sclk level[j]. + * Sclk's endianness has already been converted, + * and it's in 10Khz unit, + * as opposed to Data table, which is in Mhz unit. + */ + if (clock_freq >= tonga_clock_stretcher_ddt_table[type][i][0] * 100) { + cks_setting |= 0x2; + if (clock_freq < tonga_clock_stretcher_ddt_table[type][i][1] * 100) + cks_setting |= 0x1; + } + smu_data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); + } + CONVERT_FROM_HOST_TO_SMC_US(smu_data->smc_state_table. + ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL); + value &= 0xFFFFFFFE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL, value); + + return 0; +} + +static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint16_t config; + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { + /* Splitted mode */ + config = VR_SVI2_PLANE_1; + table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT); + + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= config; + } else { + pr_err("VDDC and VDDGFX should " + "be both on SVI2 control in splitted mode !\n"); + } + } else { + /* Merged mode */ + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT); + + /* Set Vddc Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + pr_err("VDDC should be on " + "SVI2 control in merged mode !\n"); + } + } + + /* Set Vddci Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT); + } else if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT); + } + + /* Set Mvdd Voltage Controller */ + if (SMU7_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + config = VR_SMIO_PATTERN_2; + table->VRConfig |= (config<<VRCONF_MVDD_SHIFT); + } + + return 0; +} + +static int tonga_init_arb_table_index(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t tmp; + int result; + + /* + * This is a read-modify-write on the first byte of the ARB table. + * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure + * is the field 'current'. + * This solution is ugly, but we never write the whole table only + * individual fields in it. + * In reality this field should not be in that structure + * but in a soft register. + */ + result = smu7_read_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, &tmp, SMC_RAM_END); + + if (result != 0) + return result; + + tmp &= 0x00FFFFFF; + tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; + + return smu7_write_smc_sram_dword(hwmgr, + smu_data->smu7_data.arb_table_start, tmp, SMC_RAM_END); +} + + +static int tonga_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; + SMU72_Discrete_DpmTable *dpm_table = &(smu_data->smc_state_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; + int i, j, k; + const uint16_t *pdef1, *pdef2; + + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usTDP * 256)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usConfigurableTDP * 256)); + + PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, + "Target Operating Temp is out of Range !", + ); + + dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->dte_ambient_temp_base; + + dpm_table->BAPM_TEMP_GRADIENT = + PP_HOST_TO_SMC_UL(defaults->bapm_temp_gradient); + pdef1 = defaults->bapmti_r; + pdef2 = defaults->bapmti_rc; + + for (i = 0; i < SMU72_DTE_ITERATIONS; i++) { + for (j = 0; j < SMU72_DTE_SOURCES; j++) { + for (k = 0; k < SMU72_DTE_SINKS; k++) { + dpm_table->BAPMTI_R[i][j][k] = + PP_HOST_TO_SMC_US(*pdef1); + dpm_table->BAPMTI_RC[i][j][k] = + PP_HOST_TO_SMC_US(*pdef2); + pdef1++; + pdef2++; + } + } + } + + return 0; +} + +static int tonga_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; + + smu_data->power_tune_table.SviLoadLineEn = defaults->svi_load_line_en; + smu_data->power_tune_table.SviLoadLineVddC = defaults->svi_load_line_vddC; + smu_data->power_tune_table.SviLoadLineTrimVddC = 3; + smu_data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int tonga_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + /* TDC number of fraction bits are changed from 8 to 7 + * for Fiji as requested by SMC team + */ + tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 256); + smu_data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + smu_data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->tdc_vddc_throttle_release_limit_perc; + smu_data->power_tune_table.TDC_MAWt = defaults->tdc_mawt; + + return 0; +} + +static int tonga_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + const struct tonga_pt_defaults *defaults = smu_data->power_tune_defaults; + uint32_t temp; + + if (smu7_read_smc_sram_dword(hwmgr, + fuse_table_offset + + offsetof(SMU72_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 " + "(SviLoadLineEn) from SMC Failed !", + return -EINVAL); + else + smu_data->power_tune_table.TdcWaterfallCtl = defaults->tdc_waterfall_ctl; + + return 0; +} + +static int tonga_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + int i; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.LPMLTemperatureScaler[i] = 0; + + return 0; +} + +static int tonga_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + + if ((hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity & (1 << 15)) || + (hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity == 0)) + hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity = hwmgr->thermal_controller. + advanceFanControlParameters.usDefaultFanOutputSensitivity; + + smu_data->power_tune_table.FuzzyFan_PwmSetDelta = + PP_HOST_TO_SMC_US(hwmgr->thermal_controller. + advanceFanControlParameters.usFanOutputSensitivity); + return 0; +} + +static int tonga_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + smu_data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int tonga_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint16_t hi_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t lo_sidd = smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + + hi_sidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + lo_sidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + smu_data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(hi_sidd); + smu_data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(lo_sidd); + + return 0; +} + +static int tonga_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t pm_fuse_table_offset; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed !", + return -EINVAL); + + /* DW6 */ + if (tonga_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed !", + return -EINVAL); + /* DW7 */ + if (tonga_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed !", + return -EINVAL); + /* DW8 */ + if (tonga_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl Failed !", + return -EINVAL); + + /* DW9-DW12 */ + if (tonga_populate_temperature_scaler(hwmgr) != 0) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed !", + return -EINVAL); + + /* DW13-DW14 */ + if (tonga_populate_fuzzy_fan(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate Fuzzy Fan " + "Control parameters Failed !", + return -EINVAL); + + /* DW15-DW18 */ + if (tonga_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed !", + return -EINVAL); + + /* DW20 */ + if (tonga_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE( + false, + "Attempt to populate BapmVddCBaseLeakage " + "Hi and Lo Sidd Failed !", + return -EINVAL); + + if (smu7_copy_bytes_to_smc(hwmgr, pm_fuse_table_offset, + (uint8_t *)&smu_data->power_tune_table, + sizeof(struct SMU72_Discrete_PmFuses), SMC_RAM_END)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed !", + return -EINVAL); + } + return 0; +} + +static int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr, + SMU72_Discrete_MCRegisters *mc_reg_table) +{ + const struct tonga_smumgr *smu_data = (struct tonga_smumgr *)hwmgr->smu_backend; + + uint32_t i, j; + + for (i = 0, j = 0; j < smu_data->mc_reg_table.last; j++) { + if (smu_data->mc_reg_table.validflag & 1<<j) { + PP_ASSERT_WITH_CODE( + i < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE, + "Index of mc_reg_table->address[] array " + "out of boundary", + return -EINVAL); + mc_reg_table->address[i].s0 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + PP_HOST_TO_SMC_US(smu_data->mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + + mc_reg_table->last = (uint8_t)i; + + return 0; +} + +/*convert register values from driver to SMC format */ +static void tonga_convert_mc_registers( + const struct tonga_mc_reg_entry *entry, + SMU72_Discrete_MCRegisterSet *data, + uint32_t num_entries, uint32_t valid_flag) +{ + uint32_t i, j; + + for (i = 0, j = 0; j < num_entries; j++) { + if (valid_flag & 1<<j) { + data->value[i] = PP_HOST_TO_SMC_UL(entry->mc_data[j]); + i++; + } + } +} + +static int tonga_convert_mc_reg_table_entry_to_smc( + struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + SMU72_Discrete_MCRegisterSet *mc_reg_table_data + ) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t i = 0; + + for (i = 0; i < smu_data->mc_reg_table.num_entries; i++) { + if (memory_clock <= + smu_data->mc_reg_table.mc_reg_table_entry[i].mclk_max) { + break; + } + } + + if ((i == smu_data->mc_reg_table.num_entries) && (i > 0)) + --i; + + tonga_convert_mc_registers(&smu_data->mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, smu_data->mc_reg_table.last, + smu_data->mc_reg_table.validflag); + + return 0; +} + +static int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, + SMU72_Discrete_MCRegisters *mc_regs) +{ + int result = 0; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + int res; + uint32_t i; + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + res = tonga_convert_mc_reg_table_entry_to_smc( + hwmgr, + data->dpm_table.mclk_table.dpm_levels[i].value, + &mc_regs->data[i] + ); + + if (0 != res) + result = res; + } + + return result; +} + +static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + uint32_t address; + int32_t result; + + if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) + return 0; + + + memset(&smu_data->mc_regs, 0, sizeof(SMU72_Discrete_MCRegisters)); + + result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(smu_data->mc_regs)); + + if (result != 0) + return result; + + + address = smu_data->smu7_data.mc_reg_table_start + + (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]); + + return smu7_copy_bytes_to_smc( + hwmgr, address, + (uint8_t *)&smu_data->mc_regs.data[0], + sizeof(SMU72_Discrete_MCRegisterSet) * + data->dpm_table.mclk_table.count, + SMC_RAM_END); +} + +static int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + + memset(&smu_data->mc_regs, 0x00, sizeof(SMU72_Discrete_MCRegisters)); + result = tonga_populate_mc_reg_address(hwmgr, &(smu_data->mc_regs)); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize MCRegTable for the MC register addresses !", + return result;); + + result = tonga_convert_mc_reg_table_to_smc(hwmgr, &smu_data->mc_regs); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize MCRegTable for driver state !", + return result;); + + return smu7_copy_bytes_to_smc(hwmgr, smu_data->smu7_data.mc_reg_table_start, + (uint8_t *)&smu_data->mc_regs, sizeof(SMU72_Discrete_MCRegisters), SMC_RAM_END); +} + +static void tonga_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (table_info && + table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && + table_info->cac_dtp_table->usPowerTuneDataSetID) + smu_data->power_tune_defaults = + &tonga_power_tune_data_set_array + [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; + else + smu_data->power_tune_defaults = &tonga_power_tune_data_set_array[0]; +} + +static void tonga_save_default_power_profile(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *data = (struct tonga_smumgr *)(hwmgr->smu_backend); + struct SMU72_Discrete_GraphicsLevel *levels = + data->smc_state_table.GraphicsLevel; + unsigned min_level = 1; + + hwmgr->default_gfx_power_profile.activity_threshold = + be16_to_cpu(levels[0].ActivityLevel); + hwmgr->default_gfx_power_profile.up_hyst = levels[0].UpHyst; + hwmgr->default_gfx_power_profile.down_hyst = levels[0].DownHyst; + hwmgr->default_gfx_power_profile.type = AMD_PP_GFX_PROFILE; + + hwmgr->default_compute_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->default_compute_power_profile.type = AMD_PP_COMPUTE_PROFILE; + + /* Workaround compute SDMA instability: disable lowest SCLK + * DPM level. Optimize compute power profile: Use only highest + * 2 power levels (if more than 2 are available), Hysteresis: + * 0ms up, 5ms down + */ + if (data->smc_state_table.GraphicsDpmLevelCount > 2) + min_level = data->smc_state_table.GraphicsDpmLevelCount - 2; + else if (data->smc_state_table.GraphicsDpmLevelCount == 2) + min_level = 1; + else + min_level = 0; + hwmgr->default_compute_power_profile.min_sclk = + be32_to_cpu(levels[min_level].SclkFrequency); + hwmgr->default_compute_power_profile.up_hyst = 0; + hwmgr->default_compute_power_profile.down_hyst = 5; + + hwmgr->gfx_power_profile = hwmgr->default_gfx_power_profile; + hwmgr->compute_power_profile = hwmgr->default_compute_power_profile; +} + +static int tonga_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + SMU72_Discrete_DpmTable *table = &(smu_data->smc_state_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + uint8_t i; + pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; + + + memset(&(smu_data->smc_state_table), 0x00, sizeof(smu_data->smc_state_table)); + + tonga_initialize_power_tune_defaults(hwmgr); + + if (SMU7_VOLTAGE_CONTROL_NONE != data->voltage_control) + tonga_populate_smc_voltage_tables(hwmgr, table); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN); + + if (i == 1 || i == 0) + table->SystemFlags |= 0x40; + + if (data->ulv_supported && table_info->us_ulv_voltage_offset) { + result = tonga_populate_ulv_state(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ULV state !", + return result;); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, 0x40035); + } + + result = tonga_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Link Level !", return result); + + result = tonga_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Graphics Level !", return result); + + result = tonga_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Memory Level !", return result); + + result = tonga_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ACPI Level !", return result); + + result = tonga_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize VCE Level !", return result); + + result = tonga_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize ACP Level !", return result); + + result = tonga_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize SAMU Level !", return result); + + /* Since only the initial state is completely set up at this + * point (the other states are just copies of the boot state) we only + * need to populate the ARB settings for the initial state. + */ + result = tonga_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to Write ARB settings for the initial state.", + return result;); + + result = tonga_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize UVD Level !", return result); + + result = tonga_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to initialize Boot Level !", return result); + + tonga_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate BAPM Parameters !", return result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = tonga_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate Clock Stretcher Data Table !", + return result;); + } + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + table_info->cac_dtp_table->usTargetOperatingTemp * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * + SMU7_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + + /* + * Cail reads current link status and reports it as cap (we cannot + * change this due to some previous issues we had) + * SMC drops the link status to lowest level after enabling + * DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again + * but this time Cail reads current link status which was set to low by + * SMC and reports it as cap to powerplay + * To avoid it, we set PCIeBootLinkLevel to highest dpm level + */ + PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + + table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count); + + table->PCIeGenInterval = 1; + + result = tonga_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(!result, + "Failed to populate VRConfig setting !", return result); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, + &gpio_pin_assignment)) { + table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, + &gpio_pin_assignment)) { + table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } else { + table->AcDcGpio = SMU7_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition); + + if (0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, + THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment)) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + + table->ThermOutPolarity = + (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & + (1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1 : 0; + + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO*/ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot) && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CombinePCCWithThermalSignal)){ + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } + } else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++) + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + offsetof(SMU72_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU72_Discrete_DpmTable) - 3 * sizeof(SMU72_PIDController), + SMC_RAM_END); + + PP_ASSERT_WITH_CODE(!result, + "Failed to upload dpm data to SMC memory !", return result;); + + result = tonga_init_arb_table_index(hwmgr); + PP_ASSERT_WITH_CODE(!result, + "Failed to upload arb data to SMC memory !", return result); + + tonga_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE((!result), + "Failed to populate initialize pm fuses !", return result); + + result = tonga_populate_initial_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((!result), + "Failed to populate initialize MC Reg table !", return result); + + tonga_save_default_power_profile(hwmgr); + + return 0; +} + +static int tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) + return 0; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + if (0 == smu_data->smu7_data.fan_table_start) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - + hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = smu7_get_xclk(hwmgr); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); + + fan_table.FanControl_GL_Flag = 1; + + res = smu7_copy_bytes_to_smc(hwmgr, + smu_data->smu7_data.fan_table_start, + (uint8_t *)&fan_table, + (uint32_t)sizeof(fan_table), + SMC_RAM_END); + + return 0; +} + + +static int tonga_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return tonga_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (hwmgr->gfx_arbiter.sclk_threshold != + data->low_sclk_interrupt_threshold)) { + data->low_sclk_interrupt_threshold = + hwmgr->gfx_arbiter.sclk_threshold; + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = smu7_copy_bytes_to_smc( + hwmgr, + smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + SMC_RAM_END); + } + + result = tonga_update_and_upload_mc_reg_table(hwmgr); + + PP_ASSERT_WITH_CODE((!result), + "Failed to upload MC reg table !", + return result); + + result = tonga_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((result == 0), + "Failed to program memory timing parameters !", + ); + + return result; +} + +static uint32_t tonga_get_offsetof(uint32_t type, uint32_t member) +{ + switch (type) { + case SMU_SoftRegisters: + switch (member) { + case HandshakeDisables: + return offsetof(SMU72_SoftRegisters, HandshakeDisables); + case VoltageChangeTimeout: + return offsetof(SMU72_SoftRegisters, VoltageChangeTimeout); + case AverageGraphicsActivity: + return offsetof(SMU72_SoftRegisters, AverageGraphicsActivity); + case PreVBlankGap: + return offsetof(SMU72_SoftRegisters, PreVBlankGap); + case VBlankTimeout: + return offsetof(SMU72_SoftRegisters, VBlankTimeout); + case UcodeLoadStatus: + return offsetof(SMU72_SoftRegisters, UcodeLoadStatus); + case DRAM_LOG_ADDR_H: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_H); + case DRAM_LOG_ADDR_L: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_ADDR_L); + case DRAM_LOG_PHY_ADDR_H: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_H); + case DRAM_LOG_PHY_ADDR_L: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_PHY_ADDR_L); + case DRAM_LOG_BUFF_SIZE: + return offsetof(SMU72_SoftRegisters, DRAM_LOG_BUFF_SIZE); + } + case SMU_Discrete_DpmTable: + switch (member) { + case UvdBootLevel: + return offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); + case VceBootLevel: + return offsetof(SMU72_Discrete_DpmTable, VceBootLevel); + case SamuBootLevel: + return offsetof(SMU72_Discrete_DpmTable, SamuBootLevel); + case LowSclkInterruptThreshold: + return offsetof(SMU72_Discrete_DpmTable, LowSclkInterruptThreshold); + } + } + pr_warn("can't get the offset of type %x member %x\n", type, member); + return 0; +} + +static uint32_t tonga_get_mac_definition(uint32_t value) +{ + switch (value) { + case SMU_MAX_LEVELS_GRAPHICS: + return SMU72_MAX_LEVELS_GRAPHICS; + case SMU_MAX_LEVELS_MEMORY: + return SMU72_MAX_LEVELS_MEMORY; + case SMU_MAX_LEVELS_LINK: + return SMU72_MAX_LEVELS_LINK; + case SMU_MAX_ENTRIES_SMIO: + return SMU72_MAX_ENTRIES_SMIO; + case SMU_MAX_LEVELS_VDDC: + return SMU72_MAX_LEVELS_VDDC; + case SMU_MAX_LEVELS_VDDGFX: + return SMU72_MAX_LEVELS_VDDGFX; + case SMU_MAX_LEVELS_VDDCI: + return SMU72_MAX_LEVELS_VDDCI; + case SMU_MAX_LEVELS_MVDD: + return SMU72_MAX_LEVELS_MVDD; + } + pr_warn("can't get the mac value %x\n", value); + + return 0; +} + +static int tonga_update_uvd_smc_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + smu_data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + smu_data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= smu_data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, + mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.UvdBootLevel)); + return 0; +} + +static int tonga_update_vce_smc_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = + (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + + smu_data->smc_state_table.VceBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= smu_data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)1 << smu_data->smc_state_table.VceBootLevel); + return 0; +} + +static int tonga_update_samu_smc_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + + smu_data->smc_state_table.SamuBootLevel = 0; + mm_boot_level_offset = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, SamuBootLevel); + + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFFFFFF00; + mm_boot_level_value |= smu_data->smc_state_table.SamuBootLevel << 0; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_SAMUDPM_SetEnabledMask, + (uint32_t)(1 << smu_data->smc_state_table.SamuBootLevel)); + return 0; +} + +static int tonga_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type) +{ + switch (type) { + case SMU_UVD_TABLE: + tonga_update_uvd_smc_table(hwmgr); + break; + case SMU_VCE_TABLE: + tonga_update_vce_smc_table(hwmgr); + break; + case SMU_SAMU_TABLE: + tonga_update_samu_smc_table(hwmgr); + break; + default: + break; + } + return 0; +} + +static int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + + uint32_t tmp; + int result; + bool error = false; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, DpmTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.dpm_table_start = tmp; + + error |= (result != 0); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, SoftRegisters), + &tmp, SMC_RAM_END); + + if (!result) { + data->soft_regs_start = tmp; + smu_data->smu7_data.soft_regs_start = tmp; + } + + error |= (result != 0); + + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, mcRegisterTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.mc_reg_table_start = tmp; + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, FanTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.fan_table_start = tmp; + + error |= (result != 0); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, mcArbDramTimingTable), + &tmp, SMC_RAM_END); + + if (!result) + smu_data->smu7_data.arb_table_start = tmp; + + error |= (result != 0); + + result = smu7_read_smc_sram_dword(hwmgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, Version), + &tmp, SMC_RAM_END); + + if (!result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (result != 0); + + return error ? 1 : 0; +} + +/*---------------------------MC----------------------------*/ + +static uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +static bool tonga_check_s0_mc_reg_index(uint16_t in_reg, uint16_t *out_reg) +{ + bool result = true; + + switch (in_reg) { + case mmMC_SEQ_RAS_TIMING: + *out_reg = mmMC_SEQ_RAS_TIMING_LP; + break; + + case mmMC_SEQ_DLL_STBY: + *out_reg = mmMC_SEQ_DLL_STBY_LP; + break; + + case mmMC_SEQ_G5PDX_CMD0: + *out_reg = mmMC_SEQ_G5PDX_CMD0_LP; + break; + + case mmMC_SEQ_G5PDX_CMD1: + *out_reg = mmMC_SEQ_G5PDX_CMD1_LP; + break; + + case mmMC_SEQ_G5PDX_CTRL: + *out_reg = mmMC_SEQ_G5PDX_CTRL_LP; + break; + + case mmMC_SEQ_CAS_TIMING: + *out_reg = mmMC_SEQ_CAS_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING: + *out_reg = mmMC_SEQ_MISC_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING2: + *out_reg = mmMC_SEQ_MISC_TIMING2_LP; + break; + + case mmMC_SEQ_PMG_DVS_CMD: + *out_reg = mmMC_SEQ_PMG_DVS_CMD_LP; + break; + + case mmMC_SEQ_PMG_DVS_CTL: + *out_reg = mmMC_SEQ_PMG_DVS_CTL_LP; + break; + + case mmMC_SEQ_RD_CTL_D0: + *out_reg = mmMC_SEQ_RD_CTL_D0_LP; + break; + + case mmMC_SEQ_RD_CTL_D1: + *out_reg = mmMC_SEQ_RD_CTL_D1_LP; + break; + + case mmMC_SEQ_WR_CTL_D0: + *out_reg = mmMC_SEQ_WR_CTL_D0_LP; + break; + + case mmMC_SEQ_WR_CTL_D1: + *out_reg = mmMC_SEQ_WR_CTL_D1_LP; + break; + + case mmMC_PMG_CMD_EMRS: + *out_reg = mmMC_SEQ_PMG_CMD_EMRS_LP; + break; + + case mmMC_PMG_CMD_MRS: + *out_reg = mmMC_SEQ_PMG_CMD_MRS_LP; + break; + + case mmMC_PMG_CMD_MRS1: + *out_reg = mmMC_SEQ_PMG_CMD_MRS1_LP; + break; + + case mmMC_SEQ_PMG_TIMING: + *out_reg = mmMC_SEQ_PMG_TIMING_LP; + break; + + case mmMC_PMG_CMD_MRS2: + *out_reg = mmMC_SEQ_PMG_CMD_MRS2_LP; + break; + + case mmMC_SEQ_WR_CTL_2: + *out_reg = mmMC_SEQ_WR_CTL_2_LP; + break; + + default: + result = false; + break; + } + + return result; +} + +static int tonga_set_s0_mc_reg_index(struct tonga_mc_reg_table *table) +{ + uint32_t i; + uint16_t address; + + for (i = 0; i < table->last; i++) { + table->mc_reg_address[i].s0 = + tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1, + &address) ? + address : + table->mc_reg_address[i].s1; + } + return 0; +} + +static int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, + struct tonga_mc_reg_table *ni_table) +{ + uint8_t i, j; + + PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), + "Invalid VramInfo table.", return -EINVAL); + + for (i = 0; i < table->last; i++) + ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + + ni_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + ni_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + ni_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + + ni_table->num_entries = table->num_entries; + + return 0; +} + +static int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr, + struct tonga_mc_reg_table *table) +{ + uint8_t i, j, k; + uint32_t temp_reg; + struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend); + + for (i = 0, j = table->last; i < table->last; i++) { + PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + switch (table->mc_reg_address[i].s1) { + + case mmMC_SEQ_MISC1: + temp_reg = cgs_read_register(hwmgr->device, + mmMC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + } + j++; + PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + + if (!data->is_memory_gddr5) + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + + if (!data->is_memory_gddr5) { + table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + j++; + PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + } + + break; + + case mmMC_SEQ_RESERVE_M: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -EINVAL); + break; + + default: + break; + } + + } + + table->last = j; + + return 0; +} + +static int tonga_set_valid_flag(struct tonga_mc_reg_table *table) +{ + uint8_t i, j; + + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != + table->mc_reg_table_entry[j].mc_data[i]) { + table->validflag |= (1<<i); + break; + } + } + } + + return 0; +} + +static int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct tonga_smumgr *smu_data = (struct tonga_smumgr *)(hwmgr->smu_backend); + pp_atomctrl_mc_reg_table *table; + struct tonga_mc_reg_table *ni_table = &smu_data->mc_reg_table; + uint8_t module_index = tonga_get_memory_modile_index(hwmgr); + + table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); + + if (table == NULL) + return -ENOMEM; + + /* Program additional LP registers that are no longer programmed by VBIOS */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, + cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, + cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, + cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, + cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); + + memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table)); + + result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); + + if (!result) + result = tonga_copy_vbios_smc_reg_table(table, ni_table); + + if (!result) { + tonga_set_s0_mc_reg_index(ni_table); + result = tonga_set_mc_special_registers(hwmgr, ni_table); + } + + if (!result) + tonga_set_valid_flag(ni_table); + + kfree(table); + + return result; +} + +static bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static int tonga_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, + struct amd_pp_profile *request) +{ + struct tonga_smumgr *smu_data = (struct tonga_smumgr *) + (hwmgr->smu_backend); + struct SMU72_Discrete_GraphicsLevel *levels = + smu_data->smc_state_table.GraphicsLevel; + uint32_t array = smu_data->smu7_data.dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU72_Discrete_GraphicsLevel) * + SMU72_MAX_LEVELS_GRAPHICS; + uint32_t i; + + for (i = 0; i < smu_data->smc_state_table.GraphicsDpmLevelCount; i++) { + levels[i].ActivityLevel = + cpu_to_be16(request->activity_threshold); + levels[i].EnabledForActivity = 1; + levels[i].UpHyst = request->up_hyst; + levels[i].DownHyst = request->down_hyst; + } + + return smu7_copy_bytes_to_smc(hwmgr, array, (uint8_t *)levels, + array_size, SMC_RAM_END); +} + const struct pp_smumgr_func tonga_smu_funcs = { .smu_init = &tonga_smu_init, .smu_fini = &smu7_smu_fini, diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h index 8c4f761d5bc8..5d70a00348e2 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h @@ -25,8 +25,26 @@ #define _TONGA_SMUMGR_H_ #include "smu72_discrete.h" - #include "smu7_smumgr.h" +#include "smu72.h" + + +#define ASICID_IS_TONGA_P(wDID, bRID) \ + (((wDID == 0x6930) && ((bRID == 0xF0) || (bRID == 0xF1) || (bRID == 0xFF))) \ + || ((wDID == 0x6920) && ((bRID == 0) || (bRID == 1)))) + +struct tonga_pt_defaults { + uint8_t svi_load_line_en; + uint8_t svi_load_line_vddC; + uint8_t tdc_vddc_throttle_release_limit_perc; + uint8_t tdc_mawt; + uint8_t tdc_waterfall_ctl; + uint8_t dte_ambient_temp_base; + uint32_t display_cac; + uint32_t bapm_temp_gradient; + uint16_t bapmti_r[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; + uint16_t bapmti_rc[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; +}; struct tonga_mc_reg_entry { uint32_t mclk_max; diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 97c94f9683fa..e4d3b4ec4e92 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -133,6 +133,7 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched, entity->rq = rq; entity->sched = sched; + spin_lock_init(&entity->rq_lock); spin_lock_init(&entity->queue_lock); r = kfifo_alloc(&entity->job_queue, jobs * sizeof(void *), GFP_KERNEL); if (r) @@ -204,7 +205,6 @@ static bool amd_sched_entity_is_ready(struct amd_sched_entity *entity) void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, struct amd_sched_entity *entity) { - struct amd_sched_rq *rq = entity->rq; int r; if (!amd_sched_entity_is_initialized(sched, entity)) @@ -218,7 +218,7 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, else r = wait_event_killable(sched->job_scheduled, amd_sched_entity_is_idle(entity)); - amd_sched_rq_remove_entity(rq, entity); + amd_sched_entity_set_rq(entity, NULL); if (r) { struct amd_sched_job *job; @@ -227,8 +227,14 @@ void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, */ kthread_park(sched->thread); kthread_unpark(sched->thread); - while (kfifo_out(&entity->job_queue, &job, sizeof(job))) + while (kfifo_out(&entity->job_queue, &job, sizeof(job))) { + struct amd_sched_fence *s_fence = job->s_fence; + amd_sched_fence_scheduled(s_fence); + dma_fence_set_error(&s_fence->finished, -ESRCH); + amd_sched_fence_finished(s_fence); + dma_fence_put(&s_fence->finished); sched->ops->free_job(job); + } } kfifo_free(&entity->job_queue); @@ -251,6 +257,24 @@ static void amd_sched_entity_clear_dep(struct dma_fence *f, struct dma_fence_cb dma_fence_put(f); } +void amd_sched_entity_set_rq(struct amd_sched_entity *entity, + struct amd_sched_rq *rq) +{ + if (entity->rq == rq) + return; + + spin_lock(&entity->rq_lock); + + if (entity->rq) + amd_sched_rq_remove_entity(entity->rq, entity); + + entity->rq = rq; + if (rq) + amd_sched_rq_add_entity(rq, entity); + + spin_unlock(&entity->rq_lock); +} + bool amd_sched_dependency_optimized(struct dma_fence* fence, struct amd_sched_entity *entity) { @@ -308,7 +332,7 @@ static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity) } static struct amd_sched_job * -amd_sched_entity_pop_job(struct amd_sched_entity *entity) +amd_sched_entity_peek_job(struct amd_sched_entity *entity) { struct amd_gpu_scheduler *sched = entity->sched; struct amd_sched_job *sched_job; @@ -348,14 +372,15 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job) /* first job wakes up scheduler */ if (first) { /* Add the entity to the run queue */ + spin_lock(&entity->rq_lock); amd_sched_rq_add_entity(entity->rq, entity); + spin_unlock(&entity->rq_lock); amd_sched_wakeup(sched); } return added; } -/* job_finish is called after hw fence signaled, and - * the job had already been deleted from ring_mirror_list +/* job_finish is called after hw fence signaled */ static void amd_sched_job_finish(struct work_struct *work) { @@ -381,6 +406,7 @@ static void amd_sched_job_finish(struct work_struct *work) schedule_delayed_work(&next->work_tdr, sched->timeout); } spin_unlock(&sched->job_list_lock); + dma_fence_put(&s_job->s_fence->finished); sched->ops->free_job(s_job); } @@ -396,6 +422,9 @@ static void amd_sched_job_begin(struct amd_sched_job *s_job) { struct amd_gpu_scheduler *sched = s_job->sched; + dma_fence_add_callback(&s_job->s_fence->finished, &s_job->finish_cb, + amd_sched_job_finish_cb); + spin_lock(&sched->job_list_lock); list_add_tail(&s_job->node, &sched->ring_mirror_list); if (sched->timeout != MAX_SCHEDULE_TIMEOUT && @@ -488,8 +517,6 @@ void amd_sched_entity_push_job(struct amd_sched_job *sched_job) struct amd_sched_entity *entity = sched_job->s_entity; trace_amd_sched_job(sched_job); - dma_fence_add_callback(&sched_job->s_fence->finished, &sched_job->finish_cb, - amd_sched_job_finish_cb); wait_event(entity->sched->job_scheduled, amd_sched_entity_in(sched_job)); } @@ -560,6 +587,7 @@ static void amd_sched_process_job(struct dma_fence *f, struct dma_fence_cb *cb) container_of(cb, struct amd_sched_fence, cb); struct amd_gpu_scheduler *sched = s_fence->sched; + dma_fence_get(&s_fence->finished); atomic_dec(&sched->hw_rq_count); amd_sched_fence_finished(s_fence); @@ -600,7 +628,7 @@ static int amd_sched_main(void *param) if (!entity) continue; - sched_job = amd_sched_entity_pop_job(entity); + sched_job = amd_sched_entity_peek_job(entity); if (!sched_job) continue; @@ -611,6 +639,7 @@ static int amd_sched_main(void *param) fence = sched->ops->run_job(sched_job); amd_sched_fence_scheduled(s_fence); + if (fence) { s_fence->parent = dma_fence_get(fence); r = dma_fence_add_callback(fence, &s_fence->cb, diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h index f9d8f28efd16..52c8e5447624 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h @@ -39,6 +39,7 @@ struct amd_sched_rq; struct amd_sched_entity { struct list_head list; struct amd_sched_rq *rq; + spinlock_t rq_lock; struct amd_gpu_scheduler *sched; spinlock_t queue_lock; @@ -115,9 +116,14 @@ struct amd_sched_backend_ops { enum amd_sched_priority { AMD_SCHED_PRIORITY_MIN, - AMD_SCHED_PRIORITY_NORMAL = AMD_SCHED_PRIORITY_MIN, + AMD_SCHED_PRIORITY_LOW = AMD_SCHED_PRIORITY_MIN, + AMD_SCHED_PRIORITY_NORMAL, + AMD_SCHED_PRIORITY_HIGH_SW, + AMD_SCHED_PRIORITY_HIGH_HW, AMD_SCHED_PRIORITY_KERNEL, - AMD_SCHED_PRIORITY_MAX + AMD_SCHED_PRIORITY_MAX, + AMD_SCHED_PRIORITY_INVALID = -1, + AMD_SCHED_PRIORITY_UNSET = -2 }; /** @@ -150,6 +156,8 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched, void amd_sched_entity_fini(struct amd_gpu_scheduler *sched, struct amd_sched_entity *entity); void amd_sched_entity_push_job(struct amd_sched_job *sched_job); +void amd_sched_entity_set_rq(struct amd_sched_entity *entity, + struct amd_sched_rq *rq); int amd_sched_fence_slab_init(void); void amd_sched_fence_slab_fini(void); @@ -167,4 +175,11 @@ void amd_sched_job_recovery(struct amd_gpu_scheduler *sched); bool amd_sched_dependency_optimized(struct dma_fence* fence, struct amd_sched_entity *entity); void amd_sched_job_kickout(struct amd_sched_job *s_job); + +static inline enum amd_sched_priority +amd_sched_get_job_priority(struct amd_sched_job *job) +{ + return (job->s_entity->rq - job->sched->sched_rq); +} + #endif diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 6f3849ec0c1d..9555a3542022 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -713,7 +713,7 @@ static struct drm_encoder *ast_best_single_encoder(struct drm_connector *connect int enc_id = connector->encoder_ids[0]; /* pick the encoder ids */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 6a91e62da2f4..a24a18fbd65a 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -213,7 +213,7 @@ bochs_connector_best_encoder(struct drm_connector *connector) int enc_id = connector->encoder_ids[0]; /* pick the encoder ids */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c index a4c4a465b385..cd23b1b28259 100644 --- a/drivers/gpu/drm/cirrus/cirrus_mode.c +++ b/drivers/gpu/drm/cirrus/cirrus_mode.c @@ -457,7 +457,7 @@ static struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector int enc_id = connector->encoder_ids[0]; /* pick the encoder ids */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index bf8ca515c958..37445d50816a 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -716,7 +716,7 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, struct drm_mode_config *config = &dev->mode_config; if (property == config->prop_fb_id) { - struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, val); + struct drm_framebuffer *fb = drm_framebuffer_lookup(dev, NULL, val); drm_atomic_set_fb_for_plane(state, fb); if (fb) drm_framebuffer_put(fb); @@ -732,7 +732,7 @@ static int drm_atomic_plane_set_property(struct drm_plane *plane, return -EINVAL; } else if (property == config->prop_crtc_id) { - struct drm_crtc *crtc = drm_crtc_find(dev, val); + struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val); return drm_atomic_set_crtc_for_plane(state, crtc); } else if (property == config->prop_crtc_x) { state->crtc_x = U642I64(val); @@ -1135,7 +1135,7 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, struct drm_mode_config *config = &dev->mode_config; if (property == config->prop_crtc_id) { - struct drm_crtc *crtc = drm_crtc_find(dev, val); + struct drm_crtc *crtc = drm_crtc_find(dev, NULL, val); return drm_atomic_set_crtc_for_connector(state, crtc); } else if (property == config->dpms_property) { /* setting DPMS property requires special handling, which @@ -1801,7 +1801,7 @@ int drm_atomic_debugfs_init(struct drm_minor *minor) */ static struct drm_pending_vblank_event *create_vblank_event( - struct drm_device *dev, uint64_t user_data) + struct drm_crtc *crtc, uint64_t user_data) { struct drm_pending_vblank_event *e = NULL; @@ -1811,7 +1811,8 @@ static struct drm_pending_vblank_event *create_vblank_event( e->event.base.type = DRM_EVENT_FLIP_COMPLETE; e->event.base.length = sizeof(e->event); - e->event.user_data = user_data; + e->event.vbl.crtc_id = crtc->base.id; + e->event.vbl.user_data = user_data; return e; } @@ -2065,7 +2066,7 @@ static int prepare_crtc_signaling(struct drm_device *dev, if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT || fence_ptr) { struct drm_pending_vblank_event *e; - e = create_vblank_event(dev, arg->user_data); + e = create_vblank_event(crtc, arg->user_data); if (!e) return -ENOMEM; @@ -2245,7 +2246,7 @@ retry: goto out; } - obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY); + obj = drm_mode_object_find(dev, file_priv, obj_id, DRM_MODE_OBJECT_ANY); if (!obj) { ret = -ENOENT; goto out; diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index ce6d11ae9e26..2f80377101a1 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -3309,7 +3309,7 @@ struct drm_encoder * drm_atomic_helper_best_encoder(struct drm_connector *connector) { WARN_ON(connector->encoder_ids[1]); - return drm_encoder_find(connector->dev, connector->encoder_ids[0]); + return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); } EXPORT_SYMBOL(drm_atomic_helper_best_encoder); diff --git a/drivers/gpu/drm/drm_auth.c b/drivers/gpu/drm/drm_auth.c index 7ff697389d74..aad468d170a7 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -31,6 +31,7 @@ #include <drm/drmP.h> #include "drm_internal.h" #include "drm_legacy.h" +#include <drm/drm_lease.h> /** * DOC: master and authentication @@ -93,7 +94,7 @@ int drm_authmagic(struct drm_device *dev, void *data, return file ? 0 : -EINVAL; } -static struct drm_master *drm_master_create(struct drm_device *dev) +struct drm_master *drm_master_create(struct drm_device *dev) { struct drm_master *master; @@ -107,6 +108,14 @@ static struct drm_master *drm_master_create(struct drm_device *dev) idr_init(&master->magic_map); master->dev = dev; + /* initialize the tree of output resource lessees */ + master->lessor = NULL; + master->lessee_id = 0; + INIT_LIST_HEAD(&master->lessees); + INIT_LIST_HEAD(&master->lessee_list); + idr_init(&master->leases); + idr_init(&master->lessee_idr); + return master; } @@ -189,6 +198,12 @@ int drm_setmaster_ioctl(struct drm_device *dev, void *data, goto out_unlock; } + if (file_priv->master->lessor != NULL) { + DRM_DEBUG_LEASE("Attempt to set lessee %d as master\n", file_priv->master->lessee_id); + ret = -EINVAL; + goto out_unlock; + } + ret = drm_set_master(dev, file_priv, false); out_unlock: mutex_unlock(&dev->master_mutex); @@ -270,6 +285,13 @@ void drm_master_release(struct drm_file *file_priv) if (dev->master == file_priv->master) drm_drop_master(dev, file_priv); out: + if (drm_core_check_feature(dev, DRIVER_MODESET) && file_priv->is_master) { + /* Revoke any leases held by this or lessees, but only if + * this is the "real" master + */ + drm_lease_revoke(master); + } + /* drop the master reference held by the file priv */ if (file_priv->master) drm_master_put(&file_priv->master); @@ -288,7 +310,7 @@ out: */ bool drm_is_current_master(struct drm_file *fpriv) { - return fpriv->is_master && fpriv->master == fpriv->minor->dev->master; + return fpriv->is_master && drm_lease_owner(fpriv->master) == fpriv->minor->dev->master; } EXPORT_SYMBOL(drm_is_current_master); @@ -310,12 +332,18 @@ static void drm_master_destroy(struct kref *kref) struct drm_master *master = container_of(kref, struct drm_master, refcount); struct drm_device *dev = master->dev; + if (drm_core_check_feature(dev, DRIVER_MODESET)) + drm_lease_destroy(master); + if (dev->driver->master_destroy) dev->driver->master_destroy(dev, master); drm_legacy_master_rmmaps(dev, master); idr_destroy(&master->magic_map); + idr_destroy(&master->leases); + idr_destroy(&master->lessee_idr); + kfree(master->unique); kfree(master); } diff --git a/drivers/gpu/drm/drm_color_mgmt.c b/drivers/gpu/drm/drm_color_mgmt.c index fe0982708e95..0d002b045bd2 100644 --- a/drivers/gpu/drm/drm_color_mgmt.c +++ b/drivers/gpu/drm/drm_color_mgmt.c @@ -230,7 +230,7 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - crtc = drm_crtc_find(dev, crtc_lut->crtc_id); + crtc = drm_crtc_find(dev, file_priv, crtc_lut->crtc_id); if (!crtc) return -ENOENT; @@ -308,7 +308,7 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - crtc = drm_crtc_find(dev, crtc_lut->crtc_id); + crtc = drm_crtc_find(dev, file_priv, crtc_lut->crtc_id); if (!crtc) return -ENOENT; diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index d8ca526ca4ee..704fc8934616 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -1310,7 +1310,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data, memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo)); - connector = drm_connector_lookup(dev, out_resp->connector_id); + connector = drm_connector_lookup(dev, file_priv, out_resp->connector_id); if (!connector) return -ENOENT; diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 68b4e976d5e0..f0556e654116 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c @@ -402,7 +402,7 @@ int drm_mode_getcrtc(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - crtc = drm_crtc_find(dev, crtc_resp->crtc_id); + crtc = drm_crtc_find(dev, file_priv, crtc_resp->crtc_id); if (!crtc) return -ENOENT; @@ -569,7 +569,7 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, if (crtc_req->x & 0xffff0000 || crtc_req->y & 0xffff0000) return -ERANGE; - crtc = drm_crtc_find(dev, crtc_req->crtc_id); + crtc = drm_crtc_find(dev, file_priv, crtc_req->crtc_id); if (!crtc) { DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id); return -ENOENT; @@ -595,7 +595,7 @@ retry: /* Make refcounting symmetric with the lookup path. */ drm_framebuffer_get(fb); } else { - fb = drm_framebuffer_lookup(dev, crtc_req->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, crtc_req->fb_id); if (!fb) { DRM_DEBUG_KMS("Unknown FB ID%d\n", crtc_req->fb_id); @@ -680,7 +680,7 @@ retry: goto out; } - connector = drm_connector_lookup(dev, out_id); + connector = drm_connector_lookup(dev, file_priv, out_id); if (!connector) { DRM_DEBUG_KMS("Connector id %d unknown\n", out_id); diff --git a/drivers/gpu/drm/drm_crtc_internal.h b/drivers/gpu/drm/drm_crtc_internal.h index a43582076b20..9ebb8841778c 100644 --- a/drivers/gpu/drm/drm_crtc_internal.h +++ b/drivers/gpu/drm/drm_crtc_internal.h @@ -106,6 +106,7 @@ int drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj, void drm_mode_object_register(struct drm_device *dev, struct drm_mode_object *obj); struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, + struct drm_file *file_priv, uint32_t id, uint32_t type); void drm_mode_object_unregister(struct drm_device *dev, struct drm_mode_object *object); diff --git a/drivers/gpu/drm/drm_dp_dual_mode_helper.c b/drivers/gpu/drm/drm_dp_dual_mode_helper.c index 0ef9011a1856..02a50929af67 100644 --- a/drivers/gpu/drm/drm_dp_dual_mode_helper.c +++ b/drivers/gpu/drm/drm_dp_dual_mode_helper.c @@ -410,6 +410,7 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter, { u8 data; int ret = 0; + int retry; if (!mode) { DRM_ERROR("NULL input\n"); @@ -417,10 +418,19 @@ int drm_lspcon_get_mode(struct i2c_adapter *adapter, } /* Read Status: i2c over aux */ - ret = drm_dp_dual_mode_read(adapter, DP_DUAL_MODE_LSPCON_CURRENT_MODE, - &data, sizeof(data)); + for (retry = 0; retry < 6; retry++) { + if (retry) + usleep_range(500, 1000); + + ret = drm_dp_dual_mode_read(adapter, + DP_DUAL_MODE_LSPCON_CURRENT_MODE, + &data, sizeof(data)); + if (!ret) + break; + } + if (ret < 0) { - DRM_ERROR("LSPCON read(0x80, 0x41) failed\n"); + DRM_DEBUG_KMS("LSPCON read(0x80, 0x41) failed\n"); return -EFAULT; } diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index bc2f10adc590..9acc1e157813 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -57,7 +57,8 @@ MODULE_PARM_DESC(debug, "Enable debug output, where each bit enables a debug cat "\t\tBit 2 (0x04) will enable KMS messages (modesetting code)\n" "\t\tBit 3 (0x08) will enable PRIME messages (prime code)\n" "\t\tBit 4 (0x10) will enable ATOMIC messages (atomic code)\n" -"\t\tBit 5 (0x20) will enable VBL messages (vblank code)"); +"\t\tBit 5 (0x20) will enable VBL messages (vblank code)\n" +"\t\tBit 7 (0x80) will enable LEASE messages (leasing code)"); module_param_named(debug, drm_debug, int, 0600); static DEFINE_SPINLOCK(drm_minor_lock); diff --git a/drivers/gpu/drm/drm_encoder.c b/drivers/gpu/drm/drm_encoder.c index 0708779840d2..59e0ebe733f8 100644 --- a/drivers/gpu/drm/drm_encoder.c +++ b/drivers/gpu/drm/drm_encoder.c @@ -220,13 +220,13 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - encoder = drm_encoder_find(dev, enc_resp->encoder_id); + encoder = drm_encoder_find(dev, file_priv, enc_resp->encoder_id); if (!encoder) return -ENOENT; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); crtc = drm_encoder_get_crtc(encoder); - if (crtc) + if (crtc && drm_lease_held(file_priv, crtc->base.id)) enc_resp->crtc_id = crtc->base.id; else enc_resp->crtc_id = 0; @@ -234,7 +234,8 @@ int drm_mode_getencoder(struct drm_device *dev, void *data, enc_resp->encoder_type = encoder->encoder_type; enc_resp->encoder_id = encoder->base.id; - enc_resp->possible_crtcs = encoder->possible_crtcs; + enc_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv, + encoder->possible_crtcs); enc_resp->possible_clones = encoder->possible_clones; return 0; diff --git a/drivers/gpu/drm/drm_framebuffer.c b/drivers/gpu/drm/drm_framebuffer.c index 0153000373ae..d63d4c2ac4c8 100644 --- a/drivers/gpu/drm/drm_framebuffer.c +++ b/drivers/gpu/drm/drm_framebuffer.c @@ -384,7 +384,7 @@ int drm_mode_rmfb(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - fb = drm_framebuffer_lookup(dev, *id); + fb = drm_framebuffer_lookup(dev, file_priv, *id); if (!fb) return -ENOENT; @@ -453,7 +453,7 @@ int drm_mode_getfb(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - fb = drm_framebuffer_lookup(dev, r->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id); if (!fb) return -ENOENT; @@ -518,7 +518,7 @@ int drm_mode_dirtyfb_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - fb = drm_framebuffer_lookup(dev, r->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, r->fb_id); if (!fb) return -ENOENT; @@ -684,6 +684,7 @@ EXPORT_SYMBOL(drm_framebuffer_init); /** * drm_framebuffer_lookup - look up a drm framebuffer and grab a reference * @dev: drm device + * @file_priv: drm file to check for lease against. * @id: id of the fb object * * If successful, this grabs an additional reference to the framebuffer - @@ -691,12 +692,13 @@ EXPORT_SYMBOL(drm_framebuffer_init); * again, using drm_framebuffer_put(). */ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev, + struct drm_file *file_priv, uint32_t id) { struct drm_mode_object *obj; struct drm_framebuffer *fb = NULL; - obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_FB); + obj = __drm_mode_object_find(dev, file_priv, id, DRM_MODE_OBJECT_FB); if (obj) fb = obj_to_fb(obj); return fb; diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 430ce3fe4f3b..b72242e93ea4 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -55,7 +55,6 @@ int drm_clients_info(struct seq_file *m, void* data); int drm_gem_name_info(struct seq_file *m, void *data); /* drm_vblank.c */ -extern unsigned int drm_timestamp_monotonic; void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe); void drm_vblank_cleanup(struct drm_device *dev); @@ -71,6 +70,12 @@ int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, int drm_legacy_irq_control(struct drm_device *dev, void *data, struct drm_file *file_priv); +int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); + +int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data, + struct drm_file *filp); + /* drm_auth.c */ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv); diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index a9ae6dd2d593..4aafe4802099 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -235,7 +235,7 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_ /* Only some caps make sense with UMS/render-only drivers. */ switch (req->capability) { case DRM_CAP_TIMESTAMP_MONOTONIC: - req->value = drm_timestamp_monotonic; + req->value = 1; return 0; case DRM_CAP_PRIME: req->value |= dev->driver->prime_fd_to_handle ? DRM_PRIME_CAP_IMPORT : 0; @@ -663,6 +663,12 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) diff --git a/drivers/gpu/drm/drm_lease.c b/drivers/gpu/drm/drm_lease.c new file mode 100644 index 000000000000..d1eb56a1eff4 --- /dev/null +++ b/drivers/gpu/drm/drm_lease.c @@ -0,0 +1,767 @@ +/* + * Copyright © 2017 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + +#include <drm/drmP.h> +#include "drm_internal.h" +#include "drm_legacy.h" +#include "drm_crtc_internal.h" +#include <drm/drm_lease.h> +#include <drm/drm_auth.h> +#include <drm/drm_crtc_helper.h> + +#define drm_for_each_lessee(lessee, lessor) \ + list_for_each_entry((lessee), &(lessor)->lessees, lessee_list) + +static uint64_t drm_lease_idr_object; + +/** + * drm_lease_owner - return ancestor owner drm_master + * @master: drm_master somewhere within tree of lessees and lessors + * + * RETURN: + * + * drm_master at the top of the tree (i.e, with lessor NULL + */ +struct drm_master *drm_lease_owner(struct drm_master *master) +{ + while (master->lessor != NULL) + master = master->lessor; + return master; +} +EXPORT_SYMBOL(drm_lease_owner); + +/** + * _drm_find_lessee - find lessee by id (idr_mutex held) + * @master: drm_master of lessor + * @id: lessee_id + * + * RETURN: + * + * drm_master of the lessee if valid, NULL otherwise + */ + +static struct drm_master* +_drm_find_lessee(struct drm_master *master, int lessee_id) +{ + lockdep_assert_held(&master->dev->mode_config.idr_mutex); + return idr_find(&drm_lease_owner(master)->lessee_idr, lessee_id); +} + +/** + * _drm_lease_held_master - check to see if an object is leased (or owned) by master (idr_mutex held) + * @master: the master to check the lease status of + * @id: the id to check + * + * Checks if the specified master holds a lease on the object. Return + * value: + * + * true 'master' holds a lease on (or owns) the object + * false 'master' does not hold a lease. + */ +static int _drm_lease_held_master(struct drm_master *master, int id) +{ + lockdep_assert_held(&master->dev->mode_config.idr_mutex); + if (master->lessor) + return idr_find(&master->leases, id) != NULL; + return true; +} + +/** + * _drm_has_leased - check to see if an object has been leased (idr_mutex held) + * @master: the master to check the lease status of + * @id: the id to check + * + * Checks if any lessee of 'master' holds a lease on 'id'. Return + * value: + * + * true Some lessee holds a lease on the object. + * false No lessee has a lease on the object. + */ +static bool _drm_has_leased(struct drm_master *master, int id) +{ + struct drm_master *lessee; + + lockdep_assert_held(&master->dev->mode_config.idr_mutex); + drm_for_each_lessee(lessee, master) + if (_drm_lease_held_master(lessee, id)) + return true; + return false; +} + +/** + * _drm_lease_held - check drm_mode_object lease status (idr_mutex held) + * @master: the drm_master + * @id: the object id + * + * Checks if the specified master holds a lease on the object. Return + * value: + * + * true 'master' holds a lease on (or owns) the object + * false 'master' does not hold a lease. + */ +bool _drm_lease_held(struct drm_file *file_priv, int id) +{ + if (file_priv == NULL || file_priv->master == NULL) + return true; + + return _drm_lease_held_master(file_priv->master, id); +} +EXPORT_SYMBOL(_drm_lease_held); + +/** + * drm_lease_held - check drm_mode_object lease status (idr_mutex not held) + * @master: the drm_master + * @id: the object id + * + * Checks if the specified master holds a lease on the object. Return + * value: + * + * true 'master' holds a lease on (or owns) the object + * false 'master' does not hold a lease. + */ +bool drm_lease_held(struct drm_file *file_priv, int id) +{ + struct drm_master *master; + bool ret; + + if (file_priv == NULL || file_priv->master == NULL) + return true; + + master = file_priv->master; + mutex_lock(&master->dev->mode_config.idr_mutex); + ret = _drm_lease_held_master(master, id); + mutex_unlock(&master->dev->mode_config.idr_mutex); + return ret; +} +EXPORT_SYMBOL(drm_lease_held); + +/** + * drm_lease_filter_crtcs - restricted crtc set to leased values (idr_mutex not held) + * @file_priv: requestor file + * @crtcs: bitmask of crtcs to check + * + * Reconstructs a crtc mask based on the crtcs which are visible + * through the specified file. + */ +uint32_t drm_lease_filter_crtcs(struct drm_file *file_priv, uint32_t crtcs_in) +{ + struct drm_master *master; + struct drm_device *dev; + struct drm_crtc *crtc; + int count_in, count_out; + uint32_t crtcs_out = 0; + + if (file_priv == NULL || file_priv->master == NULL) + return crtcs_in; + + master = file_priv->master; + dev = master->dev; + + count_in = count_out = 0; + mutex_lock(&master->dev->mode_config.idr_mutex); + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { + if (_drm_lease_held_master(master, crtc->base.id)) { + uint32_t mask_in = 1ul << count_in; + if ((crtcs_in & mask_in) != 0) { + uint32_t mask_out = 1ul << count_out; + crtcs_out |= mask_out; + } + count_out++; + } + count_in++; + } + mutex_unlock(&master->dev->mode_config.idr_mutex); + return crtcs_out; +} +EXPORT_SYMBOL(drm_lease_filter_crtcs); + +/* + * drm_lease_create - create a new drm_master with leased objects (idr_mutex not held) + * @lessor: lease holder (or owner) of objects + * @leases: objects to lease to the new drm_master + * + * Uses drm_master_create to allocate a new drm_master, then checks to + * make sure all of the desired objects can be leased, atomically + * leasing them to the new drmmaster. + * + * ERR_PTR(-EACCESS) some other master holds the title to any object + * ERR_PTR(-ENOENT) some object is not a valid DRM object for this device + * ERR_PTR(-EBUSY) some other lessee holds title to this object + * ERR_PTR(-EEXIST) same object specified more than once in the provided list + * ERR_PTR(-ENOMEM) allocation failed + */ +static struct drm_master *drm_lease_create(struct drm_master *lessor, struct idr *leases) +{ + struct drm_device *dev = lessor->dev; + int error; + struct drm_master *lessee; + int object; + int id; + void *entry; + + DRM_DEBUG_LEASE("lessor %d\n", lessor->lessee_id); + + lessee = drm_master_create(lessor->dev); + if (!lessee) { + DRM_DEBUG_LEASE("drm_master_create failed\n"); + return ERR_PTR(-ENOMEM); + } + + mutex_lock(&dev->mode_config.idr_mutex); + + /* Insert the new lessee into the tree */ + id = idr_alloc(&(drm_lease_owner(lessor)->lessee_idr), lessee, 1, 0, GFP_KERNEL); + if (id < 0) { + error = id; + goto out_lessee; + } + + lessee->lessee_id = id; + lessee->lessor = drm_master_get(lessor); + list_add_tail(&lessee->lessee_list, &lessor->lessees); + + idr_for_each_entry(leases, entry, object) { + error = 0; + if (!idr_find(&dev->mode_config.crtc_idr, object)) + error = -ENOENT; + else if (!_drm_lease_held_master(lessor, object)) + error = -EACCES; + else if (_drm_has_leased(lessor, object)) + error = -EBUSY; + + if (error != 0) { + DRM_DEBUG_LEASE("object %d failed %d\n", object, error); + goto out_lessee; + } + } + + /* Move the leases over */ + lessee->leases = *leases; + DRM_DEBUG_LEASE("new lessee %d %p, lessor %d %p\n", lessee->lessee_id, lessee, lessor->lessee_id, lessor); + + mutex_unlock(&dev->mode_config.idr_mutex); + return lessee; + +out_lessee: + drm_master_put(&lessee); + + mutex_unlock(&dev->mode_config.idr_mutex); + + return ERR_PTR(error); +} + +/** + * drm_lease_destroy - a master is going away (idr_mutex not held) + * @master: the drm_master being destroyed + * + * All lessees will have been destroyed as they + * hold a reference on their lessor. Notify any + * lessor for this master so that it can check + * the list of lessees. + */ +void drm_lease_destroy(struct drm_master *master) +{ + struct drm_device *dev = master->dev; + + mutex_lock(&dev->mode_config.idr_mutex); + + DRM_DEBUG_LEASE("drm_lease_destroy %d\n", master->lessee_id); + + /* This master is referenced by all lessees, hence it cannot be destroyed + * until all of them have been + */ + WARN_ON(!list_empty(&master->lessees)); + + /* Remove this master from the lessee idr in the owner */ + if (master->lessee_id != 0) { + DRM_DEBUG_LEASE("remove master %d from device list of lessees\n", master->lessee_id); + idr_remove(&(drm_lease_owner(master)->lessee_idr), master->lessee_id); + } + + /* Remove this master from any lessee list it may be on */ + list_del(&master->lessee_list); + + mutex_unlock(&dev->mode_config.idr_mutex); + + if (master->lessor) { + /* Tell the master to check the lessee list */ + drm_sysfs_hotplug_event(dev); + drm_master_put(&master->lessor); + } + + DRM_DEBUG_LEASE("drm_lease_destroy done %d\n", master->lessee_id); +} + +/** + * _drm_lease_revoke - revoke access to all leased objects (idr_mutex held) + * @master: the master losing its lease + */ +static void _drm_lease_revoke(struct drm_master *top) +{ + int object; + void *entry; + struct drm_master *master = top; + + lockdep_assert_held(&top->dev->mode_config.idr_mutex); + + /* + * Walk the tree starting at 'top' emptying all leases. Because + * the tree is fully connected, we can do this without recursing + */ + for (;;) { + DRM_DEBUG_LEASE("revoke leases for %p %d\n", master, master->lessee_id); + + /* Evacuate the lease */ + idr_for_each_entry(&master->leases, entry, object) + idr_remove(&master->leases, object); + + /* Depth-first list walk */ + + /* Down */ + if (!list_empty(&master->lessees)) { + master = list_first_entry(&master->lessees, struct drm_master, lessee_list); + } else { + /* Up */ + while (master != top && master == list_last_entry(&master->lessor->lessees, struct drm_master, lessee_list)) + master = master->lessor; + + if (master == top) + break; + + /* Over */ + master = list_entry(master->lessee_list.next, struct drm_master, lessee_list); + } + } +} + +/** + * drm_lease_revoke - revoke access to all leased objects (idr_mutex not held) + * @top: the master losing its lease + */ +void drm_lease_revoke(struct drm_master *top) +{ + mutex_lock(&top->dev->mode_config.idr_mutex); + _drm_lease_revoke(top); + mutex_unlock(&top->dev->mode_config.idr_mutex); +} + +static int validate_lease(struct drm_device *dev, + struct drm_file *lessor_priv, + int object_count, + struct drm_mode_object **objects) +{ + int o; + int has_crtc = -1; + int has_connector = -1; + int has_plane = -1; + + /* we want to confirm that there is at least one crtc, plane + connector object. */ + + for (o = 0; o < object_count; o++) { + if (objects[o]->type == DRM_MODE_OBJECT_CRTC && has_crtc == -1) { + has_crtc = o; + } + if (objects[o]->type == DRM_MODE_OBJECT_CONNECTOR && has_connector == -1) + has_connector = o; + + if (lessor_priv->universal_planes) { + if (objects[o]->type == DRM_MODE_OBJECT_PLANE && has_plane == -1) + has_plane = o; + } + } + if (has_crtc == -1 || has_connector == -1) + return -EINVAL; + if (lessor_priv->universal_planes && has_plane == -1) + return -EINVAL; + return 0; +} + +static int fill_object_idr(struct drm_device *dev, + struct drm_file *lessor_priv, + struct idr *leases, + int object_count, + u32 *object_ids) +{ + struct drm_mode_object **objects; + u32 o; + int ret; + objects = kcalloc(object_count, sizeof(struct drm_mode_object *), + GFP_KERNEL); + if (!objects) + return -ENOMEM; + + /* step one - get references to all the mode objects + and check for validity. */ + for (o = 0; o < object_count; o++) { + if ((int) object_ids[o] < 0) { + ret = -EINVAL; + goto out_free_objects; + } + + objects[o] = drm_mode_object_find(dev, lessor_priv, + object_ids[o], + DRM_MODE_OBJECT_ANY); + if (!objects[o]) { + ret = -ENOENT; + goto out_free_objects; + } + + if (!drm_mode_object_lease_required(objects[o]->type)) { + ret = -EINVAL; + goto out_free_objects; + } + } + + ret = validate_lease(dev, lessor_priv, object_count, objects); + if (ret) + goto out_free_objects; + + /* add their IDs to the lease request - taking into account + universal planes */ + for (o = 0; o < object_count; o++) { + struct drm_mode_object *obj = objects[o]; + u32 object_id = objects[o]->id; + DRM_DEBUG_LEASE("Adding object %d to lease\n", object_id); + + /* + * We're using an IDR to hold the set of leased + * objects, but we don't need to point at the object's + * data structure from the lease as the main crtc_idr + * will be used to actually find that. Instead, all we + * really want is a 'leased/not-leased' result, for + * which any non-NULL pointer will work fine. + */ + ret = idr_alloc(leases, &drm_lease_idr_object , object_id, object_id + 1, GFP_KERNEL); + if (ret < 0) { + DRM_DEBUG_LEASE("Object %d cannot be inserted into leases (%d)\n", + object_id, ret); + goto out_free_objects; + } + if (obj->type == DRM_MODE_OBJECT_CRTC && !lessor_priv->universal_planes) { + struct drm_crtc *crtc = obj_to_crtc(obj); + ret = idr_alloc(leases, &drm_lease_idr_object, crtc->primary->base.id, crtc->primary->base.id + 1, GFP_KERNEL); + if (ret < 0) { + DRM_DEBUG_LEASE("Object primary plane %d cannot be inserted into leases (%d)\n", + object_id, ret); + goto out_free_objects; + } + if (crtc->cursor) { + ret = idr_alloc(leases, &drm_lease_idr_object, crtc->cursor->base.id, crtc->cursor->base.id + 1, GFP_KERNEL); + if (ret < 0) { + DRM_DEBUG_LEASE("Object cursor plane %d cannot be inserted into leases (%d)\n", + object_id, ret); + goto out_free_objects; + } + } + } + } + + ret = 0; +out_free_objects: + for (o = 0; o < object_count; o++) { + if (objects[o]) + drm_mode_object_put(objects[o]); + } + kfree(objects); + return ret; +} + +/** + * drm_mode_create_lease_ioctl - create a new lease + * @dev: the drm device + * @data: pointer to struct drm_mode_create_lease + * @file_priv: the file being manipulated + * + * The master associated with the specified file will have a lease + * created containing the objects specified in the ioctl structure. + * A file descriptor will be allocated for that and returned to the + * application. + */ +int drm_mode_create_lease_ioctl(struct drm_device *dev, + void *data, struct drm_file *lessor_priv) +{ + struct drm_mode_create_lease *cl = data; + size_t object_count; + int ret = 0; + struct idr leases; + struct drm_master *lessor = lessor_priv->master; + struct drm_master *lessee = NULL; + struct file *lessee_file = NULL; + struct file *lessor_file = lessor_priv->filp; + struct drm_file *lessee_priv; + int fd = -1; + uint32_t *object_ids; + + /* Can't lease without MODESET */ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + /* Do not allow sub-leases */ + if (lessor->lessor) + return -EINVAL; + + /* need some objects */ + if (cl->object_count == 0) + return -EINVAL; + + if (cl->flags && (cl->flags & ~(O_CLOEXEC | O_NONBLOCK))) + return -EINVAL; + + object_count = cl->object_count; + + object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), object_count * sizeof(__u32)); + if (IS_ERR(object_ids)) + return PTR_ERR(object_ids); + + idr_init(&leases); + + /* fill and validate the object idr */ + ret = fill_object_idr(dev, lessor_priv, &leases, + object_count, object_ids); + kfree(object_ids); + if (ret) { + idr_destroy(&leases); + return ret; + } + + /* Allocate a file descriptor for the lease */ + fd = get_unused_fd_flags(cl->flags & (O_CLOEXEC | O_NONBLOCK)); + if (fd < 0) { + idr_destroy(&leases); + return fd; + } + + DRM_DEBUG_LEASE("Creating lease\n"); + lessee = drm_lease_create(lessor, &leases); + + if (IS_ERR(lessee)) { + ret = PTR_ERR(lessee); + goto out_leases; + } + + /* Clone the lessor file to create a new file for us */ + DRM_DEBUG_LEASE("Allocating lease file\n"); + path_get(&lessor_file->f_path); + lessee_file = alloc_file(&lessor_file->f_path, + lessor_file->f_mode, + fops_get(lessor_file->f_inode->i_fop)); + + if (IS_ERR(lessee_file)) { + ret = PTR_ERR(lessee_file); + goto out_lessee; + } + + /* Initialize the new file for DRM */ + DRM_DEBUG_LEASE("Initializing the file with %p\n", lessee_file->f_op->open); + ret = lessee_file->f_op->open(lessee_file->f_inode, lessee_file); + if (ret) + goto out_lessee_file; + + lessee_priv = lessee_file->private_data; + + /* Change the file to a master one */ + drm_master_put(&lessee_priv->master); + lessee_priv->master = lessee; + lessee_priv->is_master = 1; + lessee_priv->authenticated = 1; + + /* Hook up the fd */ + fd_install(fd, lessee_file); + + /* Pass fd back to userspace */ + DRM_DEBUG_LEASE("Returning fd %d id %d\n", fd, lessee->lessee_id); + cl->fd = fd; + cl->lessee_id = lessee->lessee_id; + + DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl succeeded\n"); + return 0; + +out_lessee_file: + fput(lessee_file); + +out_lessee: + drm_master_put(&lessee); + +out_leases: + put_unused_fd(fd); + idr_destroy(&leases); + + DRM_DEBUG_LEASE("drm_mode_create_lease_ioctl failed: %d\n", ret); + return ret; +} + +/** + * drm_mode_list_lessees_ioctl - list lessee ids + * @dev: the drm device + * @data: pointer to struct drm_mode_list_lessees + * @lessor_priv: the file being manipulated + * + * Starting from the master associated with the specified file, + * the master with the provided lessee_id is found, and then + * an array of lessee ids associated with leases from that master + * are returned. + */ + +int drm_mode_list_lessees_ioctl(struct drm_device *dev, + void *data, struct drm_file *lessor_priv) +{ + struct drm_mode_list_lessees *arg = data; + __u32 __user *lessee_ids = (__u32 __user *) (uintptr_t) (arg->lessees_ptr); + __u32 count_lessees = arg->count_lessees; + struct drm_master *lessor = lessor_priv->master, *lessee; + int count; + int ret = 0; + + if (arg->pad) + return -EINVAL; + + /* Can't lease without MODESET */ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + DRM_DEBUG_LEASE("List lessees for %d\n", lessor->lessee_id); + + mutex_lock(&dev->mode_config.idr_mutex); + + count = 0; + drm_for_each_lessee(lessee, lessor) { + /* Only list un-revoked leases */ + if (!idr_is_empty(&lessee->leases)) { + if (count_lessees > count) { + DRM_DEBUG_LEASE("Add lessee %d\n", lessee->lessee_id); + ret = put_user(lessee->lessee_id, lessee_ids + count); + if (ret) + break; + } + count++; + } + } + + DRM_DEBUG_LEASE("Lessor leases to %d\n", count); + if (ret == 0) + arg->count_lessees = count; + + mutex_unlock(&dev->mode_config.idr_mutex); + + return ret; +} + +/** + * drm_mode_get_lease_ioctl - list leased objects + * @dev: the drm device + * @data: pointer to struct drm_mode_get_lease + * @file_priv: the file being manipulated + * + * Return the list of leased objects for the specified lessee + */ + +int drm_mode_get_lease_ioctl(struct drm_device *dev, + void *data, struct drm_file *lessee_priv) +{ + struct drm_mode_get_lease *arg = data; + __u32 __user *object_ids = (__u32 __user *) (uintptr_t) (arg->objects_ptr); + __u32 count_objects = arg->count_objects; + struct drm_master *lessee = lessee_priv->master; + struct idr *object_idr; + int count; + void *entry; + int object; + int ret = 0; + + if (arg->pad) + return -EINVAL; + + /* Can't lease without MODESET */ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + DRM_DEBUG_LEASE("get lease for %d\n", lessee->lessee_id); + + mutex_lock(&dev->mode_config.idr_mutex); + + if (lessee->lessor == NULL) + /* owner can use all objects */ + object_idr = &lessee->dev->mode_config.crtc_idr; + else + /* lessee can only use allowed object */ + object_idr = &lessee->leases; + + count = 0; + idr_for_each_entry(object_idr, entry, object) { + if (count_objects > count) { + DRM_DEBUG_LEASE("adding object %d\n", object); + ret = put_user(object, object_ids + count); + if (ret) + break; + } + count++; + } + + DRM_DEBUG("lease holds %d objects\n", count); + if (ret == 0) + arg->count_objects = count; + + mutex_unlock(&dev->mode_config.idr_mutex); + + return ret; +} + +/** + * drm_mode_revoke_lease_ioctl - revoke lease + * @dev: the drm device + * @data: pointer to struct drm_mode_revoke_lease + * @file_priv: the file being manipulated + * + * This removes all of the objects from the lease without + * actually getting rid of the lease itself; that way all + * references to it still work correctly + */ +int drm_mode_revoke_lease_ioctl(struct drm_device *dev, + void *data, struct drm_file *lessor_priv) +{ + struct drm_mode_revoke_lease *arg = data; + struct drm_master *lessor = lessor_priv->master; + struct drm_master *lessee; + int ret = 0; + + DRM_DEBUG_LEASE("revoke lease for %d\n", arg->lessee_id); + + /* Can't lease without MODESET */ + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + mutex_lock(&dev->mode_config.idr_mutex); + + lessee = _drm_find_lessee(lessor, arg->lessee_id); + + /* No such lessee */ + if (!lessee) { + ret = -ENOENT; + goto fail; + } + + /* Lease is not held by lessor */ + if (lessee->lessor != lessor) { + ret = -EACCES; + goto fail; + } + + _drm_lease_revoke(lessee); + +fail: + mutex_unlock(&dev->mode_config.idr_mutex); + + return ret; +} diff --git a/drivers/gpu/drm/drm_mode_config.c b/drivers/gpu/drm/drm_mode_config.c index 74f6ff5df656..cda8bfab6d3b 100644 --- a/drivers/gpu/drm/drm_mode_config.c +++ b/drivers/gpu/drm/drm_mode_config.c @@ -122,10 +122,12 @@ int drm_mode_getresources(struct drm_device *dev, void *data, count = 0; crtc_id = u64_to_user_ptr(card_res->crtc_id_ptr); drm_for_each_crtc(crtc, dev) { - if (count < card_res->count_crtcs && - put_user(crtc->base.id, crtc_id + count)) - return -EFAULT; - count++; + if (drm_lease_held(file_priv, crtc->base.id)) { + if (count < card_res->count_crtcs && + put_user(crtc->base.id, crtc_id + count)) + return -EFAULT; + count++; + } } card_res->count_crtcs = count; @@ -143,12 +145,14 @@ int drm_mode_getresources(struct drm_device *dev, void *data, count = 0; connector_id = u64_to_user_ptr(card_res->connector_id_ptr); drm_for_each_connector_iter(connector, &conn_iter) { - if (count < card_res->count_connectors && - put_user(connector->base.id, connector_id + count)) { - drm_connector_list_iter_end(&conn_iter); - return -EFAULT; + if (drm_lease_held(file_priv, connector->base.id)) { + if (count < card_res->count_connectors && + put_user(connector->base.id, connector_id + count)) { + drm_connector_list_iter_end(&conn_iter); + return -EFAULT; + } + count++; } - count++; } card_res->count_connectors = count; drm_connector_list_iter_end(&conn_iter); @@ -385,7 +389,6 @@ void drm_mode_config_init(struct drm_device *dev) dev->mode_config.num_connector = 0; dev->mode_config.num_crtc = 0; dev->mode_config.num_encoder = 0; - dev->mode_config.num_overlay_plane = 0; dev->mode_config.num_total_plane = 0; } EXPORT_SYMBOL(drm_mode_config_init); diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index 7a1ea91d3343..ce4d2fb32810 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -104,7 +104,27 @@ void drm_mode_object_unregister(struct drm_device *dev, mutex_unlock(&dev->mode_config.idr_mutex); } +/** + * drm_lease_required - check types which must be leased to be used + * @type: type of object + * + * Returns whether the provided type of drm_mode_object must + * be owned or leased to be used by a process. + */ +bool drm_mode_object_lease_required(uint32_t type) +{ + switch(type) { + case DRM_MODE_OBJECT_CRTC: + case DRM_MODE_OBJECT_CONNECTOR: + case DRM_MODE_OBJECT_PLANE: + return true; + default: + return false; + } +} + struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, + struct drm_file *file_priv, uint32_t id, uint32_t type) { struct drm_mode_object *obj = NULL; @@ -116,6 +136,10 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, if (obj && obj->id != id) obj = NULL; + if (obj && drm_mode_object_lease_required(obj->type) && + !_drm_lease_held(file_priv, obj->id)) + obj = NULL; + if (obj && obj->free_cb) { if (!kref_get_unless_zero(&obj->refcount)) obj = NULL; @@ -128,6 +152,7 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, /** * drm_mode_object_find - look up a drm object with static lifetime * @dev: drm device + * @file_priv: drm file * @id: id of the mode object * @type: type of the mode object * @@ -136,11 +161,12 @@ struct drm_mode_object *__drm_mode_object_find(struct drm_device *dev, * by callind drm_mode_object_put(). */ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev, + struct drm_file *file_priv, uint32_t id, uint32_t type) { struct drm_mode_object *obj = NULL; - obj = __drm_mode_object_find(dev, id, type); + obj = __drm_mode_object_find(dev, file_priv, id, type); return obj; } EXPORT_SYMBOL(drm_mode_object_find); @@ -359,7 +385,7 @@ int drm_mode_obj_get_properties_ioctl(struct drm_device *dev, void *data, drm_modeset_lock_all(dev); - obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); + obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); if (!obj) { ret = -ENOENT; goto out; @@ -481,7 +507,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - arg_obj = drm_mode_object_find(dev, arg->obj_id, arg->obj_type); + arg_obj = drm_mode_object_find(dev, file_priv, arg->obj_id, arg->obj_type); if (!arg_obj) return -ENOENT; diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c index e123497da0ca..963e23db0fe7 100644 --- a/drivers/gpu/drm/drm_modeset_lock.c +++ b/drivers/gpu/drm/drm_modeset_lock.c @@ -93,7 +93,7 @@ void drm_modeset_lock_all(struct drm_device *dev) struct drm_modeset_acquire_ctx *ctx; int ret; - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL | __GFP_NOFAIL); if (WARN_ON(!ctx)) return; diff --git a/drivers/gpu/drm/drm_plane.c b/drivers/gpu/drm/drm_plane.c index 72cba9805edc..19404e34cd59 100644 --- a/drivers/gpu/drm/drm_plane.c +++ b/drivers/gpu/drm/drm_plane.c @@ -241,8 +241,6 @@ int drm_universal_plane_init(struct drm_device *dev, struct drm_plane *plane, list_add_tail(&plane->head, &config->plane_list); plane->index = config->num_total_plane++; - if (plane->type == DRM_PLANE_TYPE_OVERLAY) - config->num_overlay_plane++; drm_object_attach_property(&plane->base, config->plane_type_property, @@ -353,8 +351,6 @@ void drm_plane_cleanup(struct drm_plane *plane) list_del(&plane->head); dev->mode_config.num_total_plane--; - if (plane->type == DRM_PLANE_TYPE_OVERLAY) - dev->mode_config.num_overlay_plane--; WARN_ON(plane->state && !plane->funcs->atomic_destroy_state); if (plane->state && plane->funcs->atomic_destroy_state) @@ -462,43 +458,35 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data, struct drm_mode_config *config; struct drm_plane *plane; uint32_t __user *plane_ptr; - int copied = 0; - unsigned num_planes; + int count = 0; if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; config = &dev->mode_config; - - if (file_priv->universal_planes) - num_planes = config->num_total_plane; - else - num_planes = config->num_overlay_plane; + plane_ptr = u64_to_user_ptr(plane_resp->plane_id_ptr); /* * This ioctl is called twice, once to determine how much space is * needed, and the 2nd time to fill it. */ - if (num_planes && - (plane_resp->count_planes >= num_planes)) { - plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr; - - /* Plane lists are invariant, no locking needed. */ - drm_for_each_plane(plane, dev) { - /* - * Unless userspace set the 'universal planes' - * capability bit, only advertise overlays. - */ - if (plane->type != DRM_PLANE_TYPE_OVERLAY && - !file_priv->universal_planes) - continue; - - if (put_user(plane->base.id, plane_ptr + copied)) + drm_for_each_plane(plane, dev) { + /* + * Unless userspace set the 'universal planes' + * capability bit, only advertise overlays. + */ + if (plane->type != DRM_PLANE_TYPE_OVERLAY && + !file_priv->universal_planes) + continue; + + if (drm_lease_held(file_priv, plane->base.id)) { + if (count < plane_resp->count_planes && + put_user(plane->base.id, plane_ptr + count)) return -EFAULT; - copied++; + count++; } } - plane_resp->count_planes = num_planes; + plane_resp->count_planes = count; return 0; } @@ -513,14 +501,14 @@ int drm_mode_getplane(struct drm_device *dev, void *data, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - plane = drm_plane_find(dev, plane_resp->plane_id); + plane = drm_plane_find(dev, file_priv, plane_resp->plane_id); if (!plane) return -ENOENT; drm_modeset_lock(&plane->mutex, NULL); - if (plane->state && plane->state->crtc) + if (plane->state && plane->state->crtc && drm_lease_held(file_priv, plane->state->crtc->base.id)) plane_resp->crtc_id = plane->state->crtc->base.id; - else if (!plane->state && plane->crtc) + else if (!plane->state && plane->crtc && drm_lease_held(file_priv, plane->crtc->base.id)) plane_resp->crtc_id = plane->crtc->base.id; else plane_resp->crtc_id = 0; @@ -534,7 +522,9 @@ int drm_mode_getplane(struct drm_device *dev, void *data, drm_modeset_unlock(&plane->mutex); plane_resp->plane_id = plane->base.id; - plane_resp->possible_crtcs = plane->possible_crtcs; + plane_resp->possible_crtcs = drm_lease_filter_crtcs(file_priv, + plane->possible_crtcs); + plane_resp->gamma_size = 0; /* @@ -703,7 +693,7 @@ int drm_mode_setplane(struct drm_device *dev, void *data, * First, find the plane, crtc, and fb objects. If not available, * we don't bother to call the driver. */ - plane = drm_plane_find(dev, plane_req->plane_id); + plane = drm_plane_find(dev, file_priv, plane_req->plane_id); if (!plane) { DRM_DEBUG_KMS("Unknown plane ID %d\n", plane_req->plane_id); @@ -711,14 +701,14 @@ int drm_mode_setplane(struct drm_device *dev, void *data, } if (plane_req->fb_id) { - fb = drm_framebuffer_lookup(dev, plane_req->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, plane_req->fb_id); if (!fb) { DRM_DEBUG_KMS("Unknown framebuffer ID %d\n", plane_req->fb_id); return -ENOENT; } - crtc = drm_crtc_find(dev, plane_req->crtc_id); + crtc = drm_crtc_find(dev, file_priv, plane_req->crtc_id); if (!crtc) { drm_framebuffer_put(fb); DRM_DEBUG_KMS("Unknown crtc ID %d\n", @@ -829,7 +819,7 @@ static int drm_mode_cursor_common(struct drm_device *dev, if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags)) return -EINVAL; - crtc = drm_crtc_find(dev, req->crtc_id); + crtc = drm_crtc_find(dev, file_priv, req->crtc_id); if (!crtc) { DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id); return -ENOENT; @@ -944,7 +934,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev, if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip) return -EINVAL; - crtc = drm_crtc_find(dev, page_flip->crtc_id); + crtc = drm_crtc_find(dev, file_priv, page_flip->crtc_id); if (!crtc) return -ENOENT; @@ -1005,7 +995,7 @@ retry: goto out; } - fb = drm_framebuffer_lookup(dev, page_flip->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, page_flip->fb_id); if (!fb) { ret = -ENOENT; goto out; @@ -1039,7 +1029,7 @@ retry: } e->event.base.type = DRM_EVENT_FLIP_COMPLETE; e->event.base.length = sizeof(e->event); - e->event.user_data = page_flip->user_data; + e->event.vbl.user_data = page_flip->user_data; ret = drm_event_reserve_init(dev, file_priv, &e->base, &e->event.base); if (ret) { kfree(e); diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c index 5840aabbf24e..6dc2dde5b672 100644 --- a/drivers/gpu/drm/drm_probe_helper.c +++ b/drivers/gpu/drm/drm_probe_helper.c @@ -99,7 +99,7 @@ drm_mode_validate_pipeline(struct drm_display_mode *mode, /* Step 2: Validate against encoders and crtcs */ for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { - struct drm_encoder *encoder = drm_encoder_find(dev, ids[i]); + struct drm_encoder *encoder = drm_encoder_find(dev, NULL, ids[i]); struct drm_crtc *crtc; if (!encoder) diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c index bc5128203056..bae50e6b819d 100644 --- a/drivers/gpu/drm/drm_property.c +++ b/drivers/gpu/drm/drm_property.c @@ -450,7 +450,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev, if (!drm_core_check_feature(dev, DRIVER_MODESET)) return -EINVAL; - property = drm_property_find(dev, out_resp->prop_id); + property = drm_property_find(dev, file_priv, out_resp->prop_id); if (!property) return -ENOENT; @@ -634,7 +634,7 @@ struct drm_property_blob *drm_property_lookup_blob(struct drm_device *dev, struct drm_mode_object *obj; struct drm_property_blob *blob = NULL; - obj = __drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB); + obj = __drm_mode_object_find(dev, NULL, id, DRM_MODE_OBJECT_BLOB); if (obj) blob = obj_to_blob(obj); return blob; @@ -897,7 +897,7 @@ bool drm_property_change_valid_get(struct drm_property *property, if (value == 0) return true; - *ref = __drm_mode_object_find(property->dev, value, + *ref = __drm_mode_object_find(property->dev, NULL, value, property->values[0]); return *ref != NULL; } diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 7943c215a03c..9b733c510cbf 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -264,8 +264,14 @@ void drm_syncobj_free(struct kref *kref) } EXPORT_SYMBOL(drm_syncobj_free); -static int drm_syncobj_create(struct drm_file *file_private, - u32 *handle, uint32_t flags) +/** + * drm_syncobj_create - create a new syncobj + * @out_syncobj: returned syncobj + * @flags: DRM_SYNCOBJ_* flags + * @fence: if non-NULL, the syncobj will represent this fence + */ +int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags, + struct dma_fence *fence) { int ret; struct drm_syncobj *syncobj; @@ -286,6 +292,25 @@ static int drm_syncobj_create(struct drm_file *file_private, } } + if (fence) + drm_syncobj_replace_fence(syncobj, fence); + + *out_syncobj = syncobj; + return 0; +} +EXPORT_SYMBOL(drm_syncobj_create); + +/** + * drm_syncobj_get_handle - get a handle from a syncobj + */ +int drm_syncobj_get_handle(struct drm_file *file_private, + struct drm_syncobj *syncobj, u32 *handle) +{ + int ret; + + /* take a reference to put in the idr */ + drm_syncobj_get(syncobj); + idr_preload(GFP_KERNEL); spin_lock(&file_private->syncobj_table_lock); ret = idr_alloc(&file_private->syncobj_idr, syncobj, 1, 0, GFP_NOWAIT); @@ -301,6 +326,22 @@ static int drm_syncobj_create(struct drm_file *file_private, *handle = ret; return 0; } +EXPORT_SYMBOL(drm_syncobj_get_handle); + +static int drm_syncobj_create_as_handle(struct drm_file *file_private, + u32 *handle, uint32_t flags) +{ + int ret; + struct drm_syncobj *syncobj; + + ret = drm_syncobj_create(&syncobj, flags, NULL); + if (ret) + return ret; + + ret = drm_syncobj_get_handle(file_private, syncobj, handle); + drm_syncobj_put(syncobj); + return ret; +} static int drm_syncobj_destroy(struct drm_file *file_private, u32 handle) @@ -347,33 +388,38 @@ static int drm_syncobj_alloc_file(struct drm_syncobj *syncobj) return 0; } -static int drm_syncobj_handle_to_fd(struct drm_file *file_private, - u32 handle, int *p_fd) +int drm_syncobj_get_fd(struct drm_syncobj *syncobj, int *p_fd) { - struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle); int ret; int fd; - if (!syncobj) - return -EINVAL; - fd = get_unused_fd_flags(O_CLOEXEC); - if (fd < 0) { - drm_syncobj_put(syncobj); + if (fd < 0) return fd; - } if (!syncobj->file) { ret = drm_syncobj_alloc_file(syncobj); - if (ret) - goto out_put_fd; + if (ret) { + put_unused_fd(fd); + return ret; + } } fd_install(fd, syncobj->file); - drm_syncobj_put(syncobj); *p_fd = fd; return 0; -out_put_fd: - put_unused_fd(fd); +} +EXPORT_SYMBOL(drm_syncobj_get_fd); + +static int drm_syncobj_handle_to_fd(struct drm_file *file_private, + u32 handle, int *p_fd) +{ + struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle); + int ret; + + if (!syncobj) + return -EINVAL; + + ret = drm_syncobj_get_fd(syncobj, p_fd); drm_syncobj_put(syncobj); return ret; } @@ -524,8 +570,8 @@ drm_syncobj_create_ioctl(struct drm_device *dev, void *data, if (args->flags & ~DRM_SYNCOBJ_CREATE_SIGNALED) return -EINVAL; - return drm_syncobj_create(file_private, - &args->handle, args->flags); + return drm_syncobj_create_as_handle(file_private, + &args->handle, args->flags); } int diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index f14e6c92e332..09c1c4ff93ca 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -78,28 +78,20 @@ static bool drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, - struct timeval *tvblank, bool in_vblank_irq); + ktime_t *tvblank, bool in_vblank_irq); static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ -/* - * Default to use monotonic timestamps for wait-for-vblank and page-flip - * complete events. - */ -unsigned int drm_timestamp_monotonic = 1; - static int drm_vblank_offdelay = 5000; /* Default to 5000 msecs. */ module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); -module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)"); MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]"); -MODULE_PARM_DESC(timestamp_monotonic, "Use monotonic timestamps"); static void store_vblank(struct drm_device *dev, unsigned int pipe, u32 vblank_count_inc, - struct timeval *t_vblank, u32 last) + ktime_t t_vblank, u32 last) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; @@ -108,7 +100,7 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe, vblank->last = last; write_seqlock(&vblank->seqlock); - vblank->time = *t_vblank; + vblank->time = t_vblank; vblank->count += vblank_count_inc; write_sequnlock(&vblank->seqlock); } @@ -151,7 +143,7 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe { u32 cur_vblank; bool rc; - struct timeval t_vblank; + ktime_t t_vblank; int count = DRM_TIMESTAMP_MAXRETRIES; spin_lock(&dev->vblank_time_lock); @@ -171,13 +163,13 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid. */ if (!rc) - t_vblank = (struct timeval) {0, 0}; + t_vblank = 0; /* * +1 to make sure user will never see the same * vblank counter value before and after a modeset */ - store_vblank(dev, pipe, 1, &t_vblank, cur_vblank); + store_vblank(dev, pipe, 1, t_vblank, cur_vblank); spin_unlock(&dev->vblank_time_lock); } @@ -200,7 +192,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; u32 cur_vblank, diff; bool rc; - struct timeval t_vblank; + ktime_t t_vblank; int count = DRM_TIMESTAMP_MAXRETRIES; int framedur_ns = vblank->framedur_ns; @@ -225,11 +217,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, /* trust the hw counter when it's around */ diff = (cur_vblank - vblank->last) & dev->max_vblank_count; } else if (rc && framedur_ns) { - const struct timeval *t_old; - u64 diff_ns; - - t_old = &vblank->time; - diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old); + u64 diff_ns = ktime_to_ns(ktime_sub(t_vblank, vblank->time)); /* * Figure out how many vblanks we've missed based @@ -263,7 +251,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, } DRM_DEBUG_VBL("updating vblank count on crtc %u:" - " current=%u, diff=%u, hw=%u hw_last=%u\n", + " current=%llu, diff=%u, hw=%u hw_last=%u\n", pipe, vblank->count, diff, cur_vblank, vblank->last); if (diff == 0) { @@ -278,9 +266,9 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, * for now, to mark the vblanktimestamp as invalid. */ if (!rc && !in_vblank_irq) - t_vblank = (struct timeval) {0, 0}; + t_vblank = 0; - store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); + store_vblank(dev, pipe, diff, t_vblank, cur_vblank); } static u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe) @@ -311,8 +299,8 @@ u32 drm_crtc_accurate_vblank_count(struct drm_crtc *crtc) u32 vblank; unsigned long flags; - WARN(!dev->driver->get_vblank_timestamp, - "This function requires support for accurate vblank timestamps."); + WARN_ONCE(drm_debug & DRM_UT_VBL && !dev->driver->get_vblank_timestamp, + "This function requires support for accurate vblank timestamps."); spin_lock_irqsave(&dev->vblank_time_lock, flags); @@ -556,7 +544,7 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); * @pipe: index of CRTC whose vblank timestamp to retrieve * @max_error: Desired maximum allowable error in timestamps (nanosecs) * On return contains true maximum error of timestamp - * @vblank_time: Pointer to struct timeval which should receive the timestamp + * @vblank_time: Pointer to time which should receive the timestamp * @in_vblank_irq: * True when called from drm_crtc_handle_vblank(). Some drivers * need to apply some workarounds for gpu-specific vblank irq quirks @@ -584,10 +572,10 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, unsigned int pipe, int *max_error, - struct timeval *vblank_time, + ktime_t *vblank_time, bool in_vblank_irq) { - struct timeval tv_etime; + struct timespec64 ts_etime, ts_vblank_time; ktime_t stime, etime; bool vbl_status; struct drm_crtc *crtc; @@ -676,41 +664,31 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos), mode->crtc_clock); - if (!drm_timestamp_monotonic) - etime = ktime_mono_to_real(etime); - /* save this only for debugging purposes */ - tv_etime = ktime_to_timeval(etime); + ts_etime = ktime_to_timespec64(etime); + ts_vblank_time = ktime_to_timespec64(*vblank_time); /* Subtract time delta from raw timestamp to get final * vblank_time timestamp for end of vblank. */ etime = ktime_sub_ns(etime, delta_ns); - *vblank_time = ktime_to_timeval(etime); + *vblank_time = etime; - DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", + DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %lld.%06ld -> %lld.%06ld [e %d us, %d rep]\n", pipe, hpos, vpos, - (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, - (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, - duration_ns/1000, i); + (u64)ts_etime.tv_sec, ts_etime.tv_nsec / 1000, + (u64)ts_vblank_time.tv_sec, ts_vblank_time.tv_nsec / 1000, + duration_ns / 1000, i); return true; } EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); -static struct timeval get_drm_timestamp(void) -{ - ktime_t now; - - now = drm_timestamp_monotonic ? ktime_get() : ktime_get_real(); - return ktime_to_timeval(now); -} - /** * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent * vblank interval * @dev: DRM device * @pipe: index of CRTC whose vblank timestamp to retrieve - * @tvblank: Pointer to target struct timeval which should receive the timestamp + * @tvblank: Pointer to target time which should receive the timestamp * @in_vblank_irq: * True when called from drm_crtc_handle_vblank(). Some drivers * need to apply some workarounds for gpu-specific vblank irq quirks @@ -728,7 +706,7 @@ static struct timeval get_drm_timestamp(void) */ static bool drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, - struct timeval *tvblank, bool in_vblank_irq) + ktime_t *tvblank, bool in_vblank_irq) { bool ret = false; @@ -744,7 +722,7 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, * Return current monotonic/gettimeofday timestamp as best estimate. */ if (!ret) - *tvblank = get_drm_timestamp(); + *tvblank = ktime_get(); return ret; } @@ -762,21 +740,35 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, * Returns: * The software vblank counter. */ -u32 drm_crtc_vblank_count(struct drm_crtc *crtc) +u64 drm_crtc_vblank_count(struct drm_crtc *crtc) { return drm_vblank_count(crtc->dev, drm_crtc_index(crtc)); } EXPORT_SYMBOL(drm_crtc_vblank_count); -static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, - struct timeval *vblanktime) +/** + * drm_vblank_count_and_time - retrieve "cooked" vblank counter value and the + * system timestamp corresponding to that vblank counter value. + * @dev: DRM device + * @pipe: index of CRTC whose counter to retrieve + * @vblanktime: Pointer to ktime_t to receive the vblank timestamp. + * + * Fetches the "cooked" vblank count value that represents the number of + * vblank events since the system was booted, including lost events due to + * modesetting activity. Returns corresponding system timestamp of the time + * of the vblank interval that corresponds to the current vblank counter value. + * + * This is the legacy version of drm_crtc_vblank_count_and_time(). + */ +static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, + ktime_t *vblanktime) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; - u32 vblank_count; + u64 vblank_count; unsigned int seq; if (WARN_ON(pipe >= dev->num_crtcs)) { - *vblanktime = (struct timeval) { 0 }; + *vblanktime = 0; return 0; } @@ -793,15 +785,15 @@ static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value * and the system timestamp corresponding to that vblank counter value * @crtc: which counter to retrieve - * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. + * @vblanktime: Pointer to time to receive the vblank timestamp. * * Fetches the "cooked" vblank count value that represents the number of * vblank events since the system was booted, including lost events due to * modesetting activity. Returns corresponding system timestamp of the time * of the vblank interval that corresponds to the current vblank counter value. */ -u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, - struct timeval *vblanktime) +u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, + ktime_t *vblanktime) { return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc), vblanktime); @@ -810,15 +802,30 @@ EXPORT_SYMBOL(drm_crtc_vblank_count_and_time); static void send_vblank_event(struct drm_device *dev, struct drm_pending_vblank_event *e, - unsigned long seq, struct timeval *now) + u64 seq, ktime_t now) { - e->event.sequence = seq; - e->event.tv_sec = now->tv_sec; - e->event.tv_usec = now->tv_usec; - - trace_drm_vblank_event_delivered(e->base.file_priv, e->pipe, - e->event.sequence); + struct timespec64 tv; + switch (e->event.base.type) { + case DRM_EVENT_VBLANK: + case DRM_EVENT_FLIP_COMPLETE: + tv = ktime_to_timespec64(now); + e->event.vbl.sequence = seq; + /* + * e->event is a user space structure, with hardcoded unsigned + * 32-bit seconds/microseconds. This is safe as we always use + * monotonic timestamps since linux-4.15 + */ + e->event.vbl.tv_sec = tv.tv_sec; + e->event.vbl.tv_usec = tv.tv_nsec / 1000; + break; + case DRM_EVENT_CRTC_SEQUENCE: + if (seq) + e->event.seq.sequence = seq; + e->event.seq.time_ns = ktime_to_ns(now); + break; + } + trace_drm_vblank_event_delivered(e->base.file_priv, e->pipe, seq); drm_send_event_locked(dev, &e->base); } @@ -869,8 +876,7 @@ void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, assert_spin_locked(&dev->event_lock); e->pipe = pipe; - e->event.sequence = drm_crtc_accurate_vblank_count(crtc) + 1; - e->event.crtc_id = crtc->base.id; + e->sequence = drm_crtc_accurate_vblank_count(crtc) + 1; list_add_tail(&e->base.link, &dev->vblank_event_list); } EXPORT_SYMBOL(drm_crtc_arm_vblank_event); @@ -890,19 +896,19 @@ void drm_crtc_send_vblank_event(struct drm_crtc *crtc, struct drm_pending_vblank_event *e) { struct drm_device *dev = crtc->dev; - unsigned int seq, pipe = drm_crtc_index(crtc); - struct timeval now; + u64 seq; + unsigned int pipe = drm_crtc_index(crtc); + ktime_t now; if (dev->num_crtcs > 0) { seq = drm_vblank_count_and_time(dev, pipe, &now); } else { seq = 0; - now = get_drm_timestamp(); + now = ktime_get(); } e->pipe = pipe; - e->event.crtc_id = crtc->base.id; - send_vblank_event(dev, e, seq, &now); + send_vblank_event(dev, e, seq, now); } EXPORT_SYMBOL(drm_crtc_send_vblank_event); @@ -1100,9 +1106,10 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc) unsigned int pipe = drm_crtc_index(crtc); struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; struct drm_pending_vblank_event *e, *t; - struct timeval now; + + ktime_t now; unsigned long irqflags; - unsigned int seq; + u64 seq; if (WARN_ON(pipe >= dev->num_crtcs)) return; @@ -1137,11 +1144,11 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc) if (e->pipe != pipe) continue; DRM_DEBUG("Sending premature vblank event on disable: " - "wanted %u, current %u\n", - e->event.sequence, seq); + "wanted %llu, current %llu\n", + e->sequence, seq); list_del(&e->base.link); drm_vblank_put(dev, pipe); - send_vblank_event(dev, e, seq, &now); + send_vblank_event(dev, e, seq, now); } spin_unlock_irqrestore(&dev->event_lock, irqflags); @@ -1310,20 +1317,21 @@ int drm_legacy_modeset_ctl_ioctl(struct drm_device *dev, void *data, return 0; } -static inline bool vblank_passed(u32 seq, u32 ref) +static inline bool vblank_passed(u64 seq, u64 ref) { return (seq - ref) <= (1 << 23); } static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, + u64 req_seq, union drm_wait_vblank *vblwait, struct drm_file *file_priv) { struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; struct drm_pending_vblank_event *e; - struct timeval now; + ktime_t now; unsigned long flags; - unsigned int seq; + u64 seq; int ret; e = kzalloc(sizeof(*e), GFP_KERNEL); @@ -1334,8 +1342,14 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, e->pipe = pipe; e->event.base.type = DRM_EVENT_VBLANK; - e->event.base.length = sizeof(e->event); - e->event.user_data = vblwait->request.signal; + e->event.base.length = sizeof(e->event.vbl); + e->event.vbl.user_data = vblwait->request.signal; + e->event.vbl.crtc_id = 0; + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); + if (crtc) + e->event.vbl.crtc_id = crtc->base.id; + } spin_lock_irqsave(&dev->event_lock, flags); @@ -1358,21 +1372,20 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, seq = drm_vblank_count_and_time(dev, pipe, &now); - DRM_DEBUG("event on vblank count %u, current %u, crtc %u\n", - vblwait->request.sequence, seq, pipe); + DRM_DEBUG("event on vblank count %llu, current %llu, crtc %u\n", + req_seq, seq, pipe); - trace_drm_vblank_event_queued(file_priv, pipe, - vblwait->request.sequence); + trace_drm_vblank_event_queued(file_priv, pipe, req_seq); - e->event.sequence = vblwait->request.sequence; - if (vblank_passed(seq, vblwait->request.sequence)) { + e->sequence = req_seq; + if (vblank_passed(seq, req_seq)) { drm_vblank_put(dev, pipe); - send_vblank_event(dev, e, seq, &now); + send_vblank_event(dev, e, seq, now); vblwait->reply.sequence = seq; } else { /* drm_handle_vblank_events will call drm_vblank_put */ list_add_tail(&e->base.link, &dev->vblank_event_list); - vblwait->reply.sequence = vblwait->request.sequence; + vblwait->reply.sequence = req_seq; } spin_unlock_irqrestore(&dev->event_lock, flags); @@ -1398,13 +1411,49 @@ static bool drm_wait_vblank_is_query(union drm_wait_vblank *vblwait) _DRM_VBLANK_NEXTONMISS)); } +/* + * Widen a 32-bit param to 64-bits. + * + * \param narrow 32-bit value (missing upper 32 bits) + * \param near 64-bit value that should be 'close' to near + * + * This function returns a 64-bit value using the lower 32-bits from + * 'narrow' and constructing the upper 32-bits so that the result is + * as close as possible to 'near'. + */ + +static u64 widen_32_to_64(u32 narrow, u64 near) +{ + return near + (s32) (narrow - near); +} + +static void drm_wait_vblank_reply(struct drm_device *dev, unsigned int pipe, + struct drm_wait_vblank_reply *reply) +{ + ktime_t now; + struct timespec64 ts; + + /* + * drm_wait_vblank_reply is a UAPI structure that uses 'long' + * to store the seconds. This is safe as we always use monotonic + * timestamps since linux-4.15. + */ + reply->sequence = drm_vblank_count_and_time(dev, pipe, &now); + ts = ktime_to_timespec64(now); + reply->tval_sec = (u32)ts.tv_sec; + reply->tval_usec = ts.tv_nsec / 1000; +} + int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { + struct drm_crtc *crtc; struct drm_vblank_crtc *vblank; union drm_wait_vblank *vblwait = data; int ret; - unsigned int flags, seq, pipe, high_pipe; + u64 req_seq, seq; + unsigned int pipe_index; + unsigned int flags, pipe, high_pipe; if (!dev->irq_enabled) return -EINVAL; @@ -1425,9 +1474,25 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; high_pipe = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK); if (high_pipe) - pipe = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT; + pipe_index = high_pipe >> _DRM_VBLANK_HIGH_CRTC_SHIFT; else - pipe = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; + pipe_index = flags & _DRM_VBLANK_SECONDARY ? 1 : 0; + + /* Convert lease-relative crtc index into global crtc index */ + if (drm_core_check_feature(dev, DRIVER_MODESET)) { + pipe = 0; + drm_for_each_crtc(crtc, dev) { + if (drm_lease_held(file_priv, crtc->base.id)) { + if (pipe_index == 0) + break; + pipe_index--; + } + pipe++; + } + } else { + pipe = pipe_index; + } + if (pipe >= dev->num_crtcs) return -EINVAL; @@ -1439,12 +1504,7 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, if (dev->vblank_disable_immediate && drm_wait_vblank_is_query(vblwait) && READ_ONCE(vblank->enabled)) { - struct timeval now; - - vblwait->reply.sequence = - drm_vblank_count_and_time(dev, pipe, &now); - vblwait->reply.tval_sec = now.tv_sec; - vblwait->reply.tval_usec = now.tv_usec; + drm_wait_vblank_reply(dev, pipe, &vblwait->reply); return 0; } @@ -1457,9 +1517,12 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { case _DRM_VBLANK_RELATIVE: - vblwait->request.sequence += seq; + req_seq = seq + vblwait->request.sequence; + vblwait->request.sequence = req_seq; vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; + break; case _DRM_VBLANK_ABSOLUTE: + req_seq = widen_32_to_64(vblwait->request.sequence, seq); break; default: ret = -EINVAL; @@ -1467,31 +1530,30 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, } if ((flags & _DRM_VBLANK_NEXTONMISS) && - vblank_passed(seq, vblwait->request.sequence)) - vblwait->request.sequence = seq + 1; + vblank_passed(seq, req_seq)) { + req_seq = seq + 1; + vblwait->request.type &= ~_DRM_VBLANK_NEXTONMISS; + vblwait->request.sequence = req_seq; + } if (flags & _DRM_VBLANK_EVENT) { /* must hold on to the vblank ref until the event fires * drm_vblank_put will be called asynchronously */ - return drm_queue_vblank_event(dev, pipe, vblwait, file_priv); + return drm_queue_vblank_event(dev, pipe, req_seq, vblwait, file_priv); } - if (vblwait->request.sequence != seq) { - DRM_DEBUG("waiting on vblank count %u, crtc %u\n", - vblwait->request.sequence, pipe); + if (req_seq != seq) { + DRM_DEBUG("waiting on vblank count %llu, crtc %u\n", + req_seq, pipe); DRM_WAIT_ON(ret, vblank->queue, 3 * HZ, vblank_passed(drm_vblank_count(dev, pipe), - vblwait->request.sequence) || + req_seq) || !READ_ONCE(vblank->enabled)); } if (ret != -EINTR) { - struct timeval now; - - vblwait->reply.sequence = drm_vblank_count_and_time(dev, pipe, &now); - vblwait->reply.tval_sec = now.tv_sec; - vblwait->reply.tval_usec = now.tv_usec; + drm_wait_vblank_reply(dev, pipe, &vblwait->reply); DRM_DEBUG("crtc %d returning %u to client\n", pipe, vblwait->reply.sequence); @@ -1507,8 +1569,8 @@ done: static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) { struct drm_pending_vblank_event *e, *t; - struct timeval now; - unsigned int seq; + ktime_t now; + u64 seq; assert_spin_locked(&dev->event_lock); @@ -1517,15 +1579,15 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) { if (e->pipe != pipe) continue; - if (!vblank_passed(seq, e->event.sequence)) + if (!vblank_passed(seq, e->sequence)) continue; - DRM_DEBUG("vblank event on %u, current %u\n", - e->event.sequence, seq); + DRM_DEBUG("vblank event on %llu, current %llu\n", + e->sequence, seq); list_del(&e->base.link); drm_vblank_put(dev, pipe); - send_vblank_event(dev, e, seq, &now); + send_vblank_event(dev, e, seq, now); } trace_drm_vblank_event(pipe, seq); @@ -1611,3 +1673,166 @@ bool drm_crtc_handle_vblank(struct drm_crtc *crtc) return drm_handle_vblank(crtc->dev, drm_crtc_index(crtc)); } EXPORT_SYMBOL(drm_crtc_handle_vblank); + +/* + * Get crtc VBLANK count. + * + * \param dev DRM device + * \param data user arguement, pointing to a drm_crtc_get_sequence structure. + * \param file_priv drm file private for the user's open file descriptor + */ + +int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_crtc *crtc; + struct drm_vblank_crtc *vblank; + int pipe; + struct drm_crtc_get_sequence *get_seq = data; + ktime_t now; + bool vblank_enabled; + int ret; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + if (!dev->irq_enabled) + return -EINVAL; + + crtc = drm_crtc_find(dev, file_priv, get_seq->crtc_id); + if (!crtc) + return -ENOENT; + + pipe = drm_crtc_index(crtc); + + vblank = &dev->vblank[pipe]; + vblank_enabled = dev->vblank_disable_immediate && READ_ONCE(vblank->enabled); + + if (!vblank_enabled) { + ret = drm_crtc_vblank_get(crtc); + if (ret) { + DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret); + return ret; + } + } + drm_modeset_lock(&crtc->mutex, NULL); + if (crtc->state) + get_seq->active = crtc->state->enable; + else + get_seq->active = crtc->enabled; + drm_modeset_unlock(&crtc->mutex); + get_seq->sequence = drm_vblank_count_and_time(dev, pipe, &now); + get_seq->sequence_ns = ktime_to_ns(now); + if (!vblank_enabled) + drm_crtc_vblank_put(crtc); + return 0; +} + +/* + * Queue a event for VBLANK sequence + * + * \param dev DRM device + * \param data user arguement, pointing to a drm_crtc_queue_sequence structure. + * \param file_priv drm file private for the user's open file descriptor + */ + +int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_crtc *crtc; + struct drm_vblank_crtc *vblank; + int pipe; + struct drm_crtc_queue_sequence *queue_seq = data; + ktime_t now; + struct drm_pending_vblank_event *e; + u32 flags; + u64 seq; + u64 req_seq; + int ret; + unsigned long spin_flags; + + if (!drm_core_check_feature(dev, DRIVER_MODESET)) + return -EINVAL; + + if (!dev->irq_enabled) + return -EINVAL; + + crtc = drm_crtc_find(dev, file_priv, queue_seq->crtc_id); + if (!crtc) + return -ENOENT; + + flags = queue_seq->flags; + /* Check valid flag bits */ + if (flags & ~(DRM_CRTC_SEQUENCE_RELATIVE| + DRM_CRTC_SEQUENCE_NEXT_ON_MISS)) + return -EINVAL; + + pipe = drm_crtc_index(crtc); + + vblank = &dev->vblank[pipe]; + + e = kzalloc(sizeof(*e), GFP_KERNEL); + if (e == NULL) + return -ENOMEM; + + ret = drm_crtc_vblank_get(crtc); + if (ret) { + DRM_DEBUG("crtc %d failed to acquire vblank counter, %d\n", pipe, ret); + goto err_free; + } + + seq = drm_vblank_count_and_time(dev, pipe, &now); + req_seq = queue_seq->sequence; + + if (flags & DRM_CRTC_SEQUENCE_RELATIVE) + req_seq += seq; + + if ((flags & DRM_CRTC_SEQUENCE_NEXT_ON_MISS) && vblank_passed(seq, req_seq)) + req_seq = seq + 1; + + e->pipe = pipe; + e->event.base.type = DRM_EVENT_CRTC_SEQUENCE; + e->event.base.length = sizeof(e->event.seq); + e->event.seq.user_data = queue_seq->user_data; + + spin_lock_irqsave(&dev->event_lock, spin_flags); + + /* + * drm_crtc_vblank_off() might have been called after we called + * drm_crtc_vblank_get(). drm_crtc_vblank_off() holds event_lock around the + * vblank disable, so no need for further locking. The reference from + * drm_crtc_vblank_get() protects against vblank disable from another source. + */ + if (!READ_ONCE(vblank->enabled)) { + ret = -EINVAL; + goto err_unlock; + } + + ret = drm_event_reserve_init_locked(dev, file_priv, &e->base, + &e->event.base); + + if (ret) + goto err_unlock; + + e->sequence = req_seq; + + if (vblank_passed(seq, req_seq)) { + drm_crtc_vblank_put(crtc); + send_vblank_event(dev, e, seq, now); + queue_seq->sequence = seq; + } else { + /* drm_handle_vblank_events will call drm_vblank_put */ + list_add_tail(&e->base.link, &dev->vblank_event_list); + queue_seq->sequence = req_seq; + } + + spin_unlock_irqrestore(&dev->event_lock, spin_flags); + return 0; + +err_unlock: + spin_unlock_irqrestore(&dev->event_lock, spin_flags); + drm_crtc_vblank_put(crtc); +err_free: + kfree(e); + return ret; +} diff --git a/drivers/gpu/drm/etnaviv/Kconfig b/drivers/gpu/drm/etnaviv/Kconfig index 38b477b5fbf9..a29b8f59eb15 100644 --- a/drivers/gpu/drm/etnaviv/Kconfig +++ b/drivers/gpu/drm/etnaviv/Kconfig @@ -7,8 +7,6 @@ config DRM_ETNAVIV select SHMEM select SYNC_FILE select TMPFS - select IOMMU_API - select IOMMU_SUPPORT select WANT_DEV_COREDUMP select CMA if HAVE_DMA_CONTIGUOUS select DMA_CMA if HAVE_DMA_CONTIGUOUS diff --git a/drivers/gpu/drm/etnaviv/Makefile b/drivers/gpu/drm/etnaviv/Makefile index 4f76c992043f..15c3bfa89a79 100644 --- a/drivers/gpu/drm/etnaviv/Makefile +++ b/drivers/gpu/drm/etnaviv/Makefile @@ -10,6 +10,7 @@ etnaviv-y := \ etnaviv_gpu.o \ etnaviv_iommu_v2.o \ etnaviv_iommu.o \ - etnaviv_mmu.o + etnaviv_mmu.o \ + etnaviv_perfmon.o obj-$(CONFIG_DRM_ETNAVIV) += etnaviv.o diff --git a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c index ed9588f36bc9..9e7098e3207f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_buffer.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_buffer.c @@ -250,6 +250,42 @@ void etnaviv_buffer_end(struct etnaviv_gpu *gpu) } } +/* Append a 'sync point' to the ring buffer. */ +void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event) +{ + struct etnaviv_cmdbuf *buffer = gpu->buffer; + unsigned int waitlink_offset = buffer->user_size - 16; + u32 dwords, target; + + /* + * We need at most 3 dwords in the return target: + * 1 event + 1 end + 1 wait + 1 link. + */ + dwords = 4; + target = etnaviv_buffer_reserve(gpu, buffer, dwords); + + /* Signal sync point event */ + CMD_LOAD_STATE(buffer, VIVS_GL_EVENT, VIVS_GL_EVENT_EVENT_ID(event) | + VIVS_GL_EVENT_FROM_PE); + + /* Stop the FE to 'pause' the GPU */ + CMD_END(buffer); + + /* Append waitlink */ + CMD_WAIT(buffer); + CMD_LINK(buffer, 2, etnaviv_cmdbuf_get_va(buffer) + + buffer->user_size - 4); + + /* + * Kick off the 'sync point' command by replacing the previous + * WAIT with a link to the address in the ring buffer. + */ + etnaviv_buffer_replace_wait(buffer, waitlink_offset, + VIV_FE_LINK_HEADER_OP_LINK | + VIV_FE_LINK_HEADER_PREFETCH(dwords), + target); +} + /* Append a command buffer to the ring buffer. */ void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct etnaviv_cmdbuf *cmdbuf) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c index 633e0f07cbac..66ac79558bbd 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.c @@ -19,6 +19,7 @@ #include "etnaviv_cmdbuf.h" #include "etnaviv_gpu.h" #include "etnaviv_mmu.h" +#include "etnaviv_perfmon.h" #define SUBALLOC_SIZE SZ_256K #define SUBALLOC_GRANULE SZ_4K @@ -87,9 +88,10 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc) struct etnaviv_cmdbuf * etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size, - size_t nr_bos) + size_t nr_bos, size_t nr_pmrs) { struct etnaviv_cmdbuf *cmdbuf; + struct etnaviv_perfmon_request *pmrs; size_t sz = size_vstruct(nr_bos, sizeof(cmdbuf->bo_map[0]), sizeof(*cmdbuf)); int granule_offs, order, ret; @@ -98,6 +100,12 @@ etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size, if (!cmdbuf) return NULL; + sz = sizeof(*pmrs) * nr_pmrs; + pmrs = kzalloc(sz, GFP_KERNEL); + if (!pmrs) + goto out_free_cmdbuf; + + cmdbuf->pmrs = pmrs; cmdbuf->suballoc = suballoc; cmdbuf->size = size; @@ -124,6 +132,10 @@ retry: cmdbuf->vaddr = suballoc->vaddr + cmdbuf->suballoc_offset; return cmdbuf; + +out_free_cmdbuf: + kfree(cmdbuf); + return NULL; } void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf) @@ -139,6 +151,7 @@ void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf) suballoc->free_space = 1; mutex_unlock(&suballoc->lock); wake_up_all(&suballoc->free_event); + kfree(cmdbuf->pmrs); kfree(cmdbuf); } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h index 80d78076c679..b6348b9f2a9d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_cmdbuf.h @@ -21,6 +21,7 @@ struct etnaviv_gpu; struct etnaviv_cmdbuf_suballoc; +struct etnaviv_perfmon_request; struct etnaviv_cmdbuf { /* suballocator this cmdbuf is allocated from */ @@ -38,6 +39,9 @@ struct etnaviv_cmdbuf { u32 exec_state; /* per GPU in-flight list */ struct list_head node; + /* perfmon requests */ + unsigned int nr_pmrs; + struct etnaviv_perfmon_request *pmrs; /* BOs attached to this command buffer */ unsigned int nr_bos; struct etnaviv_vram_mapping *bo_map[0]; @@ -49,7 +53,7 @@ void etnaviv_cmdbuf_suballoc_destroy(struct etnaviv_cmdbuf_suballoc *suballoc); struct etnaviv_cmdbuf * etnaviv_cmdbuf_new(struct etnaviv_cmdbuf_suballoc *suballoc, u32 size, - size_t nr_bos); + size_t nr_bos, size_t nr_pmrs); void etnaviv_cmdbuf_free(struct etnaviv_cmdbuf *cmdbuf); u32 etnaviv_cmdbuf_get_va(struct etnaviv_cmdbuf *buf); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 2cb4773823c2..491eddf9b150 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -23,6 +23,7 @@ #include "etnaviv_gpu.h" #include "etnaviv_gem.h" #include "etnaviv_mmu.h" +#include "etnaviv_perfmon.h" #ifdef CONFIG_DRM_ETNAVIV_REGISTER_LOGGING static bool reglog; @@ -451,6 +452,46 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, return ret; } +static int etnaviv_ioctl_pm_query_dom(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct etnaviv_drm_private *priv = dev->dev_private; + struct drm_etnaviv_pm_domain *args = data; + struct etnaviv_gpu *gpu; + + /* reject as long as the feature isn't stable */ + return -EINVAL; + + if (args->pipe >= ETNA_MAX_PIPES) + return -EINVAL; + + gpu = priv->gpu[args->pipe]; + if (!gpu) + return -ENXIO; + + return etnaviv_pm_query_dom(gpu, args); +} + +static int etnaviv_ioctl_pm_query_sig(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct etnaviv_drm_private *priv = dev->dev_private; + struct drm_etnaviv_pm_signal *args = data; + struct etnaviv_gpu *gpu; + + /* reject as long as the feature isn't stable */ + return -EINVAL; + + if (args->pipe >= ETNA_MAX_PIPES) + return -EINVAL; + + gpu = priv->gpu[args->pipe]; + if (!gpu) + return -ENXIO; + + return etnaviv_pm_query_sig(gpu, args); +} + static const struct drm_ioctl_desc etnaviv_ioctls[] = { #define ETNA_IOCTL(n, func, flags) \ DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags) @@ -463,6 +504,8 @@ static const struct drm_ioctl_desc etnaviv_ioctls[] = { ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_AUTH|DRM_RENDER_ALLOW), ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_AUTH|DRM_RENDER_ALLOW), + ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_AUTH|DRM_RENDER_ALLOW), + ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_AUTH|DRM_RENDER_ALLOW), }; static const struct vm_operations_struct vm_ops = { diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h index 058389f93b69..d249acb6da08 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h @@ -26,7 +26,6 @@ #include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/list.h> -#include <linux/iommu.h> #include <linux/types.h> #include <linux/sizes.h> @@ -92,15 +91,12 @@ int etnaviv_gem_cpu_fini(struct drm_gem_object *obj); void etnaviv_gem_free_object(struct drm_gem_object *obj); int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, u32 size, u32 flags, u32 *handle); -struct drm_gem_object *etnaviv_gem_new_locked(struct drm_device *dev, - u32 size, u32 flags); -struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev, - u32 size, u32 flags); int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file, uintptr_t ptr, u32 size, u32 flags, u32 *handle); u16 etnaviv_buffer_init(struct etnaviv_gpu *gpu); u16 etnaviv_buffer_config_mmuv2(struct etnaviv_gpu *gpu, u32 mtlb_addr, u32 safe_addr); void etnaviv_buffer_end(struct etnaviv_gpu *gpu); +void etnaviv_sync_point_queue(struct etnaviv_gpu *gpu, unsigned int event); void etnaviv_buffer_queue(struct etnaviv_gpu *gpu, unsigned int event, struct etnaviv_cmdbuf *cmdbuf); void etnaviv_validate_init(void); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index 57881167ccd2..5884ab623e0a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -704,25 +704,6 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, return ret; } -struct drm_gem_object *etnaviv_gem_new(struct drm_device *dev, - u32 size, u32 flags) -{ - struct drm_gem_object *obj; - int ret; - - obj = __etnaviv_gem_new(dev, size, flags); - if (IS_ERR(obj)) - return obj; - - ret = etnaviv_gem_obj_add(dev, obj); - if (ret < 0) { - drm_gem_object_put_unlocked(obj); - return ERR_PTR(ret); - } - - return obj; -} - int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags, struct reservation_object *robj, const struct etnaviv_gem_ops *ops, struct etnaviv_gem_object **res) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 46dfe0737f43..ff911541a190 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -21,6 +21,7 @@ #include "etnaviv_drv.h" #include "etnaviv_gpu.h" #include "etnaviv_gem.h" +#include "etnaviv_perfmon.h" /* * Cmdstream submission: @@ -283,6 +284,54 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, void *stream, return 0; } +static int submit_perfmon_validate(struct etnaviv_gem_submit *submit, + struct etnaviv_cmdbuf *cmdbuf, + const struct drm_etnaviv_gem_submit_pmr *pmrs, + u32 nr_pms) +{ + u32 i; + + for (i = 0; i < nr_pms; i++) { + const struct drm_etnaviv_gem_submit_pmr *r = pmrs + i; + struct etnaviv_gem_submit_bo *bo; + int ret; + + ret = submit_bo(submit, r->read_idx, &bo); + if (ret) + return ret; + + /* at offset 0 a sequence number gets stored used for userspace sync */ + if (r->read_offset == 0) { + DRM_ERROR("perfmon request: offset is 0"); + return -EINVAL; + } + + if (r->read_offset >= bo->obj->base.size - sizeof(u32)) { + DRM_ERROR("perfmon request: offset %u outside object", i); + return -EINVAL; + } + + if (r->flags & ~(ETNA_PM_PROCESS_PRE | ETNA_PM_PROCESS_POST)) { + DRM_ERROR("perfmon request: flags are not valid"); + return -EINVAL; + } + + if (etnaviv_pm_req_validate(r, cmdbuf->exec_state)) { + DRM_ERROR("perfmon request: domain or signal not valid"); + return -EINVAL; + } + + cmdbuf->pmrs[i].flags = r->flags; + cmdbuf->pmrs[i].domain = r->domain; + cmdbuf->pmrs[i].signal = r->signal; + cmdbuf->pmrs[i].sequence = r->sequence; + cmdbuf->pmrs[i].offset = r->read_offset; + cmdbuf->pmrs[i].bo_vma = etnaviv_gem_vmap(&bo->obj->base); + } + + return 0; +} + static void submit_cleanup(struct etnaviv_gem_submit *submit) { unsigned i; @@ -306,6 +355,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, struct etnaviv_drm_private *priv = dev->dev_private; struct drm_etnaviv_gem_submit *args = data; struct drm_etnaviv_gem_submit_reloc *relocs; + struct drm_etnaviv_gem_submit_pmr *pmrs; struct drm_etnaviv_gem_submit_bo *bos; struct etnaviv_gem_submit *submit; struct etnaviv_cmdbuf *cmdbuf; @@ -347,11 +397,12 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, */ bos = kvmalloc_array(args->nr_bos, sizeof(*bos), GFP_KERNEL); relocs = kvmalloc_array(args->nr_relocs, sizeof(*relocs), GFP_KERNEL); + pmrs = kvmalloc_array(args->nr_pmrs, sizeof(*pmrs), GFP_KERNEL); stream = kvmalloc_array(1, args->stream_size, GFP_KERNEL); cmdbuf = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, ALIGN(args->stream_size, 8) + 8, - args->nr_bos); - if (!bos || !relocs || !stream || !cmdbuf) { + args->nr_bos, args->nr_pmrs); + if (!bos || !relocs || !pmrs || !stream || !cmdbuf) { ret = -ENOMEM; goto err_submit_cmds; } @@ -373,6 +424,14 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, goto err_submit_cmds; } + ret = copy_from_user(pmrs, u64_to_user_ptr(args->pmrs), + args->nr_pmrs * sizeof(*pmrs)); + if (ret) { + ret = -EFAULT; + goto err_submit_cmds; + } + cmdbuf->nr_pmrs = args->nr_pmrs; + ret = copy_from_user(stream, u64_to_user_ptr(args->stream), args->stream_size); if (ret) { @@ -441,6 +500,10 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data, if (ret) goto out; + ret = submit_perfmon_validate(submit, cmdbuf, pmrs, args->nr_pmrs); + if (ret) + goto out; + memcpy(cmdbuf->vaddr, stream, args->stream_size); cmdbuf->user_size = ALIGN(args->stream_size, 8); @@ -496,6 +559,8 @@ err_submit_cmds: kvfree(bos); if (relocs) kvfree(relocs); + if (pmrs) + kvfree(pmrs); return ret; } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c index fc9a6a83dfc7..8197e1d6ed11 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c @@ -25,6 +25,7 @@ #include "etnaviv_gpu.h" #include "etnaviv_gem.h" #include "etnaviv_mmu.h" +#include "etnaviv_perfmon.h" #include "common.xml.h" #include "state.xml.h" #include "state_hi.xml.h" @@ -420,9 +421,10 @@ static void etnaviv_gpu_update_clock(struct etnaviv_gpu *gpu) gpu->base_rate_shader >> gpu->freq_scale); } else { unsigned int fscale = 1 << (6 - gpu->freq_scale); - u32 clock = VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS | - VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale); + u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL); + clock &= ~VIVS_HI_CLOCK_CONTROL_FSCALE_VAL__MASK; + clock |= VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale); etnaviv_gpu_load_clock(gpu, clock); } } @@ -433,24 +435,14 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) unsigned long timeout; bool failed = true; - /* TODO - * - * - clock gating - * - puls eater - * - what about VG? - */ - /* We hope that the GPU resets in under one second */ timeout = jiffies + msecs_to_jiffies(1000); while (time_is_after_jiffies(timeout)) { /* enable clock */ - etnaviv_gpu_update_clock(gpu); - - control = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL); - - /* Wait for stable clock. Vivante's code waited for 1ms */ - usleep_range(1000, 10000); + unsigned int fscale = 1 << (6 - gpu->freq_scale); + control = VIVS_HI_CLOCK_CONTROL_FSCALE_VAL(fscale); + etnaviv_gpu_load_clock(gpu, control); /* isolate the GPU. */ control |= VIVS_HI_CLOCK_CONTROL_ISOLATE_GPU; @@ -461,7 +453,7 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control); /* wait for reset. */ - msleep(1); + usleep_range(10, 20); /* reset soft reset bit. */ control &= ~VIVS_HI_CLOCK_CONTROL_SOFT_RESET; @@ -490,6 +482,10 @@ static int etnaviv_hw_reset(struct etnaviv_gpu *gpu) continue; } + /* disable debug registers, as they are not normally needed */ + control |= VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS; + gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, control); + failed = false; break; } @@ -721,7 +717,7 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) } /* Create buffer: */ - gpu->buffer = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, PAGE_SIZE, 0); + gpu->buffer = etnaviv_cmdbuf_new(gpu->cmdbuf_suballoc, PAGE_SIZE, 0, 0); if (!gpu->buffer) { ret = -ENOMEM; dev_err(gpu->dev, "could not create command buffer\n"); @@ -739,10 +735,9 @@ int etnaviv_gpu_init(struct etnaviv_gpu *gpu) /* Setup event management */ spin_lock_init(&gpu->event_spinlock); init_completion(&gpu->event_free); - for (i = 0; i < ARRAY_SIZE(gpu->event); i++) { - gpu->event[i].used = false; + bitmap_zero(gpu->event_bitmap, ETNA_NR_EVENTS); + for (i = 0; i < ARRAY_SIZE(gpu->event); i++) complete(&gpu->event_free); - } /* Now program the hardware */ mutex_lock(&gpu->lock); @@ -926,7 +921,7 @@ static void recover_worker(struct work_struct *work) struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu, recover_work); unsigned long flags; - unsigned int i; + unsigned int i = 0; dev_err(gpu->dev, "hangcheck recover!\n"); @@ -945,14 +940,12 @@ static void recover_worker(struct work_struct *work) /* complete all events, the GPU won't do it after the reset */ spin_lock_irqsave(&gpu->event_spinlock, flags); - for (i = 0; i < ARRAY_SIZE(gpu->event); i++) { - if (!gpu->event[i].used) - continue; + for_each_set_bit_from(i, gpu->event_bitmap, ETNA_NR_EVENTS) { dma_fence_signal(gpu->event[i].fence); gpu->event[i].fence = NULL; - gpu->event[i].used = false; complete(&gpu->event_free); } + bitmap_zero(gpu->event_bitmap, ETNA_NR_EVENTS); spin_unlock_irqrestore(&gpu->event_spinlock, flags); gpu->completed_fence = gpu->active_fence; @@ -1140,30 +1133,45 @@ int etnaviv_gpu_fence_sync_obj(struct etnaviv_gem_object *etnaviv_obj, * event management: */ -static unsigned int event_alloc(struct etnaviv_gpu *gpu) +static int event_alloc(struct etnaviv_gpu *gpu, unsigned nr_events, + unsigned int *events) { - unsigned long ret, flags; - unsigned int i, event = ~0U; + unsigned long flags, timeout = msecs_to_jiffies(10 * 10000); + unsigned i, acquired = 0; - ret = wait_for_completion_timeout(&gpu->event_free, - msecs_to_jiffies(10 * 10000)); - if (!ret) - dev_err(gpu->dev, "wait_for_completion_timeout failed"); + for (i = 0; i < nr_events; i++) { + unsigned long ret; - spin_lock_irqsave(&gpu->event_spinlock, flags); + ret = wait_for_completion_timeout(&gpu->event_free, timeout); - /* find first free event */ - for (i = 0; i < ARRAY_SIZE(gpu->event); i++) { - if (gpu->event[i].used == false) { - gpu->event[i].used = true; - event = i; - break; + if (!ret) { + dev_err(gpu->dev, "wait_for_completion_timeout failed"); + goto out; } + + acquired++; + timeout = ret; + } + + spin_lock_irqsave(&gpu->event_spinlock, flags); + + for (i = 0; i < nr_events; i++) { + int event = find_first_zero_bit(gpu->event_bitmap, ETNA_NR_EVENTS); + + events[i] = event; + memset(&gpu->event[event], 0, sizeof(struct etnaviv_event)); + set_bit(event, gpu->event_bitmap); } spin_unlock_irqrestore(&gpu->event_spinlock, flags); - return event; + return 0; + +out: + for (i = 0; i < acquired; i++) + complete(&gpu->event_free); + + return -EBUSY; } static void event_free(struct etnaviv_gpu *gpu, unsigned int event) @@ -1172,12 +1180,12 @@ static void event_free(struct etnaviv_gpu *gpu, unsigned int event) spin_lock_irqsave(&gpu->event_spinlock, flags); - if (gpu->event[event].used == false) { + if (!test_bit(event, gpu->event_bitmap)) { dev_warn(gpu->dev, "event %u is already marked as free", event); spin_unlock_irqrestore(&gpu->event_spinlock, flags); } else { - gpu->event[event].used = false; + clear_bit(event, gpu->event_bitmap); spin_unlock_irqrestore(&gpu->event_spinlock, flags); complete(&gpu->event_free); @@ -1311,12 +1319,71 @@ void etnaviv_gpu_pm_put(struct etnaviv_gpu *gpu) pm_runtime_put_autosuspend(gpu->dev); } +static void sync_point_perfmon_sample(struct etnaviv_gpu *gpu, + struct etnaviv_event *event, unsigned int flags) +{ + const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf; + unsigned int i; + + for (i = 0; i < cmdbuf->nr_pmrs; i++) { + const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i; + + if (pmr->flags == flags) + etnaviv_perfmon_process(gpu, pmr); + } +} + +static void sync_point_perfmon_sample_pre(struct etnaviv_gpu *gpu, + struct etnaviv_event *event) +{ + u32 val; + + /* disable clock gating */ + val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS); + val &= ~VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING; + gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val); + + /* enable debug register */ + val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL); + val &= ~VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS; + gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val); + + sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_PRE); +} + +static void sync_point_perfmon_sample_post(struct etnaviv_gpu *gpu, + struct etnaviv_event *event) +{ + const struct etnaviv_cmdbuf *cmdbuf = event->cmdbuf; + unsigned int i; + u32 val; + + sync_point_perfmon_sample(gpu, event, ETNA_PM_PROCESS_POST); + + for (i = 0; i < cmdbuf->nr_pmrs; i++) { + const struct etnaviv_perfmon_request *pmr = cmdbuf->pmrs + i; + + *pmr->bo_vma = pmr->sequence; + } + + /* disable debug register */ + val = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL); + val |= VIVS_HI_CLOCK_CONTROL_DISABLE_DEBUG_REGISTERS; + gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, val); + + /* enable clock gating */ + val = gpu_read(gpu, VIVS_PM_POWER_CONTROLS); + val |= VIVS_PM_POWER_CONTROLS_ENABLE_MODULE_CLOCK_GATING; + gpu_write(gpu, VIVS_PM_POWER_CONTROLS, val); +} + + /* add bo's to gpu's ring, and kick gpu: */ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, struct etnaviv_gem_submit *submit, struct etnaviv_cmdbuf *cmdbuf) { struct dma_fence *fence; - unsigned int event, i; + unsigned int i, nr_events = 1, event[3]; int ret; ret = etnaviv_gpu_pm_get_sync(gpu); @@ -1332,10 +1399,19 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, * */ - event = event_alloc(gpu); - if (unlikely(event == ~0U)) { - DRM_ERROR("no free event\n"); - ret = -EBUSY; + /* + * if there are performance monitor requests we need to have + * - a sync point to re-configure gpu and process ETNA_PM_PROCESS_PRE + * requests. + * - a sync point to re-configure gpu, process ETNA_PM_PROCESS_POST requests + * and update the sequence number for userspace. + */ + if (cmdbuf->nr_pmrs) + nr_events = 3; + + ret = event_alloc(gpu, nr_events, event); + if (ret) { + DRM_ERROR("no free events\n"); goto out_pm_put; } @@ -1343,12 +1419,14 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, fence = etnaviv_gpu_fence_alloc(gpu); if (!fence) { - event_free(gpu, event); + for (i = 0; i < nr_events; i++) + event_free(gpu, event[i]); + ret = -ENOMEM; goto out_unlock; } - gpu->event[event].fence = fence; + gpu->event[event[0]].fence = fence; submit->fence = dma_fence_get(fence); gpu->active_fence = submit->fence->seqno; @@ -1358,7 +1436,19 @@ int etnaviv_gpu_submit(struct etnaviv_gpu *gpu, gpu->lastctx = cmdbuf->ctx; } - etnaviv_buffer_queue(gpu, event, cmdbuf); + if (cmdbuf->nr_pmrs) { + gpu->event[event[1]].sync_point = &sync_point_perfmon_sample_pre; + gpu->event[event[1]].cmdbuf = cmdbuf; + etnaviv_sync_point_queue(gpu, event[1]); + } + + etnaviv_buffer_queue(gpu, event[0], cmdbuf); + + if (cmdbuf->nr_pmrs) { + gpu->event[event[2]].sync_point = &sync_point_perfmon_sample_post; + gpu->event[event[2]].cmdbuf = cmdbuf; + etnaviv_sync_point_queue(gpu, event[2]); + } cmdbuf->fence = fence; list_add_tail(&cmdbuf->node, &gpu->active_cmd_list); @@ -1394,6 +1484,24 @@ out_pm_put: return ret; } +static void etnaviv_process_sync_point(struct etnaviv_gpu *gpu, + struct etnaviv_event *event) +{ + u32 addr = gpu_read(gpu, VIVS_FE_DMA_ADDRESS); + + event->sync_point(gpu, event); + etnaviv_gpu_start_fe(gpu, addr + 2, 2); +} + +static void sync_point_worker(struct work_struct *work) +{ + struct etnaviv_gpu *gpu = container_of(work, struct etnaviv_gpu, + sync_point_work); + + etnaviv_process_sync_point(gpu, &gpu->event[gpu->sync_point_event]); + event_free(gpu, gpu->sync_point_event); +} + /* * Init/Cleanup: */ @@ -1440,7 +1548,15 @@ static irqreturn_t irq_handler(int irq, void *data) dev_dbg(gpu->dev, "event %u\n", event); + if (gpu->event[event].sync_point) { + gpu->sync_point_event = event; + etnaviv_queue_work(gpu->drm, &gpu->sync_point_work); + } + fence = gpu->event[event].fence; + if (!fence) + continue; + gpu->event[event].fence = NULL; dma_fence_signal(fence); @@ -1645,6 +1761,7 @@ static int etnaviv_gpu_bind(struct device *dev, struct device *master, INIT_LIST_HEAD(&gpu->active_cmd_list); INIT_WORK(&gpu->retire_work, retire_worker); + INIT_WORK(&gpu->sync_point_work, sync_point_worker); INIT_WORK(&gpu->recover_work, recover_worker); init_waitqueue_head(&gpu->fence_event); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h index 689cb8f3680c..4f10f147297a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.h @@ -88,13 +88,17 @@ struct etnaviv_chip_identity { }; struct etnaviv_event { - bool used; struct dma_fence *fence; + struct etnaviv_cmdbuf *cmdbuf; + + void (*sync_point)(struct etnaviv_gpu *gpu, struct etnaviv_event *event); }; struct etnaviv_cmdbuf_suballoc; struct etnaviv_cmdbuf; +#define ETNA_NR_EVENTS 30 + struct etnaviv_gpu { struct drm_device *drm; struct thermal_cooling_device *cooling; @@ -112,7 +116,8 @@ struct etnaviv_gpu { u32 memory_base; /* event management: */ - struct etnaviv_event event[30]; + DECLARE_BITMAP(event_bitmap, ETNA_NR_EVENTS); + struct etnaviv_event event[ETNA_NR_EVENTS]; struct completion event_free; spinlock_t event_spinlock; @@ -133,6 +138,10 @@ struct etnaviv_gpu { /* worker for handling active-list retiring: */ struct work_struct retire_work; + /* worker for handling 'sync' points: */ + struct work_struct sync_point_work; + int sync_point_event; + void __iomem *mmio; int irq; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c index 7a7c97f599d7..14e24ac6573f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu.c @@ -14,7 +14,6 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <linux/iommu.h> #include <linux/platform_device.h> #include <linux/sizes.h> #include <linux/slab.h> @@ -31,174 +30,115 @@ #define GPU_MEM_START 0x80000000 -struct etnaviv_iommu_domain_pgtable { - u32 *pgtable; - dma_addr_t paddr; +struct etnaviv_iommuv1_domain { + struct etnaviv_iommu_domain base; + u32 *pgtable_cpu; + dma_addr_t pgtable_dma; }; -struct etnaviv_iommu_domain { - struct iommu_domain domain; - struct device *dev; - void *bad_page_cpu; - dma_addr_t bad_page_dma; - struct etnaviv_iommu_domain_pgtable pgtable; - spinlock_t map_lock; -}; - -static struct etnaviv_iommu_domain *to_etnaviv_domain(struct iommu_domain *domain) -{ - return container_of(domain, struct etnaviv_iommu_domain, domain); -} - -static int pgtable_alloc(struct etnaviv_iommu_domain_pgtable *pgtable, - size_t size) -{ - pgtable->pgtable = dma_alloc_coherent(NULL, size, &pgtable->paddr, GFP_KERNEL); - if (!pgtable->pgtable) - return -ENOMEM; - - return 0; -} - -static void pgtable_free(struct etnaviv_iommu_domain_pgtable *pgtable, - size_t size) +static struct etnaviv_iommuv1_domain * +to_etnaviv_domain(struct etnaviv_iommu_domain *domain) { - dma_free_coherent(NULL, size, pgtable->pgtable, pgtable->paddr); -} - -static u32 pgtable_read(struct etnaviv_iommu_domain_pgtable *pgtable, - unsigned long iova) -{ - /* calcuate index into page table */ - unsigned int index = (iova - GPU_MEM_START) / SZ_4K; - phys_addr_t paddr; - - paddr = pgtable->pgtable[index]; - - return paddr; + return container_of(domain, struct etnaviv_iommuv1_domain, base); } -static void pgtable_write(struct etnaviv_iommu_domain_pgtable *pgtable, - unsigned long iova, phys_addr_t paddr) -{ - /* calcuate index into page table */ - unsigned int index = (iova - GPU_MEM_START) / SZ_4K; - - pgtable->pgtable[index] = paddr; -} - -static int __etnaviv_iommu_init(struct etnaviv_iommu_domain *etnaviv_domain) +static int __etnaviv_iommu_init(struct etnaviv_iommuv1_domain *etnaviv_domain) { u32 *p; - int ret, i; - - etnaviv_domain->bad_page_cpu = dma_alloc_coherent(etnaviv_domain->dev, - SZ_4K, - &etnaviv_domain->bad_page_dma, - GFP_KERNEL); - if (!etnaviv_domain->bad_page_cpu) + int i; + + etnaviv_domain->base.bad_page_cpu = dma_alloc_coherent( + etnaviv_domain->base.dev, + SZ_4K, + &etnaviv_domain->base.bad_page_dma, + GFP_KERNEL); + if (!etnaviv_domain->base.bad_page_cpu) return -ENOMEM; - p = etnaviv_domain->bad_page_cpu; + p = etnaviv_domain->base.bad_page_cpu; for (i = 0; i < SZ_4K / 4; i++) *p++ = 0xdead55aa; - ret = pgtable_alloc(&etnaviv_domain->pgtable, PT_SIZE); - if (ret < 0) { - dma_free_coherent(etnaviv_domain->dev, SZ_4K, - etnaviv_domain->bad_page_cpu, - etnaviv_domain->bad_page_dma); - return ret; + etnaviv_domain->pgtable_cpu = + dma_alloc_coherent(etnaviv_domain->base.dev, PT_SIZE, + &etnaviv_domain->pgtable_dma, + GFP_KERNEL); + if (!etnaviv_domain->pgtable_cpu) { + dma_free_coherent(etnaviv_domain->base.dev, SZ_4K, + etnaviv_domain->base.bad_page_cpu, + etnaviv_domain->base.bad_page_dma); + return -ENOMEM; } for (i = 0; i < PT_ENTRIES; i++) - etnaviv_domain->pgtable.pgtable[i] = - etnaviv_domain->bad_page_dma; - - spin_lock_init(&etnaviv_domain->map_lock); + etnaviv_domain->pgtable_cpu[i] = + etnaviv_domain->base.bad_page_dma; return 0; } -static void etnaviv_domain_free(struct iommu_domain *domain) +static void etnaviv_iommuv1_domain_free(struct etnaviv_iommu_domain *domain) { - struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain); + struct etnaviv_iommuv1_domain *etnaviv_domain = + to_etnaviv_domain(domain); - pgtable_free(&etnaviv_domain->pgtable, PT_SIZE); + dma_free_coherent(etnaviv_domain->base.dev, PT_SIZE, + etnaviv_domain->pgtable_cpu, + etnaviv_domain->pgtable_dma); - dma_free_coherent(etnaviv_domain->dev, SZ_4K, - etnaviv_domain->bad_page_cpu, - etnaviv_domain->bad_page_dma); + dma_free_coherent(etnaviv_domain->base.dev, SZ_4K, + etnaviv_domain->base.bad_page_cpu, + etnaviv_domain->base.bad_page_dma); kfree(etnaviv_domain); } -static int etnaviv_iommuv1_map(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot) +static int etnaviv_iommuv1_map(struct etnaviv_iommu_domain *domain, + unsigned long iova, phys_addr_t paddr, + size_t size, int prot) { - struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain); + struct etnaviv_iommuv1_domain *etnaviv_domain = to_etnaviv_domain(domain); + unsigned int index = (iova - GPU_MEM_START) / SZ_4K; if (size != SZ_4K) return -EINVAL; - spin_lock(&etnaviv_domain->map_lock); - pgtable_write(&etnaviv_domain->pgtable, iova, paddr); - spin_unlock(&etnaviv_domain->map_lock); + etnaviv_domain->pgtable_cpu[index] = paddr; return 0; } -static size_t etnaviv_iommuv1_unmap(struct iommu_domain *domain, +static size_t etnaviv_iommuv1_unmap(struct etnaviv_iommu_domain *domain, unsigned long iova, size_t size) { - struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain); + struct etnaviv_iommuv1_domain *etnaviv_domain = + to_etnaviv_domain(domain); + unsigned int index = (iova - GPU_MEM_START) / SZ_4K; if (size != SZ_4K) return -EINVAL; - spin_lock(&etnaviv_domain->map_lock); - pgtable_write(&etnaviv_domain->pgtable, iova, - etnaviv_domain->bad_page_dma); - spin_unlock(&etnaviv_domain->map_lock); + etnaviv_domain->pgtable_cpu[index] = etnaviv_domain->base.bad_page_dma; return SZ_4K; } -static phys_addr_t etnaviv_iommu_iova_to_phys(struct iommu_domain *domain, - dma_addr_t iova) -{ - struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain); - - return pgtable_read(&etnaviv_domain->pgtable, iova); -} - -static size_t etnaviv_iommuv1_dump_size(struct iommu_domain *domain) +static size_t etnaviv_iommuv1_dump_size(struct etnaviv_iommu_domain *domain) { return PT_SIZE; } -static void etnaviv_iommuv1_dump(struct iommu_domain *domain, void *buf) +static void etnaviv_iommuv1_dump(struct etnaviv_iommu_domain *domain, void *buf) { - struct etnaviv_iommu_domain *etnaviv_domain = to_etnaviv_domain(domain); + struct etnaviv_iommuv1_domain *etnaviv_domain = + to_etnaviv_domain(domain); - memcpy(buf, etnaviv_domain->pgtable.pgtable, PT_SIZE); + memcpy(buf, etnaviv_domain->pgtable_cpu, PT_SIZE); } -static const struct etnaviv_iommu_ops etnaviv_iommu_ops = { - .ops = { - .domain_free = etnaviv_domain_free, - .map = etnaviv_iommuv1_map, - .unmap = etnaviv_iommuv1_unmap, - .iova_to_phys = etnaviv_iommu_iova_to_phys, - .pgsize_bitmap = SZ_4K, - }, - .dump_size = etnaviv_iommuv1_dump_size, - .dump = etnaviv_iommuv1_dump, -}; - void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu) { - struct etnaviv_iommu_domain *etnaviv_domain = + struct etnaviv_iommuv1_domain *etnaviv_domain = to_etnaviv_domain(gpu->mmu->domain); u32 pgtable; @@ -210,7 +150,7 @@ void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu) gpu_write(gpu, VIVS_MC_MEMORY_BASE_ADDR_PE, gpu->memory_base); /* set page table address in MC */ - pgtable = (u32)etnaviv_domain->pgtable.paddr; + pgtable = (u32)etnaviv_domain->pgtable_dma; gpu_write(gpu, VIVS_MC_MMU_FE_PAGE_TABLE, pgtable); gpu_write(gpu, VIVS_MC_MMU_TX_PAGE_TABLE, pgtable); @@ -219,28 +159,37 @@ void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu) gpu_write(gpu, VIVS_MC_MMU_RA_PAGE_TABLE, pgtable); } -struct iommu_domain *etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu) +const struct etnaviv_iommu_domain_ops etnaviv_iommuv1_ops = { + .free = etnaviv_iommuv1_domain_free, + .map = etnaviv_iommuv1_map, + .unmap = etnaviv_iommuv1_unmap, + .dump_size = etnaviv_iommuv1_dump_size, + .dump = etnaviv_iommuv1_dump, +}; + +struct etnaviv_iommu_domain * +etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu) { - struct etnaviv_iommu_domain *etnaviv_domain; + struct etnaviv_iommuv1_domain *etnaviv_domain; + struct etnaviv_iommu_domain *domain; int ret; etnaviv_domain = kzalloc(sizeof(*etnaviv_domain), GFP_KERNEL); if (!etnaviv_domain) return NULL; - etnaviv_domain->dev = gpu->dev; + domain = &etnaviv_domain->base; - etnaviv_domain->domain.type = __IOMMU_DOMAIN_PAGING; - etnaviv_domain->domain.ops = &etnaviv_iommu_ops.ops; - etnaviv_domain->domain.pgsize_bitmap = SZ_4K; - etnaviv_domain->domain.geometry.aperture_start = GPU_MEM_START; - etnaviv_domain->domain.geometry.aperture_end = GPU_MEM_START + PT_ENTRIES * SZ_4K - 1; + domain->dev = gpu->dev; + domain->base = GPU_MEM_START; + domain->size = PT_ENTRIES * SZ_4K; + domain->ops = &etnaviv_iommuv1_ops; ret = __etnaviv_iommu_init(etnaviv_domain); if (ret) goto out_free; - return &etnaviv_domain->domain; + return &etnaviv_domain->base; out_free: kfree(etnaviv_domain); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu.h b/drivers/gpu/drm/etnaviv/etnaviv_iommu.h index 8b51e7c16feb..01d59bf70d78 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu.h @@ -18,11 +18,14 @@ #define __ETNAVIV_IOMMU_H__ struct etnaviv_gpu; +struct etnaviv_iommu_domain; -struct iommu_domain *etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu); +struct etnaviv_iommu_domain * +etnaviv_iommuv1_domain_alloc(struct etnaviv_gpu *gpu); void etnaviv_iommuv1_restore(struct etnaviv_gpu *gpu); -struct iommu_domain *etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu); +struct etnaviv_iommu_domain * +etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu); void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu); #endif /* __ETNAVIV_IOMMU_H__ */ diff --git a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c index cbe447ac5974..fc60fc8ddbf0 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_iommu_v2.c @@ -14,7 +14,6 @@ * this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <linux/iommu.h> #include <linux/platform_device.h> #include <linux/sizes.h> #include <linux/slab.h> @@ -40,10 +39,7 @@ #define MMUv2_MAX_STLB_ENTRIES 1024 struct etnaviv_iommuv2_domain { - struct iommu_domain domain; - struct device *dev; - void *bad_page_cpu; - dma_addr_t bad_page_dma; + struct etnaviv_iommu_domain base; /* M(aster) TLB aka first level pagetable */ u32 *mtlb_cpu; dma_addr_t mtlb_dma; @@ -52,13 +48,15 @@ struct etnaviv_iommuv2_domain { dma_addr_t stlb_dma[1024]; }; -static struct etnaviv_iommuv2_domain *to_etnaviv_domain(struct iommu_domain *domain) +static struct etnaviv_iommuv2_domain * +to_etnaviv_domain(struct etnaviv_iommu_domain *domain) { - return container_of(domain, struct etnaviv_iommuv2_domain, domain); + return container_of(domain, struct etnaviv_iommuv2_domain, base); } -static int etnaviv_iommuv2_map(struct iommu_domain *domain, unsigned long iova, - phys_addr_t paddr, size_t size, int prot) +static int etnaviv_iommuv2_map(struct etnaviv_iommu_domain *domain, + unsigned long iova, phys_addr_t paddr, + size_t size, int prot) { struct etnaviv_iommuv2_domain *etnaviv_domain = to_etnaviv_domain(domain); @@ -68,7 +66,7 @@ static int etnaviv_iommuv2_map(struct iommu_domain *domain, unsigned long iova, if (size != SZ_4K) return -EINVAL; - if (prot & IOMMU_WRITE) + if (prot & ETNAVIV_PROT_WRITE) entry |= MMUv2_PTE_WRITEABLE; mtlb_entry = (iova & MMUv2_MTLB_MASK) >> MMUv2_MTLB_SHIFT; @@ -79,8 +77,8 @@ static int etnaviv_iommuv2_map(struct iommu_domain *domain, unsigned long iova, return 0; } -static size_t etnaviv_iommuv2_unmap(struct iommu_domain *domain, - unsigned long iova, size_t size) +static size_t etnaviv_iommuv2_unmap(struct etnaviv_iommu_domain *domain, + unsigned long iova, size_t size) { struct etnaviv_iommuv2_domain *etnaviv_domain = to_etnaviv_domain(domain); @@ -97,38 +95,26 @@ static size_t etnaviv_iommuv2_unmap(struct iommu_domain *domain, return SZ_4K; } -static phys_addr_t etnaviv_iommuv2_iova_to_phys(struct iommu_domain *domain, - dma_addr_t iova) -{ - struct etnaviv_iommuv2_domain *etnaviv_domain = - to_etnaviv_domain(domain); - int mtlb_entry, stlb_entry; - - mtlb_entry = (iova & MMUv2_MTLB_MASK) >> MMUv2_MTLB_SHIFT; - stlb_entry = (iova & MMUv2_STLB_MASK) >> MMUv2_STLB_SHIFT; - - return etnaviv_domain->stlb_cpu[mtlb_entry][stlb_entry] & ~(SZ_4K - 1); -} - static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain) { u32 *p; int ret, i, j; /* allocate scratch page */ - etnaviv_domain->bad_page_cpu = dma_alloc_coherent(etnaviv_domain->dev, - SZ_4K, - &etnaviv_domain->bad_page_dma, - GFP_KERNEL); - if (!etnaviv_domain->bad_page_cpu) { + etnaviv_domain->base.bad_page_cpu = dma_alloc_coherent( + etnaviv_domain->base.dev, + SZ_4K, + &etnaviv_domain->base.bad_page_dma, + GFP_KERNEL); + if (!etnaviv_domain->base.bad_page_cpu) { ret = -ENOMEM; goto fail_mem; } - p = etnaviv_domain->bad_page_cpu; + p = etnaviv_domain->base.bad_page_cpu; for (i = 0; i < SZ_4K / 4; i++) *p++ = 0xdead55aa; - etnaviv_domain->mtlb_cpu = dma_alloc_coherent(etnaviv_domain->dev, + etnaviv_domain->mtlb_cpu = dma_alloc_coherent(etnaviv_domain->base.dev, SZ_4K, &etnaviv_domain->mtlb_dma, GFP_KERNEL); @@ -140,7 +126,7 @@ static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain) /* pre-populate STLB pages (may want to switch to on-demand later) */ for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) { etnaviv_domain->stlb_cpu[i] = - dma_alloc_coherent(etnaviv_domain->dev, + dma_alloc_coherent(etnaviv_domain->base.dev, SZ_4K, &etnaviv_domain->stlb_dma[i], GFP_KERNEL); @@ -159,19 +145,19 @@ static int etnaviv_iommuv2_init(struct etnaviv_iommuv2_domain *etnaviv_domain) return 0; fail_mem: - if (etnaviv_domain->bad_page_cpu) - dma_free_coherent(etnaviv_domain->dev, SZ_4K, - etnaviv_domain->bad_page_cpu, - etnaviv_domain->bad_page_dma); + if (etnaviv_domain->base.bad_page_cpu) + dma_free_coherent(etnaviv_domain->base.dev, SZ_4K, + etnaviv_domain->base.bad_page_cpu, + etnaviv_domain->base.bad_page_dma); if (etnaviv_domain->mtlb_cpu) - dma_free_coherent(etnaviv_domain->dev, SZ_4K, + dma_free_coherent(etnaviv_domain->base.dev, SZ_4K, etnaviv_domain->mtlb_cpu, etnaviv_domain->mtlb_dma); for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) { if (etnaviv_domain->stlb_cpu[i]) - dma_free_coherent(etnaviv_domain->dev, SZ_4K, + dma_free_coherent(etnaviv_domain->base.dev, SZ_4K, etnaviv_domain->stlb_cpu[i], etnaviv_domain->stlb_dma[i]); } @@ -179,23 +165,23 @@ fail_mem: return ret; } -static void etnaviv_iommuv2_domain_free(struct iommu_domain *domain) +static void etnaviv_iommuv2_domain_free(struct etnaviv_iommu_domain *domain) { struct etnaviv_iommuv2_domain *etnaviv_domain = to_etnaviv_domain(domain); int i; - dma_free_coherent(etnaviv_domain->dev, SZ_4K, - etnaviv_domain->bad_page_cpu, - etnaviv_domain->bad_page_dma); + dma_free_coherent(etnaviv_domain->base.dev, SZ_4K, + etnaviv_domain->base.bad_page_cpu, + etnaviv_domain->base.bad_page_dma); - dma_free_coherent(etnaviv_domain->dev, SZ_4K, + dma_free_coherent(etnaviv_domain->base.dev, SZ_4K, etnaviv_domain->mtlb_cpu, etnaviv_domain->mtlb_dma); for (i = 0; i < MMUv2_MAX_STLB_ENTRIES; i++) { if (etnaviv_domain->stlb_cpu[i]) - dma_free_coherent(etnaviv_domain->dev, SZ_4K, + dma_free_coherent(etnaviv_domain->base.dev, SZ_4K, etnaviv_domain->stlb_cpu[i], etnaviv_domain->stlb_dma[i]); } @@ -203,7 +189,7 @@ static void etnaviv_iommuv2_domain_free(struct iommu_domain *domain) vfree(etnaviv_domain); } -static size_t etnaviv_iommuv2_dump_size(struct iommu_domain *domain) +static size_t etnaviv_iommuv2_dump_size(struct etnaviv_iommu_domain *domain) { struct etnaviv_iommuv2_domain *etnaviv_domain = to_etnaviv_domain(domain); @@ -217,7 +203,7 @@ static size_t etnaviv_iommuv2_dump_size(struct iommu_domain *domain) return dump_size; } -static void etnaviv_iommuv2_dump(struct iommu_domain *domain, void *buf) +static void etnaviv_iommuv2_dump(struct etnaviv_iommu_domain *domain, void *buf) { struct etnaviv_iommuv2_domain *etnaviv_domain = to_etnaviv_domain(domain); @@ -230,18 +216,6 @@ static void etnaviv_iommuv2_dump(struct iommu_domain *domain, void *buf) memcpy(buf, etnaviv_domain->stlb_cpu[i], SZ_4K); } -static const struct etnaviv_iommu_ops etnaviv_iommu_ops = { - .ops = { - .domain_free = etnaviv_iommuv2_domain_free, - .map = etnaviv_iommuv2_map, - .unmap = etnaviv_iommuv2_unmap, - .iova_to_phys = etnaviv_iommuv2_iova_to_phys, - .pgsize_bitmap = SZ_4K, - }, - .dump_size = etnaviv_iommuv2_dump_size, - .dump = etnaviv_iommuv2_dump, -}; - void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu) { struct etnaviv_iommuv2_domain *etnaviv_domain = @@ -254,35 +228,45 @@ void etnaviv_iommuv2_restore(struct etnaviv_gpu *gpu) prefetch = etnaviv_buffer_config_mmuv2(gpu, (u32)etnaviv_domain->mtlb_dma, - (u32)etnaviv_domain->bad_page_dma); + (u32)etnaviv_domain->base.bad_page_dma); etnaviv_gpu_start_fe(gpu, (u32)etnaviv_cmdbuf_get_pa(gpu->buffer), prefetch); etnaviv_gpu_wait_idle(gpu, 100); gpu_write(gpu, VIVS_MMUv2_CONTROL, VIVS_MMUv2_CONTROL_ENABLE); } -struct iommu_domain *etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu) + +const struct etnaviv_iommu_domain_ops etnaviv_iommuv2_ops = { + .free = etnaviv_iommuv2_domain_free, + .map = etnaviv_iommuv2_map, + .unmap = etnaviv_iommuv2_unmap, + .dump_size = etnaviv_iommuv2_dump_size, + .dump = etnaviv_iommuv2_dump, +}; + +struct etnaviv_iommu_domain * +etnaviv_iommuv2_domain_alloc(struct etnaviv_gpu *gpu) { struct etnaviv_iommuv2_domain *etnaviv_domain; + struct etnaviv_iommu_domain *domain; int ret; etnaviv_domain = vzalloc(sizeof(*etnaviv_domain)); if (!etnaviv_domain) return NULL; - etnaviv_domain->dev = gpu->dev; + domain = &etnaviv_domain->base; - etnaviv_domain->domain.type = __IOMMU_DOMAIN_PAGING; - etnaviv_domain->domain.ops = &etnaviv_iommu_ops.ops; - etnaviv_domain->domain.pgsize_bitmap = SZ_4K; - etnaviv_domain->domain.geometry.aperture_start = 0; - etnaviv_domain->domain.geometry.aperture_end = ~0UL & ~(SZ_4K - 1); + domain->dev = gpu->dev; + domain->base = 0; + domain->size = (u64)SZ_1G * 4; + domain->ops = &etnaviv_iommuv2_ops; ret = etnaviv_iommuv2_init(etnaviv_domain); if (ret) goto out_free; - return &etnaviv_domain->domain; + return &etnaviv_domain->base; out_free: vfree(etnaviv_domain); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c index f103e787de94..35074b944778 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.c @@ -22,17 +22,64 @@ #include "etnaviv_iommu.h" #include "etnaviv_mmu.h" -static int etnaviv_fault_handler(struct iommu_domain *iommu, struct device *dev, - unsigned long iova, int flags, void *arg) +static void etnaviv_domain_unmap(struct etnaviv_iommu_domain *domain, + unsigned long iova, size_t size) { - DBG("*** fault: iova=%08lx, flags=%d", iova, flags); - return 0; + size_t unmapped_page, unmapped = 0; + size_t pgsize = SZ_4K; + + if (!IS_ALIGNED(iova | size, pgsize)) { + pr_err("unaligned: iova 0x%lx size 0x%zx min_pagesz 0x%x\n", + iova, size, pgsize); + return; + } + + while (unmapped < size) { + unmapped_page = domain->ops->unmap(domain, iova, pgsize); + if (!unmapped_page) + break; + + iova += unmapped_page; + unmapped += unmapped_page; + } } -int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova, - struct sg_table *sgt, unsigned len, int prot) +static int etnaviv_domain_map(struct etnaviv_iommu_domain *domain, + unsigned long iova, phys_addr_t paddr, + size_t size, int prot) { - struct iommu_domain *domain = iommu->domain; + unsigned long orig_iova = iova; + size_t pgsize = SZ_4K; + size_t orig_size = size; + int ret = 0; + + if (!IS_ALIGNED(iova | paddr | size, pgsize)) { + pr_err("unaligned: iova 0x%lx pa %pa size 0x%zx min_pagesz 0x%x\n", + iova, &paddr, size, pgsize); + return -EINVAL; + } + + while (size) { + ret = domain->ops->map(domain, iova, paddr, pgsize, prot); + if (ret) + break; + + iova += pgsize; + paddr += pgsize; + size -= pgsize; + } + + /* unroll mapping in case something went wrong */ + if (ret) + etnaviv_domain_unmap(domain, orig_iova, orig_size - size); + + return ret; +} + +static int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova, + struct sg_table *sgt, unsigned len, int prot) +{ + struct etnaviv_iommu_domain *domain = iommu->domain; struct scatterlist *sg; unsigned int da = iova; unsigned int i, j; @@ -47,7 +94,7 @@ int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova, VERB("map[%d]: %08x %08x(%zx)", i, iova, pa, bytes); - ret = iommu_map(domain, da, pa, bytes, prot); + ret = etnaviv_domain_map(domain, da, pa, bytes, prot); if (ret) goto fail; @@ -62,27 +109,24 @@ fail: for_each_sg(sgt->sgl, sg, i, j) { size_t bytes = sg_dma_len(sg) + sg->offset; - iommu_unmap(domain, da, bytes); + etnaviv_domain_unmap(domain, da, bytes); da += bytes; } return ret; } -int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova, - struct sg_table *sgt, unsigned len) +static void etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova, + struct sg_table *sgt, unsigned len) { - struct iommu_domain *domain = iommu->domain; + struct etnaviv_iommu_domain *domain = iommu->domain; struct scatterlist *sg; unsigned int da = iova; int i; for_each_sg(sgt->sgl, sg, sgt->nents, i) { size_t bytes = sg_dma_len(sg) + sg->offset; - size_t unmapped; - unmapped = iommu_unmap(domain, da, bytes); - if (unmapped < bytes) - return unmapped; + etnaviv_domain_unmap(domain, da, bytes); VERB("unmap[%d]: %08x(%zx)", i, iova, bytes); @@ -90,8 +134,6 @@ int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova, da += bytes; } - - return 0; } static void etnaviv_iommu_remove_mapping(struct etnaviv_iommu *mmu, @@ -237,7 +279,7 @@ int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu, mmu->last_iova = node->start + etnaviv_obj->base.size; mapping->iova = node->start; ret = etnaviv_iommu_map(mmu, node->start, sgt, etnaviv_obj->base.size, - IOMMU_READ | IOMMU_WRITE); + ETNAVIV_PROT_READ | ETNAVIV_PROT_WRITE); if (ret < 0) { drm_mm_remove_node(node); @@ -271,7 +313,7 @@ void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu, void etnaviv_iommu_destroy(struct etnaviv_iommu *mmu) { drm_mm_takedown(&mmu->mm); - iommu_domain_free(mmu->domain); + mmu->domain->ops->free(mmu->domain); kfree(mmu); } @@ -303,11 +345,7 @@ struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu) mutex_init(&mmu->lock); INIT_LIST_HEAD(&mmu->mappings); - drm_mm_init(&mmu->mm, mmu->domain->geometry.aperture_start, - mmu->domain->geometry.aperture_end - - mmu->domain->geometry.aperture_start + 1); - - iommu_set_fault_handler(mmu->domain, etnaviv_fault_handler, gpu->dev); + drm_mm_init(&mmu->mm, mmu->domain->base, mmu->domain->size); return mmu; } @@ -338,8 +376,8 @@ int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr, mutex_unlock(&mmu->lock); return ret; } - ret = iommu_map(mmu->domain, vram_node->start, paddr, size, - IOMMU_READ); + ret = etnaviv_domain_map(mmu->domain, vram_node->start, paddr, + size, ETNAVIV_PROT_READ); if (ret < 0) { drm_mm_remove_node(vram_node); mutex_unlock(&mmu->lock); @@ -362,25 +400,17 @@ void etnaviv_iommu_put_suballoc_va(struct etnaviv_gpu *gpu, if (mmu->version == ETNAVIV_IOMMU_V2) { mutex_lock(&mmu->lock); - iommu_unmap(mmu->domain,iova, size); + etnaviv_domain_unmap(mmu->domain, iova, size); drm_mm_remove_node(vram_node); mutex_unlock(&mmu->lock); } } size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu) { - struct etnaviv_iommu_ops *ops; - - ops = container_of(iommu->domain->ops, struct etnaviv_iommu_ops, ops); - - return ops->dump_size(iommu->domain); + return iommu->domain->ops->dump_size(iommu->domain); } void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf) { - struct etnaviv_iommu_ops *ops; - - ops = container_of(iommu->domain->ops, struct etnaviv_iommu_ops, ops); - - ops->dump(iommu->domain, buf); + iommu->domain->ops->dump(iommu->domain, buf); } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h index 54be289e5981..ab603f5166b1 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_mmu.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_mmu.h @@ -17,7 +17,8 @@ #ifndef __ETNAVIV_MMU_H__ #define __ETNAVIV_MMU_H__ -#include <linux/iommu.h> +#define ETNAVIV_PROT_READ (1 << 0) +#define ETNAVIV_PROT_WRITE (1 << 1) enum etnaviv_iommu_version { ETNAVIV_IOMMU_V1 = 0, @@ -26,16 +27,31 @@ enum etnaviv_iommu_version { struct etnaviv_gpu; struct etnaviv_vram_mapping; +struct etnaviv_iommu_domain; -struct etnaviv_iommu_ops { - struct iommu_ops ops; - size_t (*dump_size)(struct iommu_domain *); - void (*dump)(struct iommu_domain *, void *); +struct etnaviv_iommu_domain_ops { + void (*free)(struct etnaviv_iommu_domain *); + int (*map)(struct etnaviv_iommu_domain *domain, unsigned long iova, + phys_addr_t paddr, size_t size, int prot); + size_t (*unmap)(struct etnaviv_iommu_domain *domain, unsigned long iova, + size_t size); + size_t (*dump_size)(struct etnaviv_iommu_domain *); + void (*dump)(struct etnaviv_iommu_domain *, void *); +}; + +struct etnaviv_iommu_domain { + struct device *dev; + void *bad_page_cpu; + dma_addr_t bad_page_dma; + u64 base; + u64 size; + + const struct etnaviv_iommu_domain_ops *ops; }; struct etnaviv_iommu { struct etnaviv_gpu *gpu; - struct iommu_domain *domain; + struct etnaviv_iommu_domain *domain; enum etnaviv_iommu_version version; @@ -49,18 +65,11 @@ struct etnaviv_iommu { struct etnaviv_gem_object; -int etnaviv_iommu_attach(struct etnaviv_iommu *iommu, const char **names, - int cnt); -int etnaviv_iommu_map(struct etnaviv_iommu *iommu, u32 iova, - struct sg_table *sgt, unsigned len, int prot); -int etnaviv_iommu_unmap(struct etnaviv_iommu *iommu, u32 iova, - struct sg_table *sgt, unsigned len); int etnaviv_iommu_map_gem(struct etnaviv_iommu *mmu, struct etnaviv_gem_object *etnaviv_obj, u32 memory_base, struct etnaviv_vram_mapping *mapping); void etnaviv_iommu_unmap_gem(struct etnaviv_iommu *mmu, struct etnaviv_vram_mapping *mapping); -void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu); int etnaviv_iommu_get_suballoc_va(struct etnaviv_gpu *gpu, dma_addr_t paddr, struct drm_mm_node *vram_node, size_t size, @@ -73,6 +82,7 @@ size_t etnaviv_iommu_dump_size(struct etnaviv_iommu *iommu); void etnaviv_iommu_dump(struct etnaviv_iommu *iommu, void *buf); struct etnaviv_iommu *etnaviv_iommu_new(struct etnaviv_gpu *gpu); +void etnaviv_iommu_destroy(struct etnaviv_iommu *iommu); void etnaviv_iommu_restore(struct etnaviv_gpu *gpu); #endif /* __ETNAVIV_MMU_H__ */ diff --git a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c new file mode 100644 index 000000000000..768f5aafdd18 --- /dev/null +++ b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.c @@ -0,0 +1,495 @@ +/* + * Copyright (C) 2017 Etnaviv Project + * Copyright (C) 2017 Zodiac Inflight Innovations + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "etnaviv_gpu.h" +#include "etnaviv_perfmon.h" +#include "state_hi.xml.h" + +struct etnaviv_pm_domain; + +struct etnaviv_pm_signal { + char name[64]; + u32 data; + + u32 (*sample)(struct etnaviv_gpu *gpu, + const struct etnaviv_pm_domain *domain, + const struct etnaviv_pm_signal *signal); +}; + +struct etnaviv_pm_domain { + char name[64]; + + /* profile register */ + u32 profile_read; + u32 profile_config; + + u8 nr_signals; + const struct etnaviv_pm_signal *signal; +}; + +struct etnaviv_pm_domain_meta { + const struct etnaviv_pm_domain *domains; + u32 nr_domains; +}; + +static u32 simple_reg_read(struct etnaviv_gpu *gpu, + const struct etnaviv_pm_domain *domain, + const struct etnaviv_pm_signal *signal) +{ + return gpu_read(gpu, signal->data); +} + +static u32 perf_reg_read(struct etnaviv_gpu *gpu, + const struct etnaviv_pm_domain *domain, + const struct etnaviv_pm_signal *signal) +{ + gpu_write(gpu, domain->profile_config, signal->data); + + return gpu_read(gpu, domain->profile_read); +} + +static u32 pipe_reg_read(struct etnaviv_gpu *gpu, + const struct etnaviv_pm_domain *domain, + const struct etnaviv_pm_signal *signal) +{ + u32 clock = gpu_read(gpu, VIVS_HI_CLOCK_CONTROL); + u32 value = 0; + unsigned i; + + for (i = 0; i < gpu->identity.pixel_pipes; i++) { + clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK); + clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(i); + gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock); + gpu_write(gpu, domain->profile_config, signal->data); + value += gpu_read(gpu, domain->profile_read); + } + + /* switch back to pixel pipe 0 to prevent GPU hang */ + clock &= ~(VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE__MASK); + clock |= VIVS_HI_CLOCK_CONTROL_DEBUG_PIXEL_PIPE(0); + gpu_write(gpu, VIVS_HI_CLOCK_CONTROL, clock); + + return value; +} + +static const struct etnaviv_pm_domain doms_3d[] = { + { + .name = "HI", + .profile_read = VIVS_MC_PROFILE_HI_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG2, + .nr_signals = 5, + .signal = (const struct etnaviv_pm_signal[]) { + { + "TOTAL_CYCLES", + VIVS_HI_PROFILE_TOTAL_CYCLES, + &simple_reg_read + }, + { + "IDLE_CYCLES", + VIVS_HI_PROFILE_IDLE_CYCLES, + &simple_reg_read + }, + { + "AXI_CYCLES_READ_REQUEST_STALLED", + VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_READ_REQUEST_STALLED, + &perf_reg_read + }, + { + "AXI_CYCLES_WRITE_REQUEST_STALLED", + VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_REQUEST_STALLED, + &perf_reg_read + }, + { + "AXI_CYCLES_WRITE_DATA_STALLED", + VIVS_MC_PROFILE_CONFIG2_HI_AXI_CYCLES_WRITE_DATA_STALLED, + &perf_reg_read + } + } + }, + { + .name = "PE", + .profile_read = VIVS_MC_PROFILE_PE_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG0, + .nr_signals = 5, + .signal = (const struct etnaviv_pm_signal[]) { + { + "PIXEL_COUNT_KILLED_BY_COLOR_PIPE", + VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_COLOR_PIPE, + &pipe_reg_read + }, + { + "PIXEL_COUNT_KILLED_BY_DEPTH_PIPE", + VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_KILLED_BY_DEPTH_PIPE, + &pipe_reg_read + }, + { + "PIXEL_COUNT_DRAWN_BY_COLOR_PIPE", + VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_COLOR_PIPE, + &pipe_reg_read + }, + { + "PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE", + VIVS_MC_PROFILE_CONFIG0_PE_PIXEL_COUNT_DRAWN_BY_DEPTH_PIPE, + &pipe_reg_read + } + } + }, + { + .name = "SH", + .profile_read = VIVS_MC_PROFILE_SH_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG0, + .nr_signals = 9, + .signal = (const struct etnaviv_pm_signal[]) { + { + "SHADER_CYCLES", + VIVS_MC_PROFILE_CONFIG0_SH_SHADER_CYCLES, + &perf_reg_read + }, + { + "PS_INST_COUNTER", + VIVS_MC_PROFILE_CONFIG0_SH_PS_INST_COUNTER, + &perf_reg_read + }, + { + "RENDERED_PIXEL_COUNTER", + VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_PIXEL_COUNTER, + &perf_reg_read + }, + { + "VS_INST_COUNTER", + VIVS_MC_PROFILE_CONFIG0_SH_VS_INST_COUNTER, + &pipe_reg_read + }, + { + "RENDERED_VERTICE_COUNTER", + VIVS_MC_PROFILE_CONFIG0_SH_RENDERED_VERTICE_COUNTER, + &pipe_reg_read + }, + { + "VTX_BRANCH_INST_COUNTER", + VIVS_MC_PROFILE_CONFIG0_SH_VTX_BRANCH_INST_COUNTER, + &pipe_reg_read + }, + { + "VTX_TEXLD_INST_COUNTER", + VIVS_MC_PROFILE_CONFIG0_SH_VTX_TEXLD_INST_COUNTER, + &pipe_reg_read + }, + { + "PXL_BRANCH_INST_COUNTER", + VIVS_MC_PROFILE_CONFIG0_SH_PXL_BRANCH_INST_COUNTER, + &pipe_reg_read + }, + { + "PXL_TEXLD_INST_COUNTER", + VIVS_MC_PROFILE_CONFIG0_SH_PXL_TEXLD_INST_COUNTER, + &pipe_reg_read + } + } + }, + { + .name = "PA", + .profile_read = VIVS_MC_PROFILE_PA_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG1, + .nr_signals = 6, + .signal = (const struct etnaviv_pm_signal[]) { + { + "INPUT_VTX_COUNTER", + VIVS_MC_PROFILE_CONFIG1_PA_INPUT_VTX_COUNTER, + &perf_reg_read + }, + { + "INPUT_PRIM_COUNTER", + VIVS_MC_PROFILE_CONFIG1_PA_INPUT_PRIM_COUNTER, + &perf_reg_read + }, + { + "OUTPUT_PRIM_COUNTER", + VIVS_MC_PROFILE_CONFIG1_PA_OUTPUT_PRIM_COUNTER, + &perf_reg_read + }, + { + "DEPTH_CLIPPED_COUNTER", + VIVS_MC_PROFILE_CONFIG1_PA_DEPTH_CLIPPED_COUNTER, + &pipe_reg_read + }, + { + "TRIVIAL_REJECTED_COUNTER", + VIVS_MC_PROFILE_CONFIG1_PA_TRIVIAL_REJECTED_COUNTER, + &pipe_reg_read + }, + { + "CULLED_COUNTER", + VIVS_MC_PROFILE_CONFIG1_PA_CULLED_COUNTER, + &pipe_reg_read + } + } + }, + { + .name = "SE", + .profile_read = VIVS_MC_PROFILE_SE_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG1, + .nr_signals = 2, + .signal = (const struct etnaviv_pm_signal[]) { + { + "CULLED_TRIANGLE_COUNT", + VIVS_MC_PROFILE_CONFIG1_SE_CULLED_TRIANGLE_COUNT, + &perf_reg_read + }, + { + "CULLED_LINES_COUNT", + VIVS_MC_PROFILE_CONFIG1_SE_CULLED_LINES_COUNT, + &perf_reg_read + } + } + }, + { + .name = "RA", + .profile_read = VIVS_MC_PROFILE_RA_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG1, + .nr_signals = 7, + .signal = (const struct etnaviv_pm_signal[]) { + { + "VALID_PIXEL_COUNT", + VIVS_MC_PROFILE_CONFIG1_RA_VALID_PIXEL_COUNT, + &perf_reg_read + }, + { + "TOTAL_QUAD_COUNT", + VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_QUAD_COUNT, + &perf_reg_read + }, + { + "VALID_QUAD_COUNT_AFTER_EARLY_Z", + VIVS_MC_PROFILE_CONFIG1_RA_VALID_QUAD_COUNT_AFTER_EARLY_Z, + &perf_reg_read + }, + { + "TOTAL_PRIMITIVE_COUNT", + VIVS_MC_PROFILE_CONFIG1_RA_TOTAL_PRIMITIVE_COUNT, + &perf_reg_read + }, + { + "PIPE_CACHE_MISS_COUNTER", + VIVS_MC_PROFILE_CONFIG1_RA_PIPE_CACHE_MISS_COUNTER, + &perf_reg_read + }, + { + "PREFETCH_CACHE_MISS_COUNTER", + VIVS_MC_PROFILE_CONFIG1_RA_PREFETCH_CACHE_MISS_COUNTER, + &perf_reg_read + }, + { + "CULLED_QUAD_COUNT", + VIVS_MC_PROFILE_CONFIG1_RA_CULLED_QUAD_COUNT, + &perf_reg_read + } + } + }, + { + .name = "TX", + .profile_read = VIVS_MC_PROFILE_TX_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG1, + .nr_signals = 9, + .signal = (const struct etnaviv_pm_signal[]) { + { + "TOTAL_BILINEAR_REQUESTS", + VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_BILINEAR_REQUESTS, + &perf_reg_read + }, + { + "TOTAL_TRILINEAR_REQUESTS", + VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TRILINEAR_REQUESTS, + &perf_reg_read + }, + { + "TOTAL_DISCARDED_TEXTURE_REQUESTS", + VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_DISCARDED_TEXTURE_REQUESTS, + &perf_reg_read + }, + { + "TOTAL_TEXTURE_REQUESTS", + VIVS_MC_PROFILE_CONFIG1_TX_TOTAL_TEXTURE_REQUESTS, + &perf_reg_read + }, + { + "MEM_READ_COUNT", + VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_COUNT, + &perf_reg_read + }, + { + "MEM_READ_IN_8B_COUNT", + VIVS_MC_PROFILE_CONFIG1_TX_MEM_READ_IN_8B_COUNT, + &perf_reg_read + }, + { + "CACHE_MISS_COUNT", + VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_COUNT, + &perf_reg_read + }, + { + "CACHE_HIT_TEXEL_COUNT", + VIVS_MC_PROFILE_CONFIG1_TX_CACHE_HIT_TEXEL_COUNT, + &perf_reg_read + }, + { + "CACHE_MISS_TEXEL_COUNT", + VIVS_MC_PROFILE_CONFIG1_TX_CACHE_MISS_TEXEL_COUNT, + &perf_reg_read + } + } + }, + { + .name = "MC", + .profile_read = VIVS_MC_PROFILE_MC_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG2, + .nr_signals = 3, + .signal = (const struct etnaviv_pm_signal[]) { + { + "TOTAL_READ_REQ_8B_FROM_PIPELINE", + VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_PIPELINE, + &perf_reg_read + }, + { + "TOTAL_READ_REQ_8B_FROM_IP", + VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_READ_REQ_8B_FROM_IP, + &perf_reg_read + }, + { + "TOTAL_WRITE_REQ_8B_FROM_PIPELINE", + VIVS_MC_PROFILE_CONFIG2_MC_TOTAL_WRITE_REQ_8B_FROM_PIPELINE, + &perf_reg_read + } + } + } +}; + +static const struct etnaviv_pm_domain doms_2d[] = { + { + .name = "PE", + .profile_read = VIVS_MC_PROFILE_PE_READ, + .profile_config = VIVS_MC_PROFILE_CONFIG0, + .nr_signals = 1, + .signal = (const struct etnaviv_pm_signal[]) { + { + "PIXELS_RENDERED_2D", + VIVS_MC_PROFILE_CONFIG0_PE_PIXELS_RENDERED_2D, + &pipe_reg_read + } + } + } +}; + +static const struct etnaviv_pm_domain doms_vg[] = { +}; + +static const struct etnaviv_pm_domain_meta doms_meta[] = { + { + .nr_domains = ARRAY_SIZE(doms_3d), + .domains = &doms_3d[0] + }, + { + .nr_domains = ARRAY_SIZE(doms_2d), + .domains = &doms_2d[0] + }, + { + .nr_domains = ARRAY_SIZE(doms_vg), + .domains = &doms_vg[0] + } +}; + +int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu, + struct drm_etnaviv_pm_domain *domain) +{ + const struct etnaviv_pm_domain_meta *meta = &doms_meta[domain->pipe]; + const struct etnaviv_pm_domain *dom; + + if (domain->iter >= meta->nr_domains) + return -EINVAL; + + dom = meta->domains + domain->iter; + + domain->id = domain->iter; + domain->nr_signals = dom->nr_signals; + strncpy(domain->name, dom->name, sizeof(domain->name)); + + domain->iter++; + if (domain->iter == meta->nr_domains) + domain->iter = 0xff; + + return 0; +} + +int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu, + struct drm_etnaviv_pm_signal *signal) +{ + const struct etnaviv_pm_domain_meta *meta = &doms_meta[signal->pipe]; + const struct etnaviv_pm_domain *dom; + const struct etnaviv_pm_signal *sig; + + if (signal->domain >= meta->nr_domains) + return -EINVAL; + + dom = meta->domains + signal->domain; + + if (signal->iter > dom->nr_signals) + return -EINVAL; + + sig = &dom->signal[signal->iter]; + + signal->id = signal->iter; + strncpy(signal->name, sig->name, sizeof(signal->name)); + + signal->iter++; + if (signal->iter == dom->nr_signals) + signal->iter = 0xffff; + + return 0; +} + +int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r, + u32 exec_state) +{ + const struct etnaviv_pm_domain_meta *meta = &doms_meta[exec_state]; + const struct etnaviv_pm_domain *dom; + + if (r->domain >= meta->nr_domains) + return -EINVAL; + + dom = meta->domains + r->domain; + + if (r->signal > dom->nr_signals) + return -EINVAL; + + return 0; +} + +void etnaviv_perfmon_process(struct etnaviv_gpu *gpu, + const struct etnaviv_perfmon_request *pmr) +{ + const struct etnaviv_pm_domain_meta *meta = &doms_meta[gpu->exec_state]; + const struct etnaviv_pm_domain *dom; + const struct etnaviv_pm_signal *sig; + u32 *bo = pmr->bo_vma; + u32 val; + + dom = meta->domains + pmr->domain; + sig = &dom->signal[pmr->signal]; + val = sig->sample(gpu, dom, sig); + + *(bo + pmr->offset) = val; +} diff --git a/drivers/gpu/drm/etnaviv/etnaviv_perfmon.h b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.h new file mode 100644 index 000000000000..35dce194cb00 --- /dev/null +++ b/drivers/gpu/drm/etnaviv/etnaviv_perfmon.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 Etnaviv Project + * Copyright (C) 2017 Zodiac Inflight Innovations + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __ETNAVIV_PERFMON_H__ +#define __ETNAVIV_PERFMON_H__ + +struct etnaviv_gpu; +struct drm_etnaviv_pm_domain; +struct drm_etnaviv_pm_signal; + +struct etnaviv_perfmon_request +{ + u32 flags; + u8 domain; + u8 signal; + u32 sequence; + + /* bo to store a value */ + u32 *bo_vma; + u32 offset; +}; + +int etnaviv_pm_query_dom(struct etnaviv_gpu *gpu, + struct drm_etnaviv_pm_domain *domain); + +int etnaviv_pm_query_sig(struct etnaviv_gpu *gpu, + struct drm_etnaviv_pm_signal *signal); + +int etnaviv_pm_req_validate(const struct drm_etnaviv_gem_submit_pmr *r, + u32 exec_state); + +void etnaviv_perfmon_process(struct etnaviv_gpu *gpu, + const struct etnaviv_perfmon_request *pmr); + +#endif /* __ETNAVIV_PERFMON_H__ */ diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 305dc3d4ff77..5a7c9d8abd6b 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig @@ -3,6 +3,7 @@ config DRM_EXYNOS depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM) select DRM_KMS_HELPER select VIDEOMODE_HELPERS + select SND_SOC_HDMI_CODEC if SND_SOC help Choose this option if you have a Samsung SoC EXYNOS chipset. If M is selected the module will be called exynosdrm. diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index 6ce0821590df..dc01342e759a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -95,8 +95,23 @@ static enum drm_mode_status exynos_crtc_mode_valid(struct drm_crtc *crtc, return MODE_OK; } +static bool exynos_crtc_mode_fixup(struct drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); + + if (exynos_crtc->ops->mode_fixup) + return exynos_crtc->ops->mode_fixup(exynos_crtc, mode, + adjusted_mode); + + return true; +} + + static const struct drm_crtc_helper_funcs exynos_crtc_helper_funcs = { .mode_valid = exynos_crtc_mode_valid, + .mode_fixup = exynos_crtc_mode_fixup, .atomic_check = exynos_crtc_atomic_check, .atomic_begin = exynos_crtc_atomic_begin, .atomic_flush = exynos_crtc_atomic_flush, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index e651a58c18cf..82b72425a42f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -168,11 +168,13 @@ static struct drm_driver exynos_drm_driver = { static int exynos_drm_suspend(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); - struct exynos_drm_private *private = drm_dev->dev_private; + struct exynos_drm_private *private; if (pm_runtime_suspended(dev) || !drm_dev) return 0; + private = drm_dev->dev_private; + drm_kms_helper_poll_disable(drm_dev); exynos_drm_fbdev_suspend(drm_dev); private->suspend_state = drm_atomic_helper_suspend(drm_dev); @@ -188,11 +190,12 @@ static int exynos_drm_suspend(struct device *dev) static int exynos_drm_resume(struct device *dev) { struct drm_device *drm_dev = dev_get_drvdata(dev); - struct exynos_drm_private *private = drm_dev->dev_private; + struct exynos_drm_private *private; if (pm_runtime_suspended(dev) || !drm_dev) return 0; + private = drm_dev->dev_private; drm_atomic_helper_resume(drm_dev, private->suspend_state); exynos_drm_fbdev_resume(drm_dev); drm_kms_helper_poll_enable(drm_dev); @@ -427,6 +430,7 @@ static void exynos_drm_unbind(struct device *dev) kfree(drm->dev_private); drm->dev_private = NULL; + dev_set_drvdata(dev, NULL); drm_dev_unref(drm); } diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index f8bae4cb4823..c6847fa708fa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -136,6 +136,9 @@ struct exynos_drm_crtc_ops { u32 (*get_vblank_counter)(struct exynos_drm_crtc *crtc); enum drm_mode_status (*mode_valid)(struct exynos_drm_crtc *crtc, const struct drm_display_mode *mode); + bool (*mode_fixup)(struct exynos_drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode); int (*atomic_check)(struct exynos_drm_crtc *crtc, struct drm_crtc_state *state); void (*atomic_begin)(struct exynos_drm_crtc *crtc); diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 0109ff40b1db..82d1b7e2febe 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c @@ -40,7 +40,7 @@ #include <linux/component.h> #include <linux/mfd/syscon.h> #include <linux/regmap.h> - +#include <sound/hdmi-codec.h> #include <drm/exynos_drm.h> #include <media/cec-notifier.h> @@ -111,15 +111,20 @@ struct hdmi_driver_data { struct string_array_spec clk_muxes; }; +struct hdmi_audio { + struct platform_device *pdev; + struct hdmi_audio_infoframe infoframe; + struct hdmi_codec_params params; + bool mute; +}; + struct hdmi_context { struct drm_encoder encoder; struct device *dev; struct drm_device *drm_dev; struct drm_connector connector; - bool powered; bool dvi_mode; struct delayed_work hotplug_work; - struct drm_display_mode current_mode; struct cec_notifier *notifier; const struct hdmi_driver_data *drv_data; @@ -137,6 +142,11 @@ struct hdmi_context { struct regulator *reg_hdmi_en; struct exynos_drm_clk phy_clk; struct drm_bridge *bridge; + + /* mutex protecting subsequent fields below */ + struct mutex mutex; + struct hdmi_audio audio; + bool powered; }; static inline struct hdmi_context *encoder_to_hdmi(struct drm_encoder *e) @@ -298,6 +308,15 @@ static const struct hdmiphy_config hdmiphy_v14_configs[] = { }, }, { + .pixel_clock = 85500000, + .conf = { + 0x01, 0xd1, 0x24, 0x11, 0x40, 0x40, 0xd0, 0x08, + 0x84, 0xa0, 0xd6, 0xd8, 0x45, 0xa0, 0xac, 0x80, + 0x08, 0x80, 0x11, 0x04, 0x02, 0x22, 0x44, 0x86, + 0x54, 0x90, 0x24, 0x01, 0x00, 0x00, 0x01, 0x80, + }, + }, + { .pixel_clock = 106500000, .conf = { 0x01, 0xd1, 0x2c, 0x12, 0x40, 0x0c, 0x09, 0x08, @@ -768,8 +787,25 @@ static int hdmi_clk_set_parents(struct hdmi_context *hdata, bool to_phy) return ret; } +static int hdmi_audio_infoframe_apply(struct hdmi_context *hdata) +{ + struct hdmi_audio_infoframe *infoframe = &hdata->audio.infoframe; + u8 buf[HDMI_INFOFRAME_SIZE(AUDIO)]; + int len; + + len = hdmi_audio_infoframe_pack(infoframe, buf, sizeof(buf)); + if (len < 0) + return len; + + hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC); + hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, len); + + return 0; +} + static void hdmi_reg_infoframes(struct hdmi_context *hdata) { + struct drm_display_mode *m = &hdata->encoder.crtc->state->mode; union hdmi_infoframe frm; u8 buf[25]; int ret; @@ -783,8 +819,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata) return; } - ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi, - &hdata->current_mode, false); + ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi, m, false); if (!ret) ret = hdmi_avi_infoframe_pack(&frm.avi, buf, sizeof(buf)); if (ret > 0) { @@ -794,8 +829,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata) DRM_INFO("%s: invalid AVI infoframe (%d)\n", __func__, ret); } - ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi, - &hdata->current_mode); + ret = drm_hdmi_vendor_infoframe_from_display_mode(&frm.vendor.hdmi, m); if (!ret) ret = hdmi_vendor_infoframe_pack(&frm.vendor.hdmi, buf, sizeof(buf)); @@ -805,15 +839,7 @@ static void hdmi_reg_infoframes(struct hdmi_context *hdata) hdmi_reg_write_buf(hdata, HDMI_VSI_DATA(0), buf + 3, ret - 3); } - ret = hdmi_audio_infoframe_init(&frm.audio); - if (!ret) { - frm.audio.channels = 2; - ret = hdmi_audio_infoframe_pack(&frm.audio, buf, sizeof(buf)); - } - if (ret > 0) { - hdmi_reg_writeb(hdata, HDMI_AUI_CON, HDMI_AUI_CON_EVERY_VSYNC); - hdmi_reg_write_buf(hdata, HDMI_AUI_HEADER0, buf, ret); - } + hdmi_audio_infoframe_apply(hdata); } static enum drm_connector_status hdmi_detect(struct drm_connector *connector, @@ -1003,23 +1029,18 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u32 freq) hdmi_reg_writeb(hdata, HDMI_ACR_CON, 4); } -static void hdmi_audio_init(struct hdmi_context *hdata) +static void hdmi_audio_config(struct hdmi_context *hdata) { - u32 sample_rate, bits_per_sample; - u32 data_num, bit_ch, sample_frq; - u32 val; - - sample_rate = 44100; - bits_per_sample = 16; + u32 bit_ch = 1; + u32 data_num, val; + int i; - switch (bits_per_sample) { + switch (hdata->audio.params.sample_width) { case 20: data_num = 2; - bit_ch = 1; break; case 24: data_num = 3; - bit_ch = 1; break; default: data_num = 1; @@ -1027,7 +1048,7 @@ static void hdmi_audio_init(struct hdmi_context *hdata) break; } - hdmi_reg_acr(hdata, sample_rate); + hdmi_reg_acr(hdata, hdata->audio.params.sample_rate); hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CON, HDMI_I2S_IN_DISABLE | HDMI_I2S_AUD_I2S | HDMI_I2S_CUV_I2S_ENABLE @@ -1037,12 +1058,6 @@ static void hdmi_audio_init(struct hdmi_context *hdata) | HDMI_I2S_CH1_EN | HDMI_I2S_CH2_EN); hdmi_reg_writeb(hdata, HDMI_I2S_MUX_CUV, HDMI_I2S_CUV_RL_EN); - - sample_frq = (sample_rate == 44100) ? 0 : - (sample_rate == 48000) ? 2 : - (sample_rate == 32000) ? 3 : - (sample_rate == 96000) ? 0xa : 0x0; - hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_DIS); hdmi_reg_writeb(hdata, HDMI_I2S_CLK_CON, HDMI_I2S_CLK_EN); @@ -1066,39 +1081,33 @@ static void hdmi_audio_init(struct hdmi_context *hdata) | HDMI_I2S_SET_SDATA_BIT(data_num) | HDMI_I2S_BASIC_FORMAT); - /* Configure register related to CUV information */ - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_0, HDMI_I2S_CH_STATUS_MODE_0 - | HDMI_I2S_2AUD_CH_WITHOUT_PREEMPH - | HDMI_I2S_COPYRIGHT - | HDMI_I2S_LINEAR_PCM - | HDMI_I2S_CONSUMER_FORMAT); - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_1, HDMI_I2S_CD_PLAYER); - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_2, HDMI_I2S_SET_SOURCE_NUM(0)); - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_3, HDMI_I2S_CLK_ACCUR_LEVEL_2 - | HDMI_I2S_SET_SMP_FREQ(sample_frq)); - hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_4, - HDMI_I2S_ORG_SMP_FREQ_44_1 - | HDMI_I2S_WORD_LEN_MAX24_24BITS - | HDMI_I2S_WORD_LEN_MAX_24BITS); + /* Configuration of the audio channel status registers */ + for (i = 0; i < HDMI_I2S_CH_ST_MAXNUM; i++) + hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST(i), + hdata->audio.params.iec.status[i]); hdmi_reg_writeb(hdata, HDMI_I2S_CH_ST_CON, HDMI_I2S_CH_STATUS_RELOAD); } -static void hdmi_audio_control(struct hdmi_context *hdata, bool onoff) +static void hdmi_audio_control(struct hdmi_context *hdata) { + bool enable = !hdata->audio.mute; + if (hdata->dvi_mode) return; - hdmi_reg_writeb(hdata, HDMI_AUI_CON, onoff ? 2 : 0); - hdmi_reg_writemask(hdata, HDMI_CON_0, onoff ? + hdmi_reg_writeb(hdata, HDMI_AUI_CON, enable ? + HDMI_AVI_CON_EVERY_VSYNC : HDMI_AUI_CON_NO_TRAN); + hdmi_reg_writemask(hdata, HDMI_CON_0, enable ? HDMI_ASP_EN : HDMI_ASP_DIS, HDMI_ASP_MASK); } static void hdmi_start(struct hdmi_context *hdata, bool start) { + struct drm_display_mode *m = &hdata->encoder.crtc->state->mode; u32 val = start ? HDMI_TG_EN : 0; - if (hdata->current_mode.flags & DRM_MODE_FLAG_INTERLACE) + if (m->flags & DRM_MODE_FLAG_INTERLACE) val |= HDMI_FIELD_EN; hdmi_reg_writemask(hdata, HDMI_CON_0, val, HDMI_EN); @@ -1168,7 +1177,7 @@ static void hdmiphy_wait_for_pll(struct hdmi_context *hdata) static void hdmi_v13_mode_apply(struct hdmi_context *hdata) { - struct drm_display_mode *m = &hdata->current_mode; + struct drm_display_mode *m = &hdata->encoder.crtc->state->mode; unsigned int val; hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay); @@ -1247,7 +1256,19 @@ static void hdmi_v13_mode_apply(struct hdmi_context *hdata) static void hdmi_v14_mode_apply(struct hdmi_context *hdata) { - struct drm_display_mode *m = &hdata->current_mode; + struct drm_display_mode *m = &hdata->encoder.crtc->state->mode; + struct drm_display_mode *am = + &hdata->encoder.crtc->state->adjusted_mode; + int hquirk = 0; + + /* + * In case video mode coming from CRTC differs from requested one HDMI + * sometimes is able to almost properly perform conversion - only + * first line is distorted. + */ + if ((m->vdisplay != am->vdisplay) && + (m->hdisplay == 1280 || m->hdisplay == 1024 || m->hdisplay == 1366)) + hquirk = 258; hdmi_reg_writev(hdata, HDMI_H_BLANK_0, 2, m->htotal - m->hdisplay); hdmi_reg_writev(hdata, HDMI_V_LINE_0, 2, m->vtotal); @@ -1341,8 +1362,9 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata) hdmi_reg_writev(hdata, HDMI_V_SYNC_LINE_AFT_PXL_6_0, 2, 0xffff); hdmi_reg_writev(hdata, HDMI_TG_H_FSZ_L, 2, m->htotal); - hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay); - hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay); + hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, + m->htotal - m->hdisplay - hquirk); + hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay + hquirk); hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal); if (hdata->drv_data == &exynos5433_hdmi_driver_data) hdmi_reg_writeb(hdata, HDMI_TG_DECON_EN, 1); @@ -1380,10 +1402,11 @@ static void hdmiphy_enable_mode_set(struct hdmi_context *hdata, bool enable) static void hdmiphy_conf_apply(struct hdmi_context *hdata) { + struct drm_display_mode *m = &hdata->encoder.crtc->state->mode; int ret; const u8 *phy_conf; - ret = hdmi_find_phy_conf(hdata, hdata->current_mode.clock * 1000); + ret = hdmi_find_phy_conf(hdata, m->clock * 1000); if (ret < 0) { DRM_ERROR("failed to find hdmiphy conf\n"); return; @@ -1406,28 +1429,14 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) hdmiphy_wait_for_pll(hdata); } +/* Should be called with hdata->mutex mutex held */ static void hdmi_conf_apply(struct hdmi_context *hdata) { hdmi_start(hdata, false); hdmi_conf_init(hdata); - hdmi_audio_init(hdata); + hdmi_audio_config(hdata); hdmi_mode_apply(hdata); - hdmi_audio_control(hdata, true); -} - -static void hdmi_mode_set(struct drm_encoder *encoder, - struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - struct hdmi_context *hdata = encoder_to_hdmi(encoder); - struct drm_display_mode *m = adjusted_mode; - - DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%s\n", - m->hdisplay, m->vdisplay, - m->vrefresh, (m->flags & DRM_MODE_FLAG_INTERLACE) ? - "INTERLACED" : "PROGRESSIVE"); - - drm_mode_copy(&hdata->current_mode, m); + hdmi_audio_control(hdata); } static void hdmi_set_refclk(struct hdmi_context *hdata, bool on) @@ -1439,6 +1448,7 @@ static void hdmi_set_refclk(struct hdmi_context *hdata, bool on) SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0); } +/* Should be called with hdata->mutex mutex held. */ static void hdmiphy_enable(struct hdmi_context *hdata) { if (hdata->powered) @@ -1461,6 +1471,7 @@ static void hdmiphy_enable(struct hdmi_context *hdata) hdata->powered = true; } +/* Should be called with hdata->mutex mutex held. */ static void hdmiphy_disable(struct hdmi_context *hdata) { if (!hdata->powered) @@ -1486,33 +1497,42 @@ static void hdmi_enable(struct drm_encoder *encoder) { struct hdmi_context *hdata = encoder_to_hdmi(encoder); + mutex_lock(&hdata->mutex); + hdmiphy_enable(hdata); hdmi_conf_apply(hdata); + + mutex_unlock(&hdata->mutex); } static void hdmi_disable(struct drm_encoder *encoder) { struct hdmi_context *hdata = encoder_to_hdmi(encoder); - if (!hdata->powered) + mutex_lock(&hdata->mutex); + + if (hdata->powered) { + /* + * The SFRs of VP and Mixer are updated by Vertical Sync of + * Timing generator which is a part of HDMI so the sequence + * to disable TV Subsystem should be as following, + * VP -> Mixer -> HDMI + * + * To achieve such sequence HDMI is disabled together with + * HDMI PHY, via pipe clock callback. + */ + mutex_unlock(&hdata->mutex); + cancel_delayed_work(&hdata->hotplug_work); + cec_notifier_set_phys_addr(hdata->notifier, + CEC_PHYS_ADDR_INVALID); return; + } - /* - * The SFRs of VP and Mixer are updated by Vertical Sync of - * Timing generator which is a part of HDMI so the sequence - * to disable TV Subsystem should be as following, - * VP -> Mixer -> HDMI - * - * To achieve such sequence HDMI is disabled together with HDMI PHY, via - * pipe clock callback. - */ - cancel_delayed_work(&hdata->hotplug_work); - cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID); + mutex_unlock(&hdata->mutex); } static const struct drm_encoder_helper_funcs exynos_hdmi_encoder_helper_funcs = { .mode_fixup = hdmi_mode_fixup, - .mode_set = hdmi_mode_set, .enable = hdmi_enable, .disable = hdmi_disable, }; @@ -1521,6 +1541,99 @@ static const struct drm_encoder_funcs exynos_hdmi_encoder_funcs = { .destroy = drm_encoder_cleanup, }; +static void hdmi_audio_shutdown(struct device *dev, void *data) +{ + struct hdmi_context *hdata = dev_get_drvdata(dev); + + mutex_lock(&hdata->mutex); + + hdata->audio.mute = true; + + if (hdata->powered) + hdmi_audio_control(hdata); + + mutex_unlock(&hdata->mutex); +} + +static int hdmi_audio_hw_params(struct device *dev, void *data, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) +{ + struct hdmi_context *hdata = dev_get_drvdata(dev); + + if (daifmt->fmt != HDMI_I2S || daifmt->bit_clk_inv || + daifmt->frame_clk_inv || daifmt->bit_clk_master || + daifmt->frame_clk_master) { + dev_err(dev, "%s: Bad flags %d %d %d %d\n", __func__, + daifmt->bit_clk_inv, daifmt->frame_clk_inv, + daifmt->bit_clk_master, + daifmt->frame_clk_master); + return -EINVAL; + } + + mutex_lock(&hdata->mutex); + + hdata->audio.params = *params; + + if (hdata->powered) { + hdmi_audio_config(hdata); + hdmi_audio_infoframe_apply(hdata); + } + + mutex_unlock(&hdata->mutex); + + return 0; +} + +static int hdmi_audio_digital_mute(struct device *dev, void *data, bool mute) +{ + struct hdmi_context *hdata = dev_get_drvdata(dev); + + mutex_lock(&hdata->mutex); + + hdata->audio.mute = mute; + + if (hdata->powered) + hdmi_audio_control(hdata); + + mutex_unlock(&hdata->mutex); + + return 0; +} + +static int hdmi_audio_get_eld(struct device *dev, void *data, uint8_t *buf, + size_t len) +{ + struct hdmi_context *hdata = dev_get_drvdata(dev); + struct drm_connector *connector = &hdata->connector; + + memcpy(buf, connector->eld, min(sizeof(connector->eld), len)); + + return 0; +} + +static const struct hdmi_codec_ops audio_codec_ops = { + .hw_params = hdmi_audio_hw_params, + .audio_shutdown = hdmi_audio_shutdown, + .digital_mute = hdmi_audio_digital_mute, + .get_eld = hdmi_audio_get_eld, +}; + +static int hdmi_register_audio_device(struct hdmi_context *hdata) +{ + struct hdmi_codec_pdata codec_data = { + .ops = &audio_codec_ops, + .max_i2s_channels = 6, + .i2s = 1, + }; + + hdata->audio.pdev = platform_device_register_data( + hdata->dev, HDMI_CODEC_DRV_NAME, PLATFORM_DEVID_AUTO, + &codec_data, sizeof(codec_data)); + + return PTR_ERR_OR_ZERO(hdata->audio.pdev); +} + static void hdmi_hotplug_work_func(struct work_struct *work) { struct hdmi_context *hdata; @@ -1596,11 +1709,14 @@ static void hdmiphy_clk_enable(struct exynos_drm_clk *clk, bool enable) { struct hdmi_context *hdata = container_of(clk, struct hdmi_context, phy_clk); + mutex_lock(&hdata->mutex); if (enable) hdmiphy_enable(hdata); else hdmiphy_disable(hdata); + + mutex_unlock(&hdata->mutex); } static int hdmi_bridge_init(struct hdmi_context *hdata) @@ -1811,6 +1927,7 @@ out: static int hdmi_probe(struct platform_device *pdev) { + struct hdmi_audio_infoframe *audio_infoframe; struct device *dev = &pdev->dev; struct hdmi_context *hdata; struct resource *res; @@ -1826,6 +1943,8 @@ static int hdmi_probe(struct platform_device *pdev) hdata->dev = dev; + mutex_init(&hdata->mutex); + ret = hdmi_resources_init(hdata); if (ret) { if (ret != -EPROBE_DEFER) @@ -1885,12 +2004,26 @@ static int hdmi_probe(struct platform_device *pdev) pm_runtime_enable(dev); - ret = component_add(&pdev->dev, &hdmi_component_ops); + audio_infoframe = &hdata->audio.infoframe; + hdmi_audio_infoframe_init(audio_infoframe); + audio_infoframe->coding_type = HDMI_AUDIO_CODING_TYPE_STREAM; + audio_infoframe->sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM; + audio_infoframe->sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM; + audio_infoframe->channels = 2; + + ret = hdmi_register_audio_device(hdata); if (ret) goto err_notifier_put; + ret = component_add(&pdev->dev, &hdmi_component_ops); + if (ret) + goto err_unregister_audio; + return ret; +err_unregister_audio: + platform_device_unregister(hdata->audio.pdev); + err_notifier_put: cec_notifier_put(hdata->notifier); pm_runtime_disable(dev); @@ -1914,6 +2047,7 @@ static int hdmi_remove(struct platform_device *pdev) cec_notifier_set_phys_addr(hdata->notifier, CEC_PHYS_ADDR_INVALID); component_del(&pdev->dev, &hdmi_component_ops); + platform_device_unregister(hdata->audio.pdev); cec_notifier_put(hdata->notifier); pm_runtime_disable(&pdev->dev); @@ -1929,6 +2063,8 @@ static int hdmi_remove(struct platform_device *pdev) put_device(&hdata->ddc_adpt->dev); + mutex_destroy(&hdata->mutex); + return 0; } diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index 002755415e00..dc5d79465f9b 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c @@ -67,19 +67,6 @@ #define MXR_FORMAT_ARGB4444 6 #define MXR_FORMAT_ARGB8888 7 -struct mixer_resources { - int irq; - void __iomem *mixer_regs; - void __iomem *vp_regs; - spinlock_t reg_slock; - struct clk *mixer; - struct clk *vp; - struct clk *hdmi; - struct clk *sclk_mixer; - struct clk *sclk_hdmi; - struct clk *mout_mixer; -}; - enum mixer_version_id { MXR_VER_0_0_0_16, MXR_VER_16_0_33_0, @@ -117,8 +104,18 @@ struct mixer_context { struct exynos_drm_plane planes[MIXER_WIN_NR]; unsigned long flags; - struct mixer_resources mixer_res; + int irq; + void __iomem *mixer_regs; + void __iomem *vp_regs; + spinlock_t reg_slock; + struct clk *mixer; + struct clk *vp; + struct clk *hdmi; + struct clk *sclk_mixer; + struct clk *sclk_hdmi; + struct clk *mout_mixer; enum mixer_version_id mxr_ver; + int scan_value; }; struct mixer_drv_data { @@ -194,44 +191,44 @@ static inline bool is_alpha_format(unsigned int pixel_format) } } -static inline u32 vp_reg_read(struct mixer_resources *res, u32 reg_id) +static inline u32 vp_reg_read(struct mixer_context *ctx, u32 reg_id) { - return readl(res->vp_regs + reg_id); + return readl(ctx->vp_regs + reg_id); } -static inline void vp_reg_write(struct mixer_resources *res, u32 reg_id, +static inline void vp_reg_write(struct mixer_context *ctx, u32 reg_id, u32 val) { - writel(val, res->vp_regs + reg_id); + writel(val, ctx->vp_regs + reg_id); } -static inline void vp_reg_writemask(struct mixer_resources *res, u32 reg_id, +static inline void vp_reg_writemask(struct mixer_context *ctx, u32 reg_id, u32 val, u32 mask) { - u32 old = vp_reg_read(res, reg_id); + u32 old = vp_reg_read(ctx, reg_id); val = (val & mask) | (old & ~mask); - writel(val, res->vp_regs + reg_id); + writel(val, ctx->vp_regs + reg_id); } -static inline u32 mixer_reg_read(struct mixer_resources *res, u32 reg_id) +static inline u32 mixer_reg_read(struct mixer_context *ctx, u32 reg_id) { - return readl(res->mixer_regs + reg_id); + return readl(ctx->mixer_regs + reg_id); } -static inline void mixer_reg_write(struct mixer_resources *res, u32 reg_id, +static inline void mixer_reg_write(struct mixer_context *ctx, u32 reg_id, u32 val) { - writel(val, res->mixer_regs + reg_id); + writel(val, ctx->mixer_regs + reg_id); } -static inline void mixer_reg_writemask(struct mixer_resources *res, +static inline void mixer_reg_writemask(struct mixer_context *ctx, u32 reg_id, u32 val, u32 mask) { - u32 old = mixer_reg_read(res, reg_id); + u32 old = mixer_reg_read(ctx, reg_id); val = (val & mask) | (old & ~mask); - writel(val, res->mixer_regs + reg_id); + writel(val, ctx->mixer_regs + reg_id); } static void mixer_regs_dump(struct mixer_context *ctx) @@ -239,7 +236,7 @@ static void mixer_regs_dump(struct mixer_context *ctx) #define DUMPREG(reg_id) \ do { \ DRM_DEBUG_KMS(#reg_id " = %08x\n", \ - (u32)readl(ctx->mixer_res.mixer_regs + reg_id)); \ + (u32)readl(ctx->mixer_regs + reg_id)); \ } while (0) DUMPREG(MXR_STATUS); @@ -271,7 +268,7 @@ static void vp_regs_dump(struct mixer_context *ctx) #define DUMPREG(reg_id) \ do { \ DRM_DEBUG_KMS(#reg_id " = %08x\n", \ - (u32) readl(ctx->mixer_res.vp_regs + reg_id)); \ + (u32) readl(ctx->vp_regs + reg_id)); \ } while (0) DUMPREG(VP_ENABLE); @@ -301,7 +298,7 @@ do { \ #undef DUMPREG } -static inline void vp_filter_set(struct mixer_resources *res, +static inline void vp_filter_set(struct mixer_context *ctx, int reg_id, const u8 *data, unsigned int size) { /* assure 4-byte align */ @@ -309,24 +306,23 @@ static inline void vp_filter_set(struct mixer_resources *res, for (; size; size -= 4, reg_id += 4, data += 4) { u32 val = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; - vp_reg_write(res, reg_id, val); + vp_reg_write(ctx, reg_id, val); } } -static void vp_default_filter(struct mixer_resources *res) +static void vp_default_filter(struct mixer_context *ctx) { - vp_filter_set(res, VP_POLY8_Y0_LL, + vp_filter_set(ctx, VP_POLY8_Y0_LL, filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8)); - vp_filter_set(res, VP_POLY4_Y0_LL, + vp_filter_set(ctx, VP_POLY4_Y0_LL, filter_y_vert_tap4, sizeof(filter_y_vert_tap4)); - vp_filter_set(res, VP_POLY4_C0_LL, + vp_filter_set(ctx, VP_POLY4_C0_LL, filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4)); } static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win, bool alpha) { - struct mixer_resources *res = &ctx->mixer_res; u32 val; val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */ @@ -335,13 +331,12 @@ static void mixer_cfg_gfx_blend(struct mixer_context *ctx, unsigned int win, val |= MXR_GRP_CFG_BLEND_PRE_MUL; val |= MXR_GRP_CFG_PIXEL_BLEND_EN; } - mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win), + mixer_reg_writemask(ctx, MXR_GRAPHIC_CFG(win), val, MXR_GRP_CFG_MISC_MASK); } static void mixer_cfg_vp_blend(struct mixer_context *ctx) { - struct mixer_resources *res = &ctx->mixer_res; u32 val; /* @@ -351,51 +346,39 @@ static void mixer_cfg_vp_blend(struct mixer_context *ctx) * support blending of the video layer through this. */ val = 0; - mixer_reg_write(res, MXR_VIDEO_CFG, val); + mixer_reg_write(ctx, MXR_VIDEO_CFG, val); } static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable) { - struct mixer_resources *res = &ctx->mixer_res; - /* block update on vsync */ - mixer_reg_writemask(res, MXR_STATUS, enable ? + mixer_reg_writemask(ctx, MXR_STATUS, enable ? MXR_STATUS_SYNC_ENABLE : 0, MXR_STATUS_SYNC_ENABLE); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) - vp_reg_write(res, VP_SHADOW_UPDATE, enable ? + vp_reg_write(ctx, VP_SHADOW_UPDATE, enable ? VP_SHADOW_UPDATE_ENABLE : 0); } -static void mixer_cfg_scan(struct mixer_context *ctx, unsigned int height) +static void mixer_cfg_scan(struct mixer_context *ctx, int width, int height) { - struct mixer_resources *res = &ctx->mixer_res; u32 val; /* choosing between interlace and progressive mode */ val = test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? MXR_CFG_SCAN_INTERLACE : MXR_CFG_SCAN_PROGRESSIVE; - if (ctx->mxr_ver != MXR_VER_128_0_0_184) { - /* choosing between proper HD and SD mode */ - if (height <= 480) - val |= MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD; - else if (height <= 576) - val |= MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD; - else if (height <= 720) - val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; - else if (height <= 1080) - val |= MXR_CFG_SCAN_HD_1080 | MXR_CFG_SCAN_HD; - else - val |= MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD; - } + if (ctx->mxr_ver == MXR_VER_128_0_0_184) + mixer_reg_write(ctx, MXR_RESOLUTION, + MXR_MXR_RES_HEIGHT(height) | MXR_MXR_RES_WIDTH(width)); + else + val |= ctx->scan_value; - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_SCAN_MASK); + mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_SCAN_MASK); } static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) { - struct mixer_resources *res = &ctx->mixer_res; u32 val; switch (height) { @@ -408,45 +391,44 @@ static void mixer_cfg_rgb_fmt(struct mixer_context *ctx, unsigned int height) default: val = MXR_CFG_RGB709_16_235; /* Configure the BT.709 CSC matrix for full range RGB. */ - mixer_reg_write(res, MXR_CM_COEFF_Y, + mixer_reg_write(ctx, MXR_CM_COEFF_Y, MXR_CSC_CT( 0.184, 0.614, 0.063) | MXR_CM_COEFF_RGB_FULL); - mixer_reg_write(res, MXR_CM_COEFF_CB, + mixer_reg_write(ctx, MXR_CM_COEFF_CB, MXR_CSC_CT(-0.102, -0.338, 0.440)); - mixer_reg_write(res, MXR_CM_COEFF_CR, + mixer_reg_write(ctx, MXR_CM_COEFF_CR, MXR_CSC_CT( 0.440, -0.399, -0.040)); break; } - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); + mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_RGB_FMT_MASK); } static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, unsigned int priority, bool enable) { - struct mixer_resources *res = &ctx->mixer_res; u32 val = enable ? ~0 : 0; switch (win) { case 0: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, + mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_GRP0_ENABLE); + mixer_reg_writemask(ctx, MXR_LAYER_CFG, MXR_LAYER_CFG_GRP0_VAL(priority), MXR_LAYER_CFG_GRP0_MASK); break; case 1: - mixer_reg_writemask(res, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, + mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_GRP1_ENABLE); + mixer_reg_writemask(ctx, MXR_LAYER_CFG, MXR_LAYER_CFG_GRP1_VAL(priority), MXR_LAYER_CFG_GRP1_MASK); break; case VP_DEFAULT_WIN: if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { - vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); - mixer_reg_writemask(res, MXR_CFG, val, + vp_reg_writemask(ctx, VP_ENABLE, val, VP_ENABLE_ON); + mixer_reg_writemask(ctx, MXR_CFG, val, MXR_CFG_VP_ENABLE); - mixer_reg_writemask(res, MXR_LAYER_CFG, + mixer_reg_writemask(ctx, MXR_LAYER_CFG, MXR_LAYER_CFG_VP_VAL(priority), MXR_LAYER_CFG_VP_MASK); } @@ -456,30 +438,34 @@ static void mixer_cfg_layer(struct mixer_context *ctx, unsigned int win, static void mixer_run(struct mixer_context *ctx) { - struct mixer_resources *res = &ctx->mixer_res; - - mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_REG_RUN); + mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_REG_RUN); } static void mixer_stop(struct mixer_context *ctx) { - struct mixer_resources *res = &ctx->mixer_res; int timeout = 20; - mixer_reg_writemask(res, MXR_STATUS, 0, MXR_STATUS_REG_RUN); + mixer_reg_writemask(ctx, MXR_STATUS, 0, MXR_STATUS_REG_RUN); - while (!(mixer_reg_read(res, MXR_STATUS) & MXR_STATUS_REG_IDLE) && + while (!(mixer_reg_read(ctx, MXR_STATUS) & MXR_STATUS_REG_IDLE) && --timeout) usleep_range(10000, 12000); } +static void mixer_commit(struct mixer_context *ctx) +{ + struct drm_display_mode *mode = &ctx->crtc->base.state->adjusted_mode; + + mixer_cfg_scan(ctx, mode->hdisplay, mode->vdisplay); + mixer_cfg_rgb_fmt(ctx, mode->vdisplay); + mixer_run(ctx); +} + static void vp_video_buffer(struct mixer_context *ctx, struct exynos_drm_plane *plane) { struct exynos_drm_plane_state *state = to_exynos_plane_state(plane->base.state); - struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; - struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb; unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; @@ -493,8 +479,7 @@ static void vp_video_buffer(struct mixer_context *ctx, luma_addr[0] = exynos_drm_fb_dma_addr(fb, 0); chroma_addr[0] = exynos_drm_fb_dma_addr(fb, 1); - if (mode->flags & DRM_MODE_FLAG_INTERLACE) { - __set_bit(MXR_BIT_INTERLACE, &ctx->flags); + if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { if (is_tiled) { luma_addr[1] = luma_addr[0] + 0x40; chroma_addr[1] = chroma_addr[0] + 0x40; @@ -503,63 +488,59 @@ static void vp_video_buffer(struct mixer_context *ctx, chroma_addr[1] = chroma_addr[0] + fb->pitches[0]; } } else { - __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); luma_addr[1] = 0; chroma_addr[1] = 0; } - spin_lock_irqsave(&res->reg_slock, flags); + spin_lock_irqsave(&ctx->reg_slock, flags); /* interlace or progressive scan mode */ val = (test_bit(MXR_BIT_INTERLACE, &ctx->flags) ? ~0 : 0); - vp_reg_writemask(res, VP_MODE, val, VP_MODE_LINE_SKIP); + vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_LINE_SKIP); /* setup format */ val = (is_nv21 ? VP_MODE_NV21 : VP_MODE_NV12); val |= (is_tiled ? VP_MODE_MEM_TILED : VP_MODE_MEM_LINEAR); - vp_reg_writemask(res, VP_MODE, val, VP_MODE_FMT_MASK); + vp_reg_writemask(ctx, VP_MODE, val, VP_MODE_FMT_MASK); /* setting size of input image */ - vp_reg_write(res, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | + vp_reg_write(ctx, VP_IMG_SIZE_Y, VP_IMG_HSIZE(fb->pitches[0]) | VP_IMG_VSIZE(fb->height)); /* chroma plane for NV12/NV21 is half the height of the luma plane */ - vp_reg_write(res, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) | + vp_reg_write(ctx, VP_IMG_SIZE_C, VP_IMG_HSIZE(fb->pitches[0]) | VP_IMG_VSIZE(fb->height / 2)); - vp_reg_write(res, VP_SRC_WIDTH, state->src.w); - vp_reg_write(res, VP_SRC_HEIGHT, state->src.h); - vp_reg_write(res, VP_SRC_H_POSITION, + vp_reg_write(ctx, VP_SRC_WIDTH, state->src.w); + vp_reg_write(ctx, VP_SRC_HEIGHT, state->src.h); + vp_reg_write(ctx, VP_SRC_H_POSITION, VP_SRC_H_POSITION_VAL(state->src.x)); - vp_reg_write(res, VP_SRC_V_POSITION, state->src.y); + vp_reg_write(ctx, VP_SRC_V_POSITION, state->src.y); - vp_reg_write(res, VP_DST_WIDTH, state->crtc.w); - vp_reg_write(res, VP_DST_H_POSITION, state->crtc.x); + vp_reg_write(ctx, VP_DST_WIDTH, state->crtc.w); + vp_reg_write(ctx, VP_DST_H_POSITION, state->crtc.x); if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { - vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h / 2); - vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y / 2); + vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h / 2); + vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y / 2); } else { - vp_reg_write(res, VP_DST_HEIGHT, state->crtc.h); - vp_reg_write(res, VP_DST_V_POSITION, state->crtc.y); + vp_reg_write(ctx, VP_DST_HEIGHT, state->crtc.h); + vp_reg_write(ctx, VP_DST_V_POSITION, state->crtc.y); } - vp_reg_write(res, VP_H_RATIO, state->h_ratio); - vp_reg_write(res, VP_V_RATIO, state->v_ratio); + vp_reg_write(ctx, VP_H_RATIO, state->h_ratio); + vp_reg_write(ctx, VP_V_RATIO, state->v_ratio); - vp_reg_write(res, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE); + vp_reg_write(ctx, VP_ENDIAN_MODE, VP_ENDIAN_MODE_LITTLE); /* set buffer address to vp */ - vp_reg_write(res, VP_TOP_Y_PTR, luma_addr[0]); - vp_reg_write(res, VP_BOT_Y_PTR, luma_addr[1]); - vp_reg_write(res, VP_TOP_C_PTR, chroma_addr[0]); - vp_reg_write(res, VP_BOT_C_PTR, chroma_addr[1]); + vp_reg_write(ctx, VP_TOP_Y_PTR, luma_addr[0]); + vp_reg_write(ctx, VP_BOT_Y_PTR, luma_addr[1]); + vp_reg_write(ctx, VP_TOP_C_PTR, chroma_addr[0]); + vp_reg_write(ctx, VP_BOT_C_PTR, chroma_addr[1]); - mixer_cfg_scan(ctx, mode->vdisplay); - mixer_cfg_rgb_fmt(ctx, mode->vdisplay); mixer_cfg_layer(ctx, plane->index, priority, true); mixer_cfg_vp_blend(ctx); - mixer_run(ctx); - spin_unlock_irqrestore(&res->reg_slock, flags); + spin_unlock_irqrestore(&ctx->reg_slock, flags); mixer_regs_dump(ctx); vp_regs_dump(ctx); @@ -567,9 +548,7 @@ static void vp_video_buffer(struct mixer_context *ctx, static void mixer_layer_update(struct mixer_context *ctx) { - struct mixer_resources *res = &ctx->mixer_res; - - mixer_reg_writemask(res, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); + mixer_reg_writemask(ctx, MXR_CFG, ~0, MXR_CFG_LAYER_UPDATE); } static void mixer_graph_buffer(struct mixer_context *ctx, @@ -577,8 +556,6 @@ static void mixer_graph_buffer(struct mixer_context *ctx, { struct exynos_drm_plane_state *state = to_exynos_plane_state(plane->base.state); - struct drm_display_mode *mode = &state->base.crtc->state->adjusted_mode; - struct mixer_resources *res = &ctx->mixer_res; struct drm_framebuffer *fb = state->base.fb; unsigned int priority = state->base.normalized_zpos + 1; unsigned long flags; @@ -623,45 +600,30 @@ static void mixer_graph_buffer(struct mixer_context *ctx, + (state->src.x * fb->format->cpp[0]) + (state->src.y * fb->pitches[0]); - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - __set_bit(MXR_BIT_INTERLACE, &ctx->flags); - else - __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); - - spin_lock_irqsave(&res->reg_slock, flags); + spin_lock_irqsave(&ctx->reg_slock, flags); /* setup format */ - mixer_reg_writemask(res, MXR_GRAPHIC_CFG(win), + mixer_reg_writemask(ctx, MXR_GRAPHIC_CFG(win), MXR_GRP_CFG_FORMAT_VAL(fmt), MXR_GRP_CFG_FORMAT_MASK); /* setup geometry */ - mixer_reg_write(res, MXR_GRAPHIC_SPAN(win), + mixer_reg_write(ctx, MXR_GRAPHIC_SPAN(win), fb->pitches[0] / fb->format->cpp[0]); - /* setup display size */ - if (ctx->mxr_ver == MXR_VER_128_0_0_184 && - win == DEFAULT_WIN) { - val = MXR_MXR_RES_HEIGHT(mode->vdisplay); - val |= MXR_MXR_RES_WIDTH(mode->hdisplay); - mixer_reg_write(res, MXR_RESOLUTION, val); - } - val = MXR_GRP_WH_WIDTH(state->src.w); val |= MXR_GRP_WH_HEIGHT(state->src.h); val |= MXR_GRP_WH_H_SCALE(x_ratio); val |= MXR_GRP_WH_V_SCALE(y_ratio); - mixer_reg_write(res, MXR_GRAPHIC_WH(win), val); + mixer_reg_write(ctx, MXR_GRAPHIC_WH(win), val); /* setup offsets in display image */ val = MXR_GRP_DXY_DX(dst_x_offset); val |= MXR_GRP_DXY_DY(dst_y_offset); - mixer_reg_write(res, MXR_GRAPHIC_DXY(win), val); + mixer_reg_write(ctx, MXR_GRAPHIC_DXY(win), val); /* set buffer address to mixer */ - mixer_reg_write(res, MXR_GRAPHIC_BASE(win), dma_addr); + mixer_reg_write(ctx, MXR_GRAPHIC_BASE(win), dma_addr); - mixer_cfg_scan(ctx, mode->vdisplay); - mixer_cfg_rgb_fmt(ctx, mode->vdisplay); mixer_cfg_layer(ctx, win, priority, true); mixer_cfg_gfx_blend(ctx, win, is_alpha_format(fb->format->format)); @@ -670,22 +632,19 @@ static void mixer_graph_buffer(struct mixer_context *ctx, ctx->mxr_ver == MXR_VER_128_0_0_184) mixer_layer_update(ctx); - mixer_run(ctx); - - spin_unlock_irqrestore(&res->reg_slock, flags); + spin_unlock_irqrestore(&ctx->reg_slock, flags); mixer_regs_dump(ctx); } static void vp_win_reset(struct mixer_context *ctx) { - struct mixer_resources *res = &ctx->mixer_res; unsigned int tries = 100; - vp_reg_write(res, VP_SRESET, VP_SRESET_PROCESSING); + vp_reg_write(ctx, VP_SRESET, VP_SRESET_PROCESSING); while (--tries) { /* waiting until VP_SRESET_PROCESSING is 0 */ - if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) + if (~vp_reg_read(ctx, VP_SRESET) & VP_SRESET_PROCESSING) break; mdelay(10); } @@ -694,57 +653,55 @@ static void vp_win_reset(struct mixer_context *ctx) static void mixer_win_reset(struct mixer_context *ctx) { - struct mixer_resources *res = &ctx->mixer_res; unsigned long flags; - spin_lock_irqsave(&res->reg_slock, flags); + spin_lock_irqsave(&ctx->reg_slock, flags); - mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK); + mixer_reg_writemask(ctx, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK); /* set output in RGB888 mode */ - mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK); + mixer_reg_writemask(ctx, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK); /* 16 beat burst in DMA */ - mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST, + mixer_reg_writemask(ctx, MXR_STATUS, MXR_STATUS_16_BURST, MXR_STATUS_BURST_MASK); /* reset default layer priority */ - mixer_reg_write(res, MXR_LAYER_CFG, 0); + mixer_reg_write(ctx, MXR_LAYER_CFG, 0); /* set all background colors to RGB (0,0,0) */ - mixer_reg_write(res, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128)); - mixer_reg_write(res, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128)); - mixer_reg_write(res, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(ctx, MXR_BG_COLOR0, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(ctx, MXR_BG_COLOR1, MXR_YCBCR_VAL(0, 128, 128)); + mixer_reg_write(ctx, MXR_BG_COLOR2, MXR_YCBCR_VAL(0, 128, 128)); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { /* configuration of Video Processor Registers */ vp_win_reset(ctx); - vp_default_filter(res); + vp_default_filter(ctx); } /* disable all layers */ - mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); - mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE); + mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE); + mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) - mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE); + mixer_reg_writemask(ctx, MXR_CFG, 0, MXR_CFG_VP_ENABLE); /* set all source image offsets to zero */ - mixer_reg_write(res, MXR_GRAPHIC_SXY(0), 0); - mixer_reg_write(res, MXR_GRAPHIC_SXY(1), 0); + mixer_reg_write(ctx, MXR_GRAPHIC_SXY(0), 0); + mixer_reg_write(ctx, MXR_GRAPHIC_SXY(1), 0); - spin_unlock_irqrestore(&res->reg_slock, flags); + spin_unlock_irqrestore(&ctx->reg_slock, flags); } static irqreturn_t mixer_irq_handler(int irq, void *arg) { struct mixer_context *ctx = arg; - struct mixer_resources *res = &ctx->mixer_res; u32 val, base, shadow; - spin_lock(&res->reg_slock); + spin_lock(&ctx->reg_slock); /* read interrupt status for handling and clearing flags for VSYNC */ - val = mixer_reg_read(res, MXR_INT_STATUS); + val = mixer_reg_read(ctx, MXR_INT_STATUS); /* handling VSYNC */ if (val & MXR_INT_STATUS_VSYNC) { @@ -754,13 +711,13 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) /* interlace scan need to check shadow register */ if (test_bit(MXR_BIT_INTERLACE, &ctx->flags)) { - base = mixer_reg_read(res, MXR_GRAPHIC_BASE(0)); - shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(0)); + base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(0)); + shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(0)); if (base != shadow) goto out; - base = mixer_reg_read(res, MXR_GRAPHIC_BASE(1)); - shadow = mixer_reg_read(res, MXR_GRAPHIC_BASE_S(1)); + base = mixer_reg_read(ctx, MXR_GRAPHIC_BASE(1)); + shadow = mixer_reg_read(ctx, MXR_GRAPHIC_BASE_S(1)); if (base != shadow) goto out; } @@ -770,9 +727,9 @@ static irqreturn_t mixer_irq_handler(int irq, void *arg) out: /* clear interrupts */ - mixer_reg_write(res, MXR_INT_STATUS, val); + mixer_reg_write(ctx, MXR_INT_STATUS, val); - spin_unlock(&res->reg_slock); + spin_unlock(&ctx->reg_slock); return IRQ_HANDLED; } @@ -780,26 +737,25 @@ out: static int mixer_resources_init(struct mixer_context *mixer_ctx) { struct device *dev = &mixer_ctx->pdev->dev; - struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; struct resource *res; int ret; - spin_lock_init(&mixer_res->reg_slock); + spin_lock_init(&mixer_ctx->reg_slock); - mixer_res->mixer = devm_clk_get(dev, "mixer"); - if (IS_ERR(mixer_res->mixer)) { + mixer_ctx->mixer = devm_clk_get(dev, "mixer"); + if (IS_ERR(mixer_ctx->mixer)) { dev_err(dev, "failed to get clock 'mixer'\n"); return -ENODEV; } - mixer_res->hdmi = devm_clk_get(dev, "hdmi"); - if (IS_ERR(mixer_res->hdmi)) { + mixer_ctx->hdmi = devm_clk_get(dev, "hdmi"); + if (IS_ERR(mixer_ctx->hdmi)) { dev_err(dev, "failed to get clock 'hdmi'\n"); - return PTR_ERR(mixer_res->hdmi); + return PTR_ERR(mixer_ctx->hdmi); } - mixer_res->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); - if (IS_ERR(mixer_res->sclk_hdmi)) { + mixer_ctx->sclk_hdmi = devm_clk_get(dev, "sclk_hdmi"); + if (IS_ERR(mixer_ctx->sclk_hdmi)) { dev_err(dev, "failed to get clock 'sclk_hdmi'\n"); return -ENODEV; } @@ -809,9 +765,9 @@ static int mixer_resources_init(struct mixer_context *mixer_ctx) return -ENXIO; } - mixer_res->mixer_regs = devm_ioremap(dev, res->start, + mixer_ctx->mixer_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (mixer_res->mixer_regs == NULL) { + if (mixer_ctx->mixer_regs == NULL) { dev_err(dev, "register mapping failed.\n"); return -ENXIO; } @@ -828,7 +784,7 @@ static int mixer_resources_init(struct mixer_context *mixer_ctx) dev_err(dev, "request interrupt failed.\n"); return ret; } - mixer_res->irq = res->start; + mixer_ctx->irq = res->start; return 0; } @@ -836,30 +792,29 @@ static int mixer_resources_init(struct mixer_context *mixer_ctx) static int vp_resources_init(struct mixer_context *mixer_ctx) { struct device *dev = &mixer_ctx->pdev->dev; - struct mixer_resources *mixer_res = &mixer_ctx->mixer_res; struct resource *res; - mixer_res->vp = devm_clk_get(dev, "vp"); - if (IS_ERR(mixer_res->vp)) { + mixer_ctx->vp = devm_clk_get(dev, "vp"); + if (IS_ERR(mixer_ctx->vp)) { dev_err(dev, "failed to get clock 'vp'\n"); return -ENODEV; } if (test_bit(MXR_BIT_HAS_SCLK, &mixer_ctx->flags)) { - mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); - if (IS_ERR(mixer_res->sclk_mixer)) { + mixer_ctx->sclk_mixer = devm_clk_get(dev, "sclk_mixer"); + if (IS_ERR(mixer_ctx->sclk_mixer)) { dev_err(dev, "failed to get clock 'sclk_mixer'\n"); return -ENODEV; } - mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer"); - if (IS_ERR(mixer_res->mout_mixer)) { + mixer_ctx->mout_mixer = devm_clk_get(dev, "mout_mixer"); + if (IS_ERR(mixer_ctx->mout_mixer)) { dev_err(dev, "failed to get clock 'mout_mixer'\n"); return -ENODEV; } - if (mixer_res->sclk_hdmi && mixer_res->mout_mixer) - clk_set_parent(mixer_res->mout_mixer, - mixer_res->sclk_hdmi); + if (mixer_ctx->sclk_hdmi && mixer_ctx->mout_mixer) + clk_set_parent(mixer_ctx->mout_mixer, + mixer_ctx->sclk_hdmi); } res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1); @@ -868,9 +823,9 @@ static int vp_resources_init(struct mixer_context *mixer_ctx) return -ENXIO; } - mixer_res->vp_regs = devm_ioremap(dev, res->start, + mixer_ctx->vp_regs = devm_ioremap(dev, res->start, resource_size(res)); - if (mixer_res->vp_regs == NULL) { + if (mixer_ctx->vp_regs == NULL) { dev_err(dev, "register mapping failed.\n"); return -ENXIO; } @@ -914,15 +869,14 @@ static void mixer_ctx_remove(struct mixer_context *mixer_ctx) static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) { struct mixer_context *mixer_ctx = crtc->ctx; - struct mixer_resources *res = &mixer_ctx->mixer_res; __set_bit(MXR_BIT_VSYNC, &mixer_ctx->flags); if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) return 0; /* enable vsync interrupt */ - mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); - mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC); + mixer_reg_writemask(mixer_ctx, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); + mixer_reg_writemask(mixer_ctx, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC); return 0; } @@ -930,7 +884,6 @@ static int mixer_enable_vblank(struct exynos_drm_crtc *crtc) static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) { struct mixer_context *mixer_ctx = crtc->ctx; - struct mixer_resources *res = &mixer_ctx->mixer_res; __clear_bit(MXR_BIT_VSYNC, &mixer_ctx->flags); @@ -938,8 +891,8 @@ static void mixer_disable_vblank(struct exynos_drm_crtc *crtc) return; /* disable vsync interrupt */ - mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); - mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); + mixer_reg_writemask(mixer_ctx, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); + mixer_reg_writemask(mixer_ctx, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); } static void mixer_atomic_begin(struct exynos_drm_crtc *crtc) @@ -972,7 +925,6 @@ static void mixer_disable_plane(struct exynos_drm_crtc *crtc, struct exynos_drm_plane *plane) { struct mixer_context *mixer_ctx = crtc->ctx; - struct mixer_resources *res = &mixer_ctx->mixer_res; unsigned long flags; DRM_DEBUG_KMS("win: %d\n", plane->index); @@ -980,9 +932,9 @@ static void mixer_disable_plane(struct exynos_drm_crtc *crtc, if (!test_bit(MXR_BIT_POWERED, &mixer_ctx->flags)) return; - spin_lock_irqsave(&res->reg_slock, flags); + spin_lock_irqsave(&mixer_ctx->reg_slock, flags); mixer_cfg_layer(mixer_ctx, plane->index, 0, false); - spin_unlock_irqrestore(&res->reg_slock, flags); + spin_unlock_irqrestore(&mixer_ctx->reg_slock, flags); } static void mixer_atomic_flush(struct exynos_drm_crtc *crtc) @@ -999,7 +951,6 @@ static void mixer_atomic_flush(struct exynos_drm_crtc *crtc) static void mixer_enable(struct exynos_drm_crtc *crtc) { struct mixer_context *ctx = crtc->ctx; - struct mixer_resources *res = &ctx->mixer_res; if (test_bit(MXR_BIT_POWERED, &ctx->flags)) return; @@ -1010,14 +961,17 @@ static void mixer_enable(struct exynos_drm_crtc *crtc) mixer_vsync_set_update(ctx, false); - mixer_reg_writemask(res, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); + mixer_reg_writemask(ctx, MXR_STATUS, ~0, MXR_STATUS_SOFT_RESET); if (test_bit(MXR_BIT_VSYNC, &ctx->flags)) { - mixer_reg_writemask(res, MXR_INT_STATUS, ~0, MXR_INT_CLEAR_VSYNC); - mixer_reg_writemask(res, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC); + mixer_reg_writemask(ctx, MXR_INT_STATUS, ~0, + MXR_INT_CLEAR_VSYNC); + mixer_reg_writemask(ctx, MXR_INT_EN, ~0, MXR_INT_EN_VSYNC); } mixer_win_reset(ctx); + mixer_commit(ctx); + mixer_vsync_set_update(ctx, true); set_bit(MXR_BIT_POWERED, &ctx->flags); @@ -1044,26 +998,75 @@ static void mixer_disable(struct exynos_drm_crtc *crtc) clear_bit(MXR_BIT_POWERED, &ctx->flags); } -/* Only valid for Mixer version 16.0.33.0 */ -static int mixer_atomic_check(struct exynos_drm_crtc *crtc, - struct drm_crtc_state *state) +static int mixer_mode_valid(struct exynos_drm_crtc *crtc, + const struct drm_display_mode *mode) { - struct drm_display_mode *mode = &state->adjusted_mode; - u32 w, h; + struct mixer_context *ctx = crtc->ctx; + u32 w = mode->hdisplay, h = mode->vdisplay; - w = mode->hdisplay; - h = mode->vdisplay; + DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n", w, h, + mode->vrefresh, !!(mode->flags & DRM_MODE_FLAG_INTERLACE)); - DRM_DEBUG_KMS("xres=%d, yres=%d, refresh=%d, intl=%d\n", - mode->hdisplay, mode->vdisplay, mode->vrefresh, - (mode->flags & DRM_MODE_FLAG_INTERLACE) ? 1 : 0); + if (ctx->mxr_ver == MXR_VER_128_0_0_184) + return MODE_OK; if ((w >= 464 && w <= 720 && h >= 261 && h <= 576) || - (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) || - (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080)) - return 0; + (w >= 1024 && w <= 1280 && h >= 576 && h <= 720) || + (w >= 1664 && w <= 1920 && h >= 936 && h <= 1080)) + return MODE_OK; + + if ((w == 1024 && h == 768) || + (w == 1366 && h == 768) || + (w == 1280 && h == 1024)) + return MODE_OK; + + return MODE_BAD; +} + +static bool mixer_mode_fixup(struct exynos_drm_crtc *crtc, + const struct drm_display_mode *mode, + struct drm_display_mode *adjusted_mode) +{ + struct mixer_context *ctx = crtc->ctx; + int width = mode->hdisplay, height = mode->vdisplay, i; + + struct { + int hdisplay, vdisplay, htotal, vtotal, scan_val; + } static const modes[] = { + { 720, 480, 858, 525, MXR_CFG_SCAN_NTSC | MXR_CFG_SCAN_SD }, + { 720, 576, 864, 625, MXR_CFG_SCAN_PAL | MXR_CFG_SCAN_SD }, + { 1280, 720, 1650, 750, MXR_CFG_SCAN_HD_720 | MXR_CFG_SCAN_HD }, + { 1920, 1080, 2200, 1125, MXR_CFG_SCAN_HD_1080 | + MXR_CFG_SCAN_HD } + }; + + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + __set_bit(MXR_BIT_INTERLACE, &ctx->flags); + else + __clear_bit(MXR_BIT_INTERLACE, &ctx->flags); + + if (ctx->mxr_ver == MXR_VER_128_0_0_184) + return true; + + for (i = 0; i < ARRAY_SIZE(modes); ++i) + if (width <= modes[i].hdisplay && height <= modes[i].vdisplay) { + ctx->scan_value = modes[i].scan_val; + if (width < modes[i].hdisplay || + height < modes[i].vdisplay) { + adjusted_mode->hdisplay = modes[i].hdisplay; + adjusted_mode->hsync_start = modes[i].hdisplay; + adjusted_mode->hsync_end = modes[i].htotal; + adjusted_mode->htotal = modes[i].htotal; + adjusted_mode->vdisplay = modes[i].vdisplay; + adjusted_mode->vsync_start = modes[i].vdisplay; + adjusted_mode->vsync_end = modes[i].vtotal; + adjusted_mode->vtotal = modes[i].vtotal; + } + + return true; + } - return -EINVAL; + return false; } static const struct exynos_drm_crtc_ops mixer_crtc_ops = { @@ -1075,7 +1078,8 @@ static const struct exynos_drm_crtc_ops mixer_crtc_ops = { .update_plane = mixer_update_plane, .disable_plane = mixer_disable_plane, .atomic_flush = mixer_atomic_flush, - .atomic_check = mixer_atomic_check, + .mode_valid = mixer_mode_valid, + .mode_fixup = mixer_mode_fixup, }; static const struct mixer_drv_data exynos5420_mxr_drv_data = { @@ -1217,14 +1221,13 @@ static int mixer_remove(struct platform_device *pdev) static int __maybe_unused exynos_mixer_suspend(struct device *dev) { struct mixer_context *ctx = dev_get_drvdata(dev); - struct mixer_resources *res = &ctx->mixer_res; - clk_disable_unprepare(res->hdmi); - clk_disable_unprepare(res->mixer); + clk_disable_unprepare(ctx->hdmi); + clk_disable_unprepare(ctx->mixer); if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { - clk_disable_unprepare(res->vp); + clk_disable_unprepare(ctx->vp); if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) - clk_disable_unprepare(res->sclk_mixer); + clk_disable_unprepare(ctx->sclk_mixer); } return 0; @@ -1233,28 +1236,27 @@ static int __maybe_unused exynos_mixer_suspend(struct device *dev) static int __maybe_unused exynos_mixer_resume(struct device *dev) { struct mixer_context *ctx = dev_get_drvdata(dev); - struct mixer_resources *res = &ctx->mixer_res; int ret; - ret = clk_prepare_enable(res->mixer); + ret = clk_prepare_enable(ctx->mixer); if (ret < 0) { DRM_ERROR("Failed to prepare_enable the mixer clk [%d]\n", ret); return ret; } - ret = clk_prepare_enable(res->hdmi); + ret = clk_prepare_enable(ctx->hdmi); if (ret < 0) { DRM_ERROR("Failed to prepare_enable the hdmi clk [%d]\n", ret); return ret; } if (test_bit(MXR_BIT_VP_ENABLED, &ctx->flags)) { - ret = clk_prepare_enable(res->vp); + ret = clk_prepare_enable(ctx->vp); if (ret < 0) { DRM_ERROR("Failed to prepare_enable the vp clk [%d]\n", ret); return ret; } if (test_bit(MXR_BIT_HAS_SCLK, &ctx->flags)) { - ret = clk_prepare_enable(res->sclk_mixer); + ret = clk_prepare_enable(ctx->sclk_mixer); if (ret < 0) { DRM_ERROR("Failed to prepare_enable the " \ "sclk_mixer clk [%d]\n", diff --git a/drivers/gpu/drm/exynos/regs-hdmi.h b/drivers/gpu/drm/exynos/regs-hdmi.h index a0507dc18d9e..04be0f7e8193 100644 --- a/drivers/gpu/drm/exynos/regs-hdmi.h +++ b/drivers/gpu/drm/exynos/regs-hdmi.h @@ -419,11 +419,9 @@ #define HDMI_I2S_DSD_CON HDMI_I2S_BASE(0x01c) #define HDMI_I2S_MUX_CON HDMI_I2S_BASE(0x020) #define HDMI_I2S_CH_ST_CON HDMI_I2S_BASE(0x024) -#define HDMI_I2S_CH_ST_0 HDMI_I2S_BASE(0x028) -#define HDMI_I2S_CH_ST_1 HDMI_I2S_BASE(0x02c) -#define HDMI_I2S_CH_ST_2 HDMI_I2S_BASE(0x030) -#define HDMI_I2S_CH_ST_3 HDMI_I2S_BASE(0x034) -#define HDMI_I2S_CH_ST_4 HDMI_I2S_BASE(0x038) +/* n must be within range 0...(HDMI_I2S_CH_ST_MAXNUM - 1) */ +#define HDMI_I2S_CH_ST_MAXNUM 5 +#define HDMI_I2S_CH_ST(n) HDMI_I2S_BASE(0x028 + 4 * (n)) #define HDMI_I2S_CH_ST_SH_0 HDMI_I2S_BASE(0x03c) #define HDMI_I2S_CH_ST_SH_1 HDMI_I2S_BASE(0x040) #define HDMI_I2S_CH_ST_SH_2 HDMI_I2S_BASE(0x044) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index ec4dd9df9150..f4eba87c96f3 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -36,7 +36,7 @@ static int hibmc_connector_mode_valid(struct drm_connector *connector, static struct drm_encoder * hibmc_connector_best_encoder(struct drm_connector *connector) { - return drm_encoder_find(connector->dev, connector->encoder_ids[0]); + return drm_encoder_find(connector->dev, NULL, connector->encoder_ids[0]); } static const struct drm_connector_helper_funcs diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index 9823477b1855..2269be91f3e1 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -534,9 +534,12 @@ static void ade_crtc_atomic_begin(struct drm_crtc *crtc, { struct ade_crtc *acrtc = to_ade_crtc(crtc); struct ade_hw_ctx *ctx = acrtc->ctx; + struct drm_display_mode *mode = &crtc->state->mode; + struct drm_display_mode *adj_mode = &crtc->state->adjusted_mode; if (!ctx->power_on) (void)ade_power_up(ctx); + ade_ldi_set_mode(acrtc, mode, adj_mode); } static void ade_crtc_atomic_flush(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index e9e64e8e9765..dfd95889f4b7 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig @@ -12,6 +12,7 @@ config DRM_I915 select DRM_PANEL select DRM_MIPI_DSI select RELAY + select IRQ_WORK # i915 depends on ACPI_VIDEO when ACPI is enabled # but for select to work, need to select ACPI_VIDEO's dependencies, ick select BACKLIGHT_LCD_SUPPORT if ACPI diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 1cb8059a3a16..6c3b0481ef82 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -47,6 +47,7 @@ i915-y += i915_cmd_parser.o \ i915_gem_tiling.o \ i915_gem_timeline.o \ i915_gem_userptr.o \ + i915_gemfs.o \ i915_trace_points.o \ i915_vma.o \ intel_breadcrumbs.o \ @@ -59,9 +60,11 @@ i915-y += i915_cmd_parser.o \ # general-purpose microcontroller (GuC) support i915-y += intel_uc.o \ + intel_uc_fw.o \ + intel_guc.o \ intel_guc_ct.o \ intel_guc_log.o \ - intel_guc_loader.o \ + intel_guc_fw.o \ intel_huc.o \ i915_guc_submission.o @@ -139,7 +142,8 @@ i915-y += i915_perf.o \ i915_oa_bxt.o \ i915_oa_kblgt2.o \ i915_oa_kblgt3.o \ - i915_oa_glk.o + i915_oa_glk.o \ + i915_oa_cflgt2.o ifeq ($(CONFIG_DRM_I915_GVT),y) i915-y += intel_gvt.o diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index ff3154fe6588..ab19545d59a1 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -101,7 +101,7 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, if (WARN_ON(bytes > 4)) return -EINVAL; - if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ)) + if (WARN_ON(offset + bytes > vgpu->gvt->device_info.cfg_space_size)) return -EINVAL; memcpy(p_data, vgpu_cfg_space(vgpu) + offset, bytes); @@ -110,13 +110,25 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, static int map_aperture(struct intel_vgpu *vgpu, bool map) { - u64 first_gfn, first_mfn; + phys_addr_t aperture_pa = vgpu_aperture_pa_base(vgpu); + unsigned long aperture_sz = vgpu_aperture_sz(vgpu); + u64 first_gfn; u64 val; int ret; if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) return 0; + if (map) { + vgpu->gm.aperture_va = memremap(aperture_pa, aperture_sz, + MEMREMAP_WC); + if (!vgpu->gm.aperture_va) + return -ENOMEM; + } else { + memunmap(vgpu->gm.aperture_va); + vgpu->gm.aperture_va = NULL; + } + val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2]; if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); @@ -124,14 +136,16 @@ static int map_aperture(struct intel_vgpu *vgpu, bool map) val = *(u32 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); first_gfn = (val + vgpu_aperture_offset(vgpu)) >> PAGE_SHIFT; - first_mfn = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT; ret = intel_gvt_hypervisor_map_gfn_to_mfn(vgpu, first_gfn, - first_mfn, - vgpu_aperture_sz(vgpu) >> - PAGE_SHIFT, map); - if (ret) + aperture_pa >> PAGE_SHIFT, + aperture_sz >> PAGE_SHIFT, + map); + if (ret) { + memunmap(vgpu->gm.aperture_va); + vgpu->gm.aperture_va = NULL; return ret; + } vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map; return 0; @@ -275,7 +289,7 @@ int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, if (WARN_ON(bytes > 4)) return -EINVAL; - if (WARN_ON(offset + bytes > INTEL_GVT_MAX_CFG_SPACE_SZ)) + if (WARN_ON(offset + bytes > vgpu->gvt->device_info.cfg_space_size)) return -EINVAL; /* First check if it's PCI_COMMAND */ diff --git a/drivers/gpu/drm/i915/gvt/cmd_parser.c b/drivers/gpu/drm/i915/gvt/cmd_parser.c index 21c36e256884..701a3c6f1669 100644 --- a/drivers/gpu/drm/i915/gvt/cmd_parser.c +++ b/drivers/gpu/drm/i915/gvt/cmd_parser.c @@ -1576,11 +1576,11 @@ static int batch_buffer_needs_scan(struct parser_exec_state *s) return 1; } -static uint32_t find_bb_size(struct parser_exec_state *s) +static int find_bb_size(struct parser_exec_state *s) { unsigned long gma = 0; struct cmd_info *info; - uint32_t bb_size = 0; + int bb_size = 0; uint32_t cmd_len = 0; bool met_bb_end = false; struct intel_vgpu *vgpu = s->vgpu; @@ -1637,6 +1637,8 @@ static int perform_bb_shadow(struct parser_exec_state *s) /* get the size of the batch buffer */ bb_size = find_bb_size(s); + if (bb_size < 0) + return -EINVAL; /* allocate shadow batch buffer */ entry_obj = kmalloc(sizeof(*entry_obj), GFP_KERNEL); @@ -2603,7 +2605,8 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload) { struct intel_vgpu *vgpu = workload->vgpu; unsigned long gma_head, gma_tail, gma_top, guest_rb_size; - u32 *cs; + void *shadow_ring_buffer_va; + int ring_id = workload->ring_id; int ret; guest_rb_size = _RING_CTL_BUF_SIZE(workload->rb_ctl); @@ -2616,34 +2619,42 @@ static int shadow_workload_ring_buffer(struct intel_vgpu_workload *workload) gma_tail = workload->rb_start + workload->rb_tail; gma_top = workload->rb_start + guest_rb_size; - /* allocate shadow ring buffer */ - cs = intel_ring_begin(workload->req, workload->rb_len / sizeof(u32)); - if (IS_ERR(cs)) - return PTR_ERR(cs); + if (workload->rb_len > vgpu->reserve_ring_buffer_size[ring_id]) { + void *va = vgpu->reserve_ring_buffer_va[ring_id]; + /* realloc the new ring buffer if needed */ + vgpu->reserve_ring_buffer_va[ring_id] = + krealloc(va, workload->rb_len, GFP_KERNEL); + if (!vgpu->reserve_ring_buffer_va[ring_id]) { + gvt_vgpu_err("fail to alloc reserve ring buffer\n"); + return -ENOMEM; + } + vgpu->reserve_ring_buffer_size[ring_id] = workload->rb_len; + } + + shadow_ring_buffer_va = vgpu->reserve_ring_buffer_va[ring_id]; /* get shadow ring buffer va */ - workload->shadow_ring_buffer_va = cs; + workload->shadow_ring_buffer_va = shadow_ring_buffer_va; /* head > tail --> copy head <-> top */ if (gma_head > gma_tail) { ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, - gma_head, gma_top, cs); + gma_head, gma_top, shadow_ring_buffer_va); if (ret < 0) { gvt_vgpu_err("fail to copy guest ring buffer\n"); return ret; } - cs += ret / sizeof(u32); + shadow_ring_buffer_va += ret; gma_head = workload->rb_start; } /* copy head or start <-> tail */ - ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, gma_head, gma_tail, cs); + ret = copy_gma_to_hva(vgpu, vgpu->gtt.ggtt_mm, gma_head, gma_tail, + shadow_ring_buffer_va); if (ret < 0) { gvt_vgpu_err("fail to copy guest ring buffer\n"); return ret; } - cs += ret / sizeof(u32); - intel_ring_advance(workload->req, cs); return 0; } @@ -2723,6 +2734,9 @@ static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) uint32_t per_ctx_start[CACHELINE_DWORDS] = {0}; unsigned char *bb_start_sva; + if (!wa_ctx->per_ctx.valid) + return 0; + per_ctx_start[0] = 0x18800001; per_ctx_start[1] = wa_ctx->per_ctx.guest_gma; diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 91b4300f3b39..4427be18e4a9 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -368,7 +368,7 @@ static void free_workload(struct intel_vgpu_workload *workload) #define get_desc_from_elsp_dwords(ed, i) \ ((struct execlist_ctx_descriptor_format *)&((ed)->data[i * 2])) -static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) +static int prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) { const int gmadr_bytes = workload->vgpu->gvt->device_info.gmadr_bytes_in_cmd; struct intel_shadow_bb_entry *entry_obj; @@ -379,7 +379,7 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) vma = i915_gem_object_ggtt_pin(entry_obj->obj, NULL, 0, 4, 0); if (IS_ERR(vma)) { - return; + return PTR_ERR(vma); } /* FIXME: we are not tracking our pinned VMA leaving it @@ -392,6 +392,7 @@ static void prepare_shadow_batch_buffer(struct intel_vgpu_workload *workload) if (gmadr_bytes == 8) entry_obj->bb_start_cmd_va[2] = 0; } + return 0; } static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) @@ -420,7 +421,7 @@ static int update_wa_ctx_2_shadow_ctx(struct intel_shadow_wa_ctx *wa_ctx) return 0; } -static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +static int prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) { struct i915_vma *vma; unsigned char *per_ctx_va = @@ -428,12 +429,12 @@ static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) wa_ctx->indirect_ctx.size; if (wa_ctx->indirect_ctx.size == 0) - return; + return 0; vma = i915_gem_object_ggtt_pin(wa_ctx->indirect_ctx.obj, NULL, 0, CACHELINE_BYTES, 0); if (IS_ERR(vma)) { - return; + return PTR_ERR(vma); } /* FIXME: we are not tracking our pinned VMA leaving it @@ -447,26 +448,7 @@ static void prepare_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) memset(per_ctx_va, 0, CACHELINE_BYTES); update_wa_ctx_2_shadow_ctx(wa_ctx); -} - -static int prepare_execlist_workload(struct intel_vgpu_workload *workload) -{ - struct intel_vgpu *vgpu = workload->vgpu; - struct execlist_ctx_descriptor_format ctx[2]; - int ring_id = workload->ring_id; - - intel_vgpu_pin_mm(workload->shadow_mm); - intel_vgpu_sync_oos_pages(workload->vgpu); - intel_vgpu_flush_post_shadow(workload->vgpu); - prepare_shadow_batch_buffer(workload); - prepare_shadow_wa_ctx(&workload->wa_ctx); - if (!workload->emulate_schedule_in) - return 0; - - ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1); - ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0); - - return emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx); + return 0; } static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) @@ -489,13 +471,62 @@ static void release_shadow_batch_buffer(struct intel_vgpu_workload *workload) } } -static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +static int prepare_execlist_workload(struct intel_vgpu_workload *workload) { - if (!wa_ctx->indirect_ctx.obj) - return; + struct intel_vgpu *vgpu = workload->vgpu; + struct execlist_ctx_descriptor_format ctx[2]; + int ring_id = workload->ring_id; + int ret; + + ret = intel_vgpu_pin_mm(workload->shadow_mm); + if (ret) { + gvt_vgpu_err("fail to vgpu pin mm\n"); + goto out; + } + + ret = intel_vgpu_sync_oos_pages(workload->vgpu); + if (ret) { + gvt_vgpu_err("fail to vgpu sync oos pages\n"); + goto err_unpin_mm; + } + + ret = intel_vgpu_flush_post_shadow(workload->vgpu); + if (ret) { + gvt_vgpu_err("fail to flush post shadow\n"); + goto err_unpin_mm; + } + + ret = prepare_shadow_batch_buffer(workload); + if (ret) { + gvt_vgpu_err("fail to prepare_shadow_batch_buffer\n"); + goto err_unpin_mm; + } + + ret = prepare_shadow_wa_ctx(&workload->wa_ctx); + if (ret) { + gvt_vgpu_err("fail to prepare_shadow_wa_ctx\n"); + goto err_shadow_batch; + } + + if (!workload->emulate_schedule_in) + return 0; + + ctx[0] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 1); + ctx[1] = *get_desc_from_elsp_dwords(&workload->elsp_dwords, 0); - i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj); - i915_gem_object_put(wa_ctx->indirect_ctx.obj); + ret = emulate_execlist_schedule_in(&vgpu->execlist[ring_id], ctx); + if (!ret) + goto out; + else + gvt_vgpu_err("fail to emulate execlist schedule in\n"); + + release_shadow_wa_ctx(&workload->wa_ctx); +err_shadow_batch: + release_shadow_batch_buffer(workload); +err_unpin_mm: + intel_vgpu_unpin_mm(workload->shadow_mm); +out: + return ret; } static int complete_execlist_workload(struct intel_vgpu_workload *workload) @@ -511,8 +542,10 @@ static int complete_execlist_workload(struct intel_vgpu_workload *workload) gvt_dbg_el("complete workload %p status %d\n", workload, workload->status); - release_shadow_batch_buffer(workload); - release_shadow_wa_ctx(&workload->wa_ctx); + if (!workload->status) { + release_shadow_batch_buffer(workload); + release_shadow_wa_ctx(&workload->wa_ctx); + } if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) { /* if workload->status is not successful means HW GPU @@ -701,8 +734,7 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id, CACHELINE_BYTES; workload->wa_ctx.per_ctx.guest_gma = per_ctx & PER_CTX_ADDR_MASK; - - WARN_ON(workload->wa_ctx.indirect_ctx.size && !(per_ctx & 0x1)); + workload->wa_ctx.per_ctx.valid = per_ctx & 1; } if (emulate_schedule_in) @@ -820,10 +852,21 @@ static void clean_workloads(struct intel_vgpu *vgpu, unsigned long engine_mask) void intel_vgpu_clean_execlist(struct intel_vgpu *vgpu) { + enum intel_engine_id i; + struct intel_engine_cs *engine; + clean_workloads(vgpu, ALL_ENGINES); kmem_cache_destroy(vgpu->workloads); + + for_each_engine(engine, vgpu->gvt->dev_priv, i) { + kfree(vgpu->reserve_ring_buffer_va[i]); + vgpu->reserve_ring_buffer_va[i] = NULL; + vgpu->reserve_ring_buffer_size[i] = 0; + } + } +#define RESERVE_RING_BUFFER_SIZE ((1 * PAGE_SIZE)/8) int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) { enum intel_engine_id i; @@ -843,7 +886,26 @@ int intel_vgpu_init_execlist(struct intel_vgpu *vgpu) if (!vgpu->workloads) return -ENOMEM; + /* each ring has a shadow ring buffer until vgpu destroyed */ + for_each_engine(engine, vgpu->gvt->dev_priv, i) { + vgpu->reserve_ring_buffer_va[i] = + kmalloc(RESERVE_RING_BUFFER_SIZE, GFP_KERNEL); + if (!vgpu->reserve_ring_buffer_va[i]) { + gvt_vgpu_err("fail to alloc reserve ring buffer\n"); + goto out; + } + vgpu->reserve_ring_buffer_size[i] = RESERVE_RING_BUFFER_SIZE; + } return 0; +out: + for_each_engine(engine, vgpu->gvt->dev_priv, i) { + if (vgpu->reserve_ring_buffer_size[i]) { + kfree(vgpu->reserve_ring_buffer_va[i]); + vgpu->reserve_ring_buffer_va[i] = NULL; + vgpu->reserve_ring_buffer_size[i] = 0; + } + } + return -ENOMEM; } void intel_vgpu_reset_execlist(struct intel_vgpu *vgpu, diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index e6dfc3331f4b..2801d70579d8 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1647,14 +1647,13 @@ int intel_vgpu_pin_mm(struct intel_vgpu_mm *mm) if (WARN_ON(mm->type != INTEL_GVT_MM_PPGTT)) return 0; - atomic_inc(&mm->pincount); - if (!mm->shadowed) { ret = shadow_mm(mm); if (ret) return ret; } + atomic_inc(&mm->pincount); list_del_init(&mm->lru_list); list_add_tail(&mm->lru_list, &mm->vgpu->gvt->gtt.mm_lru_list_head); return 0; @@ -1972,7 +1971,7 @@ static int alloc_scratch_pages(struct intel_vgpu *vgpu, */ se.val64 |= _PAGE_PRESENT | _PAGE_RW; if (type == GTT_TYPE_PPGTT_PDE_PT) - se.val64 |= PPAT_CACHED_INDEX; + se.val64 |= PPAT_CACHED; for (i = 0; i < page_entry_num; i++) ops->set_entry(scratch_pt, &se, i, false, 0, vgpu); diff --git a/drivers/gpu/drm/i915/gvt/gvt.c b/drivers/gpu/drm/i915/gvt/gvt.c index c27c6838eaca..aaa347f8620c 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.c +++ b/drivers/gpu/drm/i915/gvt/gvt.c @@ -111,7 +111,7 @@ static void init_device_info(struct intel_gvt *gvt) if (IS_BROADWELL(gvt->dev_priv) || IS_SKYLAKE(gvt->dev_priv) || IS_KABYLAKE(gvt->dev_priv)) { info->max_support_vgpus = 8; - info->cfg_space_size = 256; + info->cfg_space_size = PCI_CFG_SPACE_EXP_SIZE; info->mmio_size = 2 * 1024 * 1024; info->mmio_bar = 0; info->gtt_start_offset = 8 * 1024 * 1024; diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 44b719eda8c4..9c2e7c0aa38f 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -80,6 +80,7 @@ struct intel_gvt_device_info { struct intel_vgpu_gm { u64 aperture_sz; u64 hidden_sz; + void *aperture_va; struct drm_mm_node low_gm_node; struct drm_mm_node high_gm_node; }; @@ -99,7 +100,6 @@ struct intel_vgpu_mmio { bool disable_warn_untrack; }; -#define INTEL_GVT_MAX_CFG_SPACE_SZ 256 #define INTEL_GVT_MAX_BAR_NUM 4 struct intel_vgpu_pci_bar { @@ -108,7 +108,7 @@ struct intel_vgpu_pci_bar { }; struct intel_vgpu_cfg_space { - unsigned char virtual_cfg_space[INTEL_GVT_MAX_CFG_SPACE_SZ]; + unsigned char virtual_cfg_space[PCI_CFG_SPACE_EXP_SIZE]; struct intel_vgpu_pci_bar bar[INTEL_GVT_MAX_BAR_NUM]; }; @@ -165,6 +165,9 @@ struct intel_vgpu { struct list_head workload_q_head[I915_NUM_ENGINES]; struct kmem_cache *workloads; atomic_t running_workload_num; + /* 1/2K for each reserve ring buffer */ + void *reserve_ring_buffer_va[I915_NUM_ENGINES]; + int reserve_ring_buffer_size[I915_NUM_ENGINES]; DECLARE_BITMAP(tlb_handle_pending, I915_NUM_ENGINES); struct i915_gem_context *shadow_ctx; DECLARE_BITMAP(shadow_ctx_desc_updated, I915_NUM_ENGINES); @@ -474,6 +477,13 @@ int intel_vgpu_emulate_cfg_read(struct intel_vgpu *vgpu, unsigned int offset, int intel_vgpu_emulate_cfg_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes); +static inline u64 intel_vgpu_get_bar_gpa(struct intel_vgpu *vgpu, int bar) +{ + /* We are 64bit bar. */ + return (*(u64 *)(vgpu->cfg_space.virtual_cfg_space + bar)) & + PCI_BASE_ADDRESS_MEM_MASK; +} + void intel_gvt_clean_opregion(struct intel_gvt *gvt); int intel_gvt_init_opregion(struct intel_gvt *gvt); diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 2294466dd415..a5bed2e71b92 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1429,18 +1429,7 @@ static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset, return 0; } -static int ring_timestamp_mmio_read(struct intel_vgpu *vgpu, - unsigned int offset, void *p_data, unsigned int bytes) -{ - struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; - - mmio_hw_access_pre(dev_priv); - vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset)); - mmio_hw_access_post(dev_priv); - return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes); -} - -static int instdone_mmio_read(struct intel_vgpu *vgpu, +static int mmio_read_from_hw(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; @@ -1589,6 +1578,8 @@ static int ring_reset_ctl_write(struct intel_vgpu *vgpu, MMIO_F(prefix(BLT_RING_BASE), s, f, am, rm, d, r, w); \ MMIO_F(prefix(GEN6_BSD_RING_BASE), s, f, am, rm, d, r, w); \ MMIO_F(prefix(VEBOX_RING_BASE), s, f, am, rm, d, r, w); \ + if (HAS_BSD2(dev_priv)) \ + MMIO_F(prefix(GEN8_BSD2_RING_BASE), s, f, am, rm, d, r, w); \ } while (0) #define MMIO_RING_D(prefix, d) \ @@ -1635,10 +1626,9 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) #undef RING_REG #define RING_REG(base) (base + 0x6c) - MMIO_RING_DFH(RING_REG, D_ALL, 0, instdone_mmio_read, NULL); - MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_ALL, instdone_mmio_read, NULL); + MMIO_RING_DFH(RING_REG, D_ALL, 0, mmio_read_from_hw, NULL); #undef RING_REG - MMIO_DH(GEN7_SC_INSTDONE, D_BDW_PLUS, instdone_mmio_read, NULL); + MMIO_DH(GEN7_SC_INSTDONE, D_BDW_PLUS, mmio_read_from_hw, NULL); MMIO_GM_RDR(0x2148, D_ALL, NULL, NULL); MMIO_GM_RDR(CCID, D_ALL, NULL, NULL); @@ -1648,7 +1638,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_RING_DFH(RING_TAIL, D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_RING_DFH(RING_HEAD, D_ALL, F_CMD_ACCESS, NULL, NULL); MMIO_RING_DFH(RING_CTL, D_ALL, F_CMD_ACCESS, NULL, NULL); - MMIO_RING_DFH(RING_ACTHD, D_ALL, F_CMD_ACCESS, NULL, NULL); + MMIO_RING_DFH(RING_ACTHD, D_ALL, F_CMD_ACCESS, mmio_read_from_hw, NULL); MMIO_RING_GM_RDR(RING_START, D_ALL, NULL, NULL); /* RING MODE */ @@ -1662,9 +1652,9 @@ static int init_generic_mmio_info(struct intel_gvt *gvt) MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS, - ring_timestamp_mmio_read, NULL); + mmio_read_from_hw, NULL); MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS, - ring_timestamp_mmio_read, NULL); + mmio_read_from_hw, NULL); MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK | F_CMD_ACCESS, @@ -2411,9 +2401,6 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) struct drm_i915_private *dev_priv = gvt->dev_priv; int ret; - MMIO_DFH(RING_IMR(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, NULL, - intel_vgpu_reg_imr_handler); - MMIO_DH(GEN8_GT_IMR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler); MMIO_DH(GEN8_GT_IER(0), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler); MMIO_DH(GEN8_GT_IIR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler); @@ -2476,68 +2463,34 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) MMIO_DH(GEN8_MASTER_IRQ, D_BDW_PLUS, NULL, intel_vgpu_reg_master_irq_handler); - MMIO_DFH(RING_HWSTAM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, - F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(0x1c134, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); - - MMIO_DFH(RING_TAIL(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, - NULL, NULL); - MMIO_DFH(RING_HEAD(GEN8_BSD2_RING_BASE), D_BDW_PLUS, - F_CMD_ACCESS, NULL, NULL); - MMIO_GM_RDR(RING_START(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL); - MMIO_DFH(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, - NULL, NULL); - MMIO_DFH(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS, - F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS, - F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, - ring_mode_mmio_write); - MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS, - F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS, - F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, - ring_timestamp_mmio_read, NULL); - - MMIO_RING_DFH(RING_ACTHD_UDW, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); + MMIO_RING_DFH(RING_ACTHD_UDW, D_BDW_PLUS, F_CMD_ACCESS, + mmio_read_from_hw, NULL); #define RING_REG(base) (base + 0xd0) MMIO_RING_F(RING_REG, 4, F_RO, 0, ~_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET), D_BDW_PLUS, NULL, ring_reset_ctl_write); - MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0, - ~_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET), D_BDW_PLUS, NULL, - ring_reset_ctl_write); #undef RING_REG #define RING_REG(base) (base + 0x230) MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, elsp_mmio_write); - MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, elsp_mmio_write); #undef RING_REG #define RING_REG(base) (base + 0x234) MMIO_RING_F(RING_REG, 8, F_RO | F_CMD_ACCESS, 0, ~0, D_BDW_PLUS, NULL, NULL); - MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO | F_CMD_ACCESS, 0, - ~0LL, D_BDW_PLUS, NULL, NULL); #undef RING_REG #define RING_REG(base) (base + 0x244) MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); - MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, - NULL, NULL); #undef RING_REG #define RING_REG(base) (base + 0x370) MMIO_RING_F(RING_REG, 48, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL); - MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 48, F_RO, 0, ~0, D_BDW_PLUS, - NULL, NULL); #undef RING_REG #define RING_REG(base) (base + 0x3a0) MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_MODE_MASK, NULL, NULL); - MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, NULL, NULL); #undef RING_REG MMIO_D(PIPEMISC(PIPE_A), D_BDW_PLUS); @@ -2557,11 +2510,9 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt) #define RING_REG(base) (base + 0x270) MMIO_RING_F(RING_REG, 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL); - MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL); #undef RING_REG MMIO_RING_GM_RDR(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL); - MMIO_GM_RDR(RING_HWS_PGA(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL); MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL); @@ -2849,7 +2800,6 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_D(0x65f08, D_SKL | D_KBL); MMIO_D(0x320f0, D_SKL | D_KBL); - MMIO_DFH(_REG_VCS2_EXCC, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL); MMIO_D(0x70034, D_SKL_PLUS); MMIO_D(0x71034, D_SKL_PLUS); MMIO_D(0x72034, D_SKL_PLUS); diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 83e88c70272a..96060920a6fe 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -609,21 +609,20 @@ static void intel_vgpu_release_work(struct work_struct *work) __intel_vgpu_release(vgpu); } -static uint64_t intel_vgpu_get_bar0_addr(struct intel_vgpu *vgpu) +static uint64_t intel_vgpu_get_bar_addr(struct intel_vgpu *vgpu, int bar) { u32 start_lo, start_hi; u32 mem_type; - int pos = PCI_BASE_ADDRESS_0; - start_lo = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + pos)) & + start_lo = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + bar)) & PCI_BASE_ADDRESS_MEM_MASK; - mem_type = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + pos)) & + mem_type = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space + bar)) & PCI_BASE_ADDRESS_MEM_TYPE_MASK; switch (mem_type) { case PCI_BASE_ADDRESS_MEM_TYPE_64: start_hi = (*(u32 *)(vgpu->cfg_space.virtual_cfg_space - + pos + 4)); + + bar + 4)); break; case PCI_BASE_ADDRESS_MEM_TYPE_32: case PCI_BASE_ADDRESS_MEM_TYPE_1M: @@ -637,6 +636,21 @@ static uint64_t intel_vgpu_get_bar0_addr(struct intel_vgpu *vgpu) return ((u64)start_hi << 32) | start_lo; } +static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, uint64_t off, + void *buf, unsigned int count, bool is_write) +{ + uint64_t bar_start = intel_vgpu_get_bar_addr(vgpu, bar); + int ret; + + if (is_write) + ret = intel_gvt_ops->emulate_mmio_write(vgpu, + bar_start + off, buf, count); + else + ret = intel_gvt_ops->emulate_mmio_read(vgpu, + bar_start + off, buf, count); + return ret; +} + static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, size_t count, loff_t *ppos, bool is_write) { @@ -661,20 +675,14 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, buf, count); break; case VFIO_PCI_BAR0_REGION_INDEX: - case VFIO_PCI_BAR1_REGION_INDEX: - if (is_write) { - uint64_t bar0_start = intel_vgpu_get_bar0_addr(vgpu); - - ret = intel_gvt_ops->emulate_mmio_write(vgpu, - bar0_start + pos, buf, count); - } else { - uint64_t bar0_start = intel_vgpu_get_bar0_addr(vgpu); - - ret = intel_gvt_ops->emulate_mmio_read(vgpu, - bar0_start + pos, buf, count); - } + ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_0, pos, + buf, count, is_write); break; case VFIO_PCI_BAR2_REGION_INDEX: + ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_2, pos, + buf, count, is_write); + break; + case VFIO_PCI_BAR1_REGION_INDEX: case VFIO_PCI_BAR3_REGION_INDEX: case VFIO_PCI_BAR4_REGION_INDEX: case VFIO_PCI_BAR5_REGION_INDEX: @@ -970,7 +978,7 @@ static long intel_vgpu_ioctl(struct mdev_device *mdev, unsigned int cmd, switch (info.index) { case VFIO_PCI_CONFIG_REGION_INDEX: info.offset = VFIO_PCI_INDEX_TO_OFFSET(info.index); - info.size = INTEL_GVT_MAX_CFG_SPACE_SZ; + info.size = vgpu->gvt->device_info.cfg_space_size; info.flags = VFIO_REGION_INFO_FLAG_READ | VFIO_REGION_INFO_FLAG_WRITE; break; diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 980ec8906b1e..1e1310f50289 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -45,8 +45,7 @@ */ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa) { - u64 gttmmio_gpa = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_0) & - ~GENMASK(3, 0); + u64 gttmmio_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_0); return gpa - gttmmio_gpa; } @@ -57,6 +56,38 @@ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa) (reg >= gvt->device_info.gtt_start_offset \ && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt)) +static bool vgpu_gpa_is_aperture(struct intel_vgpu *vgpu, uint64_t gpa) +{ + u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2); + u64 aperture_sz = vgpu_aperture_sz(vgpu); + + return gpa >= aperture_gpa && gpa < aperture_gpa + aperture_sz; +} + +static int vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t gpa, + void *pdata, unsigned int size, bool is_read) +{ + u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2); + u64 offset = gpa - aperture_gpa; + + if (!vgpu_gpa_is_aperture(vgpu, gpa + size - 1)) { + gvt_vgpu_err("Aperture rw out of range, offset %llx, size %d\n", + offset, size); + return -EINVAL; + } + + if (!vgpu->gm.aperture_va) { + gvt_vgpu_err("BAR is not enabled\n"); + return -ENXIO; + } + + if (is_read) + memcpy(pdata, vgpu->gm.aperture_va + offset, size); + else + memcpy(vgpu->gm.aperture_va + offset, pdata, size); + return 0; +} + static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa, void *p_data, unsigned int bytes, bool read) { @@ -133,6 +164,12 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa, } mutex_lock(&gvt->lock); + if (vgpu_gpa_is_aperture(vgpu, pa)) { + ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, true); + mutex_unlock(&gvt->lock); + return ret; + } + if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { struct intel_vgpu_guest_page *gp; @@ -224,6 +261,12 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa, mutex_lock(&gvt->lock); + if (vgpu_gpa_is_aperture(vgpu, pa)) { + ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, false); + mutex_unlock(&gvt->lock); + return ret; + } + if (atomic_read(&vgpu->gtt.n_write_protected_guest_page)) { struct intel_vgpu_guest_page *gp; diff --git a/drivers/gpu/drm/i915/gvt/reg.h b/drivers/gpu/drm/i915/gvt/reg.h index fbd023a16f18..7d01c77a0f7a 100644 --- a/drivers/gpu/drm/i915/gvt/reg.h +++ b/drivers/gpu/drm/i915/gvt/reg.h @@ -54,9 +54,6 @@ #define VGT_SPRSTRIDE(pipe) _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B) -#define _REG_VECS_EXCC 0x1A028 -#define _REG_VCS2_EXCC 0x1c028 - #define _REG_701C0(pipe, plane) (0x701c0 + pipe * 0x1000 + (plane - 1) * 0x100) #define _REG_701C4(pipe, plane) (0x701c4 + pipe * 0x1000 + (plane - 1) * 0x100) diff --git a/drivers/gpu/drm/i915/gvt/render.c b/drivers/gpu/drm/i915/gvt/render.c index 2ea542257f03..6d066cf35478 100644 --- a/drivers/gpu/drm/i915/gvt/render.c +++ b/drivers/gpu/drm/i915/gvt/render.c @@ -293,7 +293,7 @@ static void switch_mmio_to_vgpu(struct intel_vgpu *vgpu, int ring_id) */ if (mmio->in_context && ((ctx_ctrl & inhibit_mask) != inhibit_mask) && - i915.enable_execlists) + i915_modparams.enable_execlists) continue; if (mmio->mask) diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index 436377da41ba..03532dfc0cd5 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -308,20 +308,8 @@ static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu) static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu) { - struct intel_gvt_workload_scheduler *scheduler = &vgpu->gvt->scheduler; - int ring_id; - kfree(vgpu->sched_data); vgpu->sched_data = NULL; - - spin_lock_bh(&scheduler->mmio_context_lock); - for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) { - if (scheduler->engine_owner[ring_id] == vgpu) { - intel_gvt_switch_mmio(vgpu, NULL, ring_id); - scheduler->engine_owner[ring_id] = NULL; - } - } - spin_unlock_bh(&scheduler->mmio_context_lock); } static void tbs_sched_start_schedule(struct intel_vgpu *vgpu) @@ -388,6 +376,7 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) { struct intel_gvt_workload_scheduler *scheduler = &vgpu->gvt->scheduler; + int ring_id; gvt_dbg_core("vgpu%d: stop schedule\n", vgpu->id); @@ -401,4 +390,13 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) scheduler->need_reschedule = true; scheduler->current_vgpu = NULL; } + + spin_lock_bh(&scheduler->mmio_context_lock); + for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) { + if (scheduler->engine_owner[ring_id] == vgpu) { + intel_gvt_switch_mmio(vgpu, NULL, ring_id); + scheduler->engine_owner[ring_id] = NULL; + } + } + spin_unlock_bh(&scheduler->mmio_context_lock); } diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 391800d2067b..f6ded475bb2c 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -87,7 +87,7 @@ static int populate_shadow_context(struct intel_vgpu_workload *workload) return -EINVAL; } - page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i); + page = i915_gem_object_get_page(ctx_obj, LRC_HEADER_PAGES + i); dst = kmap(page); intel_gvt_hypervisor_read_gpa(vgpu, context_gpa, dst, GTT_PAGE_SIZE); @@ -174,6 +174,7 @@ static int shadow_context_status_change(struct notifier_block *nb, atomic_set(&workload->shadow_ctx_active, 1); break; case INTEL_CONTEXT_SCHEDULE_OUT: + case INTEL_CONTEXT_SCHEDULE_PREEMPTED: atomic_set(&workload->shadow_ctx_active, 0); break; default: @@ -201,6 +202,43 @@ static void shadow_context_descriptor_update(struct i915_gem_context *ctx, ce->lrc_desc = desc; } +static int copy_workload_to_ring_buffer(struct intel_vgpu_workload *workload) +{ + struct intel_vgpu *vgpu = workload->vgpu; + void *shadow_ring_buffer_va; + u32 *cs; + + /* allocate shadow ring buffer */ + cs = intel_ring_begin(workload->req, workload->rb_len / sizeof(u32)); + if (IS_ERR(cs)) { + gvt_vgpu_err("fail to alloc size =%ld shadow ring buffer\n", + workload->rb_len); + return PTR_ERR(cs); + } + + shadow_ring_buffer_va = workload->shadow_ring_buffer_va; + + /* get shadow ring buffer va */ + workload->shadow_ring_buffer_va = cs; + + memcpy(cs, shadow_ring_buffer_va, + workload->rb_len); + + cs += workload->rb_len / sizeof(u32); + intel_ring_advance(workload->req, cs); + + return 0; +} + +void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx) +{ + if (!wa_ctx->indirect_ctx.obj) + return; + + i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj); + i915_gem_object_put(wa_ctx->indirect_ctx.obj); +} + /** * intel_gvt_scan_and_shadow_workload - audit the workload by scanning and * shadow it as well, include ringbuffer,wa_ctx and ctx. @@ -214,8 +252,10 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) int ring_id = workload->ring_id; struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; + struct intel_engine_cs *engine = dev_priv->engine[ring_id]; struct drm_i915_gem_request *rq; struct intel_vgpu *vgpu = workload->vgpu; + struct intel_ring *ring; int ret; lockdep_assert_held(&dev_priv->drm.struct_mutex); @@ -231,35 +271,56 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload) shadow_context_descriptor_update(shadow_ctx, dev_priv->engine[ring_id]); - rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); - if (IS_ERR(rq)) { - gvt_vgpu_err("fail to allocate gem request\n"); - ret = PTR_ERR(rq); - goto out; - } - - gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq); - - workload->req = i915_gem_request_get(rq); - ret = intel_gvt_scan_and_shadow_ringbuffer(workload); if (ret) - goto out; + goto err_scan; if ((workload->ring_id == RCS) && (workload->wa_ctx.indirect_ctx.size != 0)) { ret = intel_gvt_scan_and_shadow_wa_ctx(&workload->wa_ctx); if (ret) - goto out; + goto err_scan; + } + + /* pin shadow context by gvt even the shadow context will be pinned + * when i915 alloc request. That is because gvt will update the guest + * context from shadow context when workload is completed, and at that + * moment, i915 may already unpined the shadow context to make the + * shadow_ctx pages invalid. So gvt need to pin itself. After update + * the guest context, gvt can unpin the shadow_ctx safely. + */ + ring = engine->context_pin(engine, shadow_ctx); + if (IS_ERR(ring)) { + ret = PTR_ERR(ring); + gvt_vgpu_err("fail to pin shadow context\n"); + goto err_shadow; } ret = populate_shadow_context(workload); if (ret) - goto out; + goto err_unpin; + rq = i915_gem_request_alloc(dev_priv->engine[ring_id], shadow_ctx); + if (IS_ERR(rq)) { + gvt_vgpu_err("fail to allocate gem request\n"); + ret = PTR_ERR(rq); + goto err_unpin; + } + + gvt_dbg_sched("ring id %d get i915 gem request %p\n", ring_id, rq); + + workload->req = i915_gem_request_get(rq); + ret = copy_workload_to_ring_buffer(workload); + if (ret) + goto err_unpin; workload->shadowed = true; + return 0; -out: +err_unpin: + engine->context_unpin(engine, shadow_ctx); +err_shadow: + release_shadow_wa_ctx(&workload->wa_ctx); +err_scan: return ret; } @@ -269,8 +330,6 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) struct i915_gem_context *shadow_ctx = workload->vgpu->shadow_ctx; struct drm_i915_private *dev_priv = workload->vgpu->gvt->dev_priv; struct intel_engine_cs *engine = dev_priv->engine[ring_id]; - struct intel_vgpu *vgpu = workload->vgpu; - struct intel_ring *ring; int ret = 0; gvt_dbg_sched("ring id %d prepare to dispatch workload %p\n", @@ -284,22 +343,10 @@ static int dispatch_workload(struct intel_vgpu_workload *workload) if (workload->prepare) { ret = workload->prepare(workload); - if (ret) + if (ret) { + engine->context_unpin(engine, shadow_ctx); goto out; - } - - /* pin shadow context by gvt even the shadow context will be pinned - * when i915 alloc request. That is because gvt will update the guest - * context from shadow context when workload is completed, and at that - * moment, i915 may already unpined the shadow context to make the - * shadow_ctx pages invalid. So gvt need to pin itself. After update - * the guest context, gvt can unpin the shadow_ctx safely. - */ - ring = engine->context_pin(engine, shadow_ctx); - if (IS_ERR(ring)) { - ret = PTR_ERR(ring); - gvt_vgpu_err("fail to pin shadow context\n"); - goto out; + } } out: @@ -408,7 +455,7 @@ static void update_guest_context(struct intel_vgpu_workload *workload) return; } - page = i915_gem_object_get_page(ctx_obj, LRC_PPHWSP_PN + i); + page = i915_gem_object_get_page(ctx_obj, LRC_HEADER_PAGES + i); src = kmap(page); intel_gvt_hypervisor_write_gpa(vgpu, context_gpa, src, GTT_PAGE_SIZE); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 0d431a968a32..2d694f6c0907 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -68,6 +68,7 @@ struct shadow_indirect_ctx { struct shadow_per_ctx { unsigned long guest_gma; unsigned long shadow_gma; + unsigned valid; }; struct intel_shadow_wa_ctx { @@ -140,4 +141,5 @@ int intel_vgpu_init_gvt_context(struct intel_vgpu *vgpu); void intel_vgpu_clean_gvt_context(struct intel_vgpu *vgpu); +void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx); #endif diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e4d4b6b41e26..c65e381b85f3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -30,6 +30,7 @@ #include <linux/sort.h> #include <linux/sched/mm.h> #include "intel_drv.h" +#include "i915_guc_submission.h" static inline struct drm_i915_private *node_to_i915(struct drm_info_node *node) { @@ -67,7 +68,7 @@ static int i915_capabilities(struct seq_file *m, void *data) #undef PRINT_FLAG kernel_param_lock(THIS_MODULE); -#define PRINT_PARAM(T, x) seq_print_param(m, #x, #T, &i915.x); +#define PRINT_PARAM(T, x, ...) seq_print_param(m, #x, #T, &i915_modparams.x); I915_PARAMS_FOR_EACH(PRINT_PARAM); #undef PRINT_PARAM kernel_param_unlock(THIS_MODULE); @@ -82,7 +83,7 @@ static char get_active_flag(struct drm_i915_gem_object *obj) static char get_pin_flag(struct drm_i915_gem_object *obj) { - return obj->pin_display ? 'p' : ' '; + return obj->pin_global ? 'p' : ' '; } static char get_tiling_flag(struct drm_i915_gem_object *obj) @@ -97,7 +98,7 @@ static char get_tiling_flag(struct drm_i915_gem_object *obj) static char get_global_flag(struct drm_i915_gem_object *obj) { - return !list_empty(&obj->userfault_link) ? 'g' : ' '; + return obj->userfault_count ? 'g' : ' '; } static char get_pin_mapped_flag(struct drm_i915_gem_object *obj) @@ -118,6 +119,36 @@ static u64 i915_gem_obj_total_ggtt_size(struct drm_i915_gem_object *obj) return size; } +static const char * +stringify_page_sizes(unsigned int page_sizes, char *buf, size_t len) +{ + size_t x = 0; + + switch (page_sizes) { + case 0: + return ""; + case I915_GTT_PAGE_SIZE_4K: + return "4K"; + case I915_GTT_PAGE_SIZE_64K: + return "64K"; + case I915_GTT_PAGE_SIZE_2M: + return "2M"; + default: + if (!buf) + return "M"; + + if (page_sizes & I915_GTT_PAGE_SIZE_2M) + x += snprintf(buf + x, len - x, "2M, "); + if (page_sizes & I915_GTT_PAGE_SIZE_64K) + x += snprintf(buf + x, len - x, "64K, "); + if (page_sizes & I915_GTT_PAGE_SIZE_4K) + x += snprintf(buf + x, len - x, "4K, "); + buf[x-2] = '\0'; + + return buf; + } +} + static void describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) { @@ -149,15 +180,16 @@ describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) pin_count++; } seq_printf(m, " (pinned x %d)", pin_count); - if (obj->pin_display) - seq_printf(m, " (display)"); + if (obj->pin_global) + seq_printf(m, " (global)"); list_for_each_entry(vma, &obj->vma_list, obj_link) { if (!drm_mm_node_allocated(&vma->node)) continue; - seq_printf(m, " (%sgtt offset: %08llx, size: %08llx", + seq_printf(m, " (%sgtt offset: %08llx, size: %08llx, pages: %s", i915_vma_is_ggtt(vma) ? "g" : "pp", - vma->node.start, vma->node.size); + vma->node.start, vma->node.size, + stringify_page_sizes(vma->page_sizes.gtt, NULL, 0)); if (i915_vma_is_ggtt(vma)) { switch (vma->ggtt_view.type) { case I915_GGTT_VIEW_NORMAL: @@ -239,7 +271,9 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) goto out; total_obj_size = total_gtt_size = count = 0; - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { + + spin_lock(&dev_priv->mm.obj_lock); + list_for_each_entry(obj, &dev_priv->mm.bound_list, mm.link) { if (count == total) break; @@ -251,7 +285,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) total_gtt_size += i915_gem_obj_total_ggtt_size(obj); } - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) { + list_for_each_entry(obj, &dev_priv->mm.unbound_list, mm.link) { if (count == total) break; @@ -261,6 +295,7 @@ static int i915_gem_stolen_list_info(struct seq_file *m, void *data) objects[count++] = obj; total_obj_size += obj->base.size; } + spin_unlock(&dev_priv->mm.obj_lock); sort(objects, count, sizeof(*objects), obj_rank_by_stolen, NULL); @@ -402,10 +437,12 @@ static int i915_gem_object_info(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_device *dev = &dev_priv->drm; struct i915_ggtt *ggtt = &dev_priv->ggtt; - u32 count, mapped_count, purgeable_count, dpy_count; - u64 size, mapped_size, purgeable_size, dpy_size; + u32 count, mapped_count, purgeable_count, dpy_count, huge_count; + u64 size, mapped_size, purgeable_size, dpy_size, huge_size; struct drm_i915_gem_object *obj; + unsigned int page_sizes = 0; struct drm_file *file; + char buf[80]; int ret; ret = mutex_lock_interruptible(&dev->struct_mutex); @@ -419,7 +456,10 @@ static int i915_gem_object_info(struct seq_file *m, void *data) size = count = 0; mapped_size = mapped_count = 0; purgeable_size = purgeable_count = 0; - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) { + huge_size = huge_count = 0; + + spin_lock(&dev_priv->mm.obj_lock); + list_for_each_entry(obj, &dev_priv->mm.unbound_list, mm.link) { size += obj->base.size; ++count; @@ -432,15 +472,21 @@ static int i915_gem_object_info(struct seq_file *m, void *data) mapped_count++; mapped_size += obj->base.size; } + + if (obj->mm.page_sizes.sg > I915_GTT_PAGE_SIZE) { + huge_count++; + huge_size += obj->base.size; + page_sizes |= obj->mm.page_sizes.sg; + } } seq_printf(m, "%u unbound objects, %llu bytes\n", count, size); size = count = dpy_size = dpy_count = 0; - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { + list_for_each_entry(obj, &dev_priv->mm.bound_list, mm.link) { size += obj->base.size; ++count; - if (obj->pin_display) { + if (obj->pin_global) { dpy_size += obj->base.size; ++dpy_count; } @@ -454,18 +500,33 @@ static int i915_gem_object_info(struct seq_file *m, void *data) mapped_count++; mapped_size += obj->base.size; } + + if (obj->mm.page_sizes.sg > I915_GTT_PAGE_SIZE) { + huge_count++; + huge_size += obj->base.size; + page_sizes |= obj->mm.page_sizes.sg; + } } + spin_unlock(&dev_priv->mm.obj_lock); + seq_printf(m, "%u bound objects, %llu bytes\n", count, size); seq_printf(m, "%u purgeable objects, %llu bytes\n", purgeable_count, purgeable_size); seq_printf(m, "%u mapped objects, %llu bytes\n", mapped_count, mapped_size); - seq_printf(m, "%u display objects (pinned), %llu bytes\n", + seq_printf(m, "%u huge-paged objects (%s) %llu bytes\n", + huge_count, + stringify_page_sizes(page_sizes, buf, sizeof(buf)), + huge_size); + seq_printf(m, "%u display objects (globally pinned), %llu bytes\n", dpy_count, dpy_size); seq_printf(m, "%llu [%llu] gtt total\n", ggtt->base.total, ggtt->mappable_end); + seq_printf(m, "Supported page sizes: %s\n", + stringify_page_sizes(INTEL_INFO(dev_priv)->page_sizes, + buf, sizeof(buf))); seq_putc(m, '\n'); print_batch_pool_stats(m, dev_priv); @@ -514,32 +575,46 @@ static int i915_gem_gtt_info(struct seq_file *m, void *data) struct drm_info_node *node = m->private; struct drm_i915_private *dev_priv = node_to_i915(node); struct drm_device *dev = &dev_priv->drm; - bool show_pin_display_only = !!node->info_ent->data; + struct drm_i915_gem_object **objects; struct drm_i915_gem_object *obj; u64 total_obj_size, total_gtt_size; + unsigned long nobject, n; int count, ret; + nobject = READ_ONCE(dev_priv->mm.object_count); + objects = kvmalloc_array(nobject, sizeof(*objects), GFP_KERNEL); + if (!objects) + return -ENOMEM; + ret = mutex_lock_interruptible(&dev->struct_mutex); if (ret) return ret; - total_obj_size = total_gtt_size = count = 0; - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { - if (show_pin_display_only && !obj->pin_display) - continue; + count = 0; + spin_lock(&dev_priv->mm.obj_lock); + list_for_each_entry(obj, &dev_priv->mm.bound_list, mm.link) { + objects[count++] = obj; + if (count == nobject) + break; + } + spin_unlock(&dev_priv->mm.obj_lock); + + total_obj_size = total_gtt_size = 0; + for (n = 0; n < count; n++) { + obj = objects[n]; seq_puts(m, " "); describe_obj(m, obj); seq_putc(m, '\n'); total_obj_size += obj->base.size; total_gtt_size += i915_gem_obj_total_ggtt_size(obj); - count++; } mutex_unlock(&dev->struct_mutex); seq_printf(m, "Total %d objects, %llu bytes, %llu GTT size\n", count, total_obj_size, total_gtt_size); + kvfree(objects); return 0; } @@ -589,54 +664,6 @@ static int i915_gem_batch_pool_info(struct seq_file *m, void *data) return 0; } -static void print_request(struct seq_file *m, - struct drm_i915_gem_request *rq, - const char *prefix) -{ - seq_printf(m, "%s%x [%x:%x] prio=%d @ %dms: %s\n", prefix, - rq->global_seqno, rq->ctx->hw_id, rq->fence.seqno, - rq->priotree.priority, - jiffies_to_msecs(jiffies - rq->emitted_jiffies), - rq->timeline->common->name); -} - -static int i915_gem_request_info(struct seq_file *m, void *data) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct drm_i915_gem_request *req; - struct intel_engine_cs *engine; - enum intel_engine_id id; - int ret, any; - - ret = mutex_lock_interruptible(&dev->struct_mutex); - if (ret) - return ret; - - any = 0; - for_each_engine(engine, dev_priv, id) { - int count; - - count = 0; - list_for_each_entry(req, &engine->timeline->requests, link) - count++; - if (count == 0) - continue; - - seq_printf(m, "%s requests: %d\n", engine->name, count); - list_for_each_entry(req, &engine->timeline->requests, link) - print_request(m, req, " "); - - any++; - } - mutex_unlock(&dev->struct_mutex); - - if (any == 0) - seq_puts(m, "No requests\n"); - - return 0; -} - static void i915_ring_seqno_info(struct seq_file *m, struct intel_engine_cs *engine) { @@ -1026,6 +1053,7 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_next_seqno_fops, static int i915_frequency_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct intel_rps *rps = &dev_priv->gt_pm.rps; int ret = 0; intel_runtime_pm_get(dev_priv); @@ -1041,9 +1069,19 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "Current P-state: %d\n", (rgvstat & MEMSTAT_PSTATE_MASK) >> MEMSTAT_PSTATE_SHIFT); } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - u32 freq_sts; + u32 rpmodectl, freq_sts; + + mutex_lock(&dev_priv->pcu_lock); + + rpmodectl = I915_READ(GEN6_RP_CONTROL); + seq_printf(m, "Video Turbo Mode: %s\n", + yesno(rpmodectl & GEN6_RP_MEDIA_TURBO)); + seq_printf(m, "HW control enabled: %s\n", + yesno(rpmodectl & GEN6_RP_ENABLE)); + seq_printf(m, "SW control enabled: %s\n", + yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == + GEN6_RP_MEDIA_SW_MODE)); - mutex_lock(&dev_priv->rps.hw_lock); freq_sts = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); seq_printf(m, "PUNIT_REG_GPU_FREQ_STS: 0x%08x\n", freq_sts); seq_printf(m, "DDR freq: %d MHz\n", dev_priv->mem_freq); @@ -1052,21 +1090,21 @@ static int i915_frequency_info(struct seq_file *m, void *unused) intel_gpu_freq(dev_priv, (freq_sts >> 8) & 0xff)); seq_printf(m, "current GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); + intel_gpu_freq(dev_priv, rps->cur_freq)); seq_printf(m, "max GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); + intel_gpu_freq(dev_priv, rps->max_freq)); seq_printf(m, "min GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.min_freq)); + intel_gpu_freq(dev_priv, rps->min_freq)); seq_printf(m, "idle GPU freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq)); + intel_gpu_freq(dev_priv, rps->idle_freq)); seq_printf(m, "efficient (RPe) frequency: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); - mutex_unlock(&dev_priv->rps.hw_lock); + intel_gpu_freq(dev_priv, rps->efficient_freq)); + mutex_unlock(&dev_priv->pcu_lock); } else if (INTEL_GEN(dev_priv) >= 6) { u32 rp_state_limits; u32 gt_perf_status; @@ -1136,10 +1174,17 @@ static int i915_frequency_info(struct seq_file *m, void *unused) pm_iir = I915_READ(GEN8_GT_IIR(2)); pm_mask = I915_READ(GEN6_PMINTRMSK); } + seq_printf(m, "Video Turbo Mode: %s\n", + yesno(rpmodectl & GEN6_RP_MEDIA_TURBO)); + seq_printf(m, "HW control enabled: %s\n", + yesno(rpmodectl & GEN6_RP_ENABLE)); + seq_printf(m, "SW control enabled: %s\n", + yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == + GEN6_RP_MEDIA_SW_MODE)); seq_printf(m, "PM IER=0x%08x IMR=0x%08x ISR=0x%08x IIR=0x%08x, MASK=0x%08x\n", pm_ier, pm_imr, pm_isr, pm_iir, pm_mask); seq_printf(m, "pm_intrmsk_mbz: 0x%08x\n", - dev_priv->rps.pm_intrmsk_mbz); + rps->pm_intrmsk_mbz); seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status); seq_printf(m, "Render p-state ratio: %d\n", (gt_perf_status & (INTEL_GEN(dev_priv) >= 9 ? 0x1ff00 : 0xff00)) >> 8); @@ -1159,8 +1204,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) rpcurup, GT_PM_INTERVAL_TO_US(dev_priv, rpcurup)); seq_printf(m, "RP PREV UP: %d (%dus)\n", rpprevup, GT_PM_INTERVAL_TO_US(dev_priv, rpprevup)); - seq_printf(m, "Up threshold: %d%%\n", - dev_priv->rps.up_threshold); + seq_printf(m, "Up threshold: %d%%\n", rps->up_threshold); seq_printf(m, "RP CUR DOWN EI: %d (%dus)\n", rpdownei, GT_PM_INTERVAL_TO_US(dev_priv, rpdownei)); @@ -1168,8 +1212,7 @@ static int i915_frequency_info(struct seq_file *m, void *unused) rpcurdown, GT_PM_INTERVAL_TO_US(dev_priv, rpcurdown)); seq_printf(m, "RP PREV DOWN: %d (%dus)\n", rpprevdown, GT_PM_INTERVAL_TO_US(dev_priv, rpprevdown)); - seq_printf(m, "Down threshold: %d%%\n", - dev_priv->rps.down_threshold); + seq_printf(m, "Down threshold: %d%%\n", rps->down_threshold); max_freq = (IS_GEN9_LP(dev_priv) ? rp_state_cap >> 0 : rp_state_cap >> 16) & 0xff; @@ -1191,22 +1234,22 @@ static int i915_frequency_info(struct seq_file *m, void *unused) seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n", intel_gpu_freq(dev_priv, max_freq)); seq_printf(m, "Max overclocked frequency: %dMHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); + intel_gpu_freq(dev_priv, rps->max_freq)); seq_printf(m, "Current freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); + intel_gpu_freq(dev_priv, rps->cur_freq)); seq_printf(m, "Actual freq: %d MHz\n", cagf); seq_printf(m, "Idle freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq)); + intel_gpu_freq(dev_priv, rps->idle_freq)); seq_printf(m, "Min freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.min_freq)); + intel_gpu_freq(dev_priv, rps->min_freq)); seq_printf(m, "Boost freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.boost_freq)); + intel_gpu_freq(dev_priv, rps->boost_freq)); seq_printf(m, "Max freq: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); + intel_gpu_freq(dev_priv, rps->max_freq)); seq_printf(m, "efficient (RPe) frequency: %d MHz\n", - intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq)); + intel_gpu_freq(dev_priv, rps->efficient_freq)); } else { seq_puts(m, "no P-state info available\n"); } @@ -1267,7 +1310,7 @@ static int i915_hangcheck_info(struct seq_file *m, void *unused) if (waitqueue_active(&dev_priv->gpu_error.reset_queue)) seq_puts(m, "struct_mutex blocked for reset\n"); - if (!i915.enable_hangcheck) { + if (!i915_modparams.enable_hangcheck) { seq_puts(m, "Hangcheck disabled\n"); return 0; } @@ -1422,6 +1465,9 @@ static int i915_forcewake_domains(struct seq_file *m, void *data) struct intel_uncore_forcewake_domain *fw_domain; unsigned int tmp; + seq_printf(m, "user.bypass_count = %u\n", + i915->uncore.user_forcewake.count); + for_each_fw_domain(fw_domain, i915, tmp) seq_printf(m, "%s.wake_count = %u\n", intel_uncore_forcewake_domain_to_str(fw_domain->id), @@ -1444,21 +1490,11 @@ static void print_rc6_res(struct seq_file *m, static int vlv_drpc_info(struct seq_file *m) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - u32 rpmodectl1, rcctl1, pw_status; + u32 rcctl1, pw_status; pw_status = I915_READ(VLV_GTLC_PW_STATUS); - rpmodectl1 = I915_READ(GEN6_RP_CONTROL); rcctl1 = I915_READ(GEN6_RC_CONTROL); - seq_printf(m, "Video Turbo Mode: %s\n", - yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO)); - seq_printf(m, "Turbo enabled: %s\n", - yesno(rpmodectl1 & GEN6_RP_ENABLE)); - seq_printf(m, "HW control enabled: %s\n", - yesno(rpmodectl1 & GEN6_RP_ENABLE)); - seq_printf(m, "SW control enabled: %s\n", - yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) == - GEN6_RP_MEDIA_SW_MODE)); seq_printf(m, "RC6 Enabled: %s\n", yesno(rcctl1 & (GEN7_RC_CTL_TO_MODE | GEN6_RC_CTL_EI_MODE(1)))); @@ -1476,7 +1512,7 @@ static int vlv_drpc_info(struct seq_file *m) static int gen6_drpc_info(struct seq_file *m) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - u32 rpmodectl1, gt_core_status, rcctl1, rc6vids = 0; + u32 gt_core_status, rcctl1, rc6vids = 0; u32 gen9_powergate_enable = 0, gen9_powergate_status = 0; unsigned forcewake_count; int count = 0; @@ -1495,24 +1531,16 @@ static int gen6_drpc_info(struct seq_file *m) gt_core_status = I915_READ_FW(GEN6_GT_CORE_STATUS); trace_i915_reg_rw(false, GEN6_GT_CORE_STATUS, gt_core_status, 4, true); - rpmodectl1 = I915_READ(GEN6_RP_CONTROL); rcctl1 = I915_READ(GEN6_RC_CONTROL); if (INTEL_GEN(dev_priv) >= 9) { gen9_powergate_enable = I915_READ(GEN9_PG_ENABLE); gen9_powergate_status = I915_READ(GEN9_PWRGT_DOMAIN_STATUS); } - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); - seq_printf(m, "Video Turbo Mode: %s\n", - yesno(rpmodectl1 & GEN6_RP_MEDIA_TURBO)); - seq_printf(m, "HW control enabled: %s\n", - yesno(rpmodectl1 & GEN6_RP_ENABLE)); - seq_printf(m, "SW control enabled: %s\n", - yesno((rpmodectl1 & GEN6_RP_MEDIA_MODE_MASK) == - GEN6_RP_MEDIA_SW_MODE)); seq_printf(m, "RC1e Enabled: %s\n", yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); seq_printf(m, "RC6 Enabled: %s\n", @@ -1699,7 +1727,7 @@ static int i915_ips_status(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); seq_printf(m, "Enabled by kernel parameter: %s\n", - yesno(i915.enable_ips)); + yesno(i915_modparams.enable_ips)); if (INTEL_GEN(dev_priv) >= 8) { seq_puts(m, "Currently: unknown\n"); @@ -1775,6 +1803,7 @@ static int i915_emon_status(struct seq_file *m, void *unused) static int i915_ring_freq_table(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); + struct intel_rps *rps = &dev_priv->gt_pm.rps; int ret = 0; int gpu_freq, ia_freq; unsigned int max_gpu_freq, min_gpu_freq; @@ -1786,19 +1815,17 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) intel_runtime_pm_get(dev_priv); - ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); + ret = mutex_lock_interruptible(&dev_priv->pcu_lock); if (ret) goto out; if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { /* Convert GT frequency to 50 HZ units */ - min_gpu_freq = - dev_priv->rps.min_freq_softlimit / GEN9_FREQ_SCALER; - max_gpu_freq = - dev_priv->rps.max_freq_softlimit / GEN9_FREQ_SCALER; + min_gpu_freq = rps->min_freq_softlimit / GEN9_FREQ_SCALER; + max_gpu_freq = rps->max_freq_softlimit / GEN9_FREQ_SCALER; } else { - min_gpu_freq = dev_priv->rps.min_freq_softlimit; - max_gpu_freq = dev_priv->rps.max_freq_softlimit; + min_gpu_freq = rps->min_freq_softlimit; + max_gpu_freq = rps->max_freq_softlimit; } seq_puts(m, "GPU freq (MHz)\tEffective CPU freq (MHz)\tEffective Ring freq (MHz)\n"); @@ -1817,7 +1844,7 @@ static int i915_ring_freq_table(struct seq_file *m, void *unused) ((ia_freq >> 8) & 0xff) * 100); } - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); out: intel_runtime_pm_put(dev_priv); @@ -2014,7 +2041,7 @@ static int i915_dump_lrc(struct seq_file *m, void *unused) enum intel_engine_id id; int ret; - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { seq_printf(m, "Logical Ring Contexts are disabled\n"); return 0; } @@ -2251,25 +2278,26 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_device *dev = &dev_priv->drm; + struct intel_rps *rps = &dev_priv->gt_pm.rps; struct drm_file *file; - seq_printf(m, "RPS enabled? %d\n", dev_priv->rps.enabled); + seq_printf(m, "RPS enabled? %d\n", rps->enabled); seq_printf(m, "GPU busy? %s [%d requests]\n", yesno(dev_priv->gt.awake), dev_priv->gt.active_requests); seq_printf(m, "CPU waiting? %d\n", count_irq_waiters(dev_priv)); seq_printf(m, "Boosts outstanding? %d\n", - atomic_read(&dev_priv->rps.num_waiters)); + atomic_read(&rps->num_waiters)); seq_printf(m, "Frequency requested %d\n", - intel_gpu_freq(dev_priv, dev_priv->rps.cur_freq)); + intel_gpu_freq(dev_priv, rps->cur_freq)); seq_printf(m, " min hard:%d, soft:%d; max soft:%d, hard:%d\n", - intel_gpu_freq(dev_priv, dev_priv->rps.min_freq), - intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit), - intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit), - intel_gpu_freq(dev_priv, dev_priv->rps.max_freq)); + intel_gpu_freq(dev_priv, rps->min_freq), + intel_gpu_freq(dev_priv, rps->min_freq_softlimit), + intel_gpu_freq(dev_priv, rps->max_freq_softlimit), + intel_gpu_freq(dev_priv, rps->max_freq)); seq_printf(m, " idle:%d, efficient:%d, boost:%d\n", - intel_gpu_freq(dev_priv, dev_priv->rps.idle_freq), - intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq), - intel_gpu_freq(dev_priv, dev_priv->rps.boost_freq)); + intel_gpu_freq(dev_priv, rps->idle_freq), + intel_gpu_freq(dev_priv, rps->efficient_freq), + intel_gpu_freq(dev_priv, rps->boost_freq)); mutex_lock(&dev->filelist_mutex); list_for_each_entry_reverse(file, &dev->filelist, lhead) { @@ -2281,15 +2309,15 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) seq_printf(m, "%s [%d]: %d boosts\n", task ? task->comm : "<unknown>", task ? task->pid : -1, - atomic_read(&file_priv->rps.boosts)); + atomic_read(&file_priv->rps_client.boosts)); rcu_read_unlock(); } seq_printf(m, "Kernel (anonymous) boosts: %d\n", - atomic_read(&dev_priv->rps.boosts)); + atomic_read(&rps->boosts)); mutex_unlock(&dev->filelist_mutex); if (INTEL_GEN(dev_priv) >= 6 && - dev_priv->rps.enabled && + rps->enabled && dev_priv->gt.active_requests) { u32 rpup, rpupei; u32 rpdown, rpdownei; @@ -2302,13 +2330,13 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); seq_printf(m, "\nRPS Autotuning (current \"%s\" window):\n", - rps_power_to_str(dev_priv->rps.power)); + rps_power_to_str(rps->power)); seq_printf(m, " Avg. up: %d%% [above threshold? %d%%]\n", rpup && rpupei ? 100 * rpup / rpupei : 0, - dev_priv->rps.up_threshold); + rps->up_threshold); seq_printf(m, " Avg. down: %d%% [below threshold? %d%%]\n", rpdown && rpdownei ? 100 * rpdown / rpdownei : 0, - dev_priv->rps.down_threshold); + rps->down_threshold); } else { seq_puts(m, "\nRPS Autotuning inactive\n"); } @@ -2331,27 +2359,13 @@ static int i915_llc(struct seq_file *m, void *data) static int i915_huc_load_status_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct intel_uc_fw *huc_fw = &dev_priv->huc.fw; + struct drm_printer p; if (!HAS_HUC_UCODE(dev_priv)) return 0; - seq_puts(m, "HuC firmware status:\n"); - seq_printf(m, "\tpath: %s\n", huc_fw->path); - seq_printf(m, "\tfetch: %s\n", - intel_uc_fw_status_repr(huc_fw->fetch_status)); - seq_printf(m, "\tload: %s\n", - intel_uc_fw_status_repr(huc_fw->load_status)); - seq_printf(m, "\tversion wanted: %d.%d\n", - huc_fw->major_ver_wanted, huc_fw->minor_ver_wanted); - seq_printf(m, "\tversion found: %d.%d\n", - huc_fw->major_ver_found, huc_fw->minor_ver_found); - seq_printf(m, "\theader: offset is %d; size = %d\n", - huc_fw->header_offset, huc_fw->header_size); - seq_printf(m, "\tuCode: offset is %d; size = %d\n", - huc_fw->ucode_offset, huc_fw->ucode_size); - seq_printf(m, "\tRSA: offset is %d; size = %d\n", - huc_fw->rsa_offset, huc_fw->rsa_size); + p = drm_seq_file_printer(m); + intel_uc_fw_dump(&dev_priv->huc.fw, &p); intel_runtime_pm_get(dev_priv); seq_printf(m, "\nHuC status 0x%08x:\n", I915_READ(HUC_STATUS2)); @@ -2363,29 +2377,14 @@ static int i915_huc_load_status_info(struct seq_file *m, void *data) static int i915_guc_load_status_info(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; + struct drm_printer p; u32 tmp, i; if (!HAS_GUC_UCODE(dev_priv)) return 0; - seq_printf(m, "GuC firmware status:\n"); - seq_printf(m, "\tpath: %s\n", - guc_fw->path); - seq_printf(m, "\tfetch: %s\n", - intel_uc_fw_status_repr(guc_fw->fetch_status)); - seq_printf(m, "\tload: %s\n", - intel_uc_fw_status_repr(guc_fw->load_status)); - seq_printf(m, "\tversion wanted: %d.%d\n", - guc_fw->major_ver_wanted, guc_fw->minor_ver_wanted); - seq_printf(m, "\tversion found: %d.%d\n", - guc_fw->major_ver_found, guc_fw->minor_ver_found); - seq_printf(m, "\theader: offset is %d; size = %d\n", - guc_fw->header_offset, guc_fw->header_size); - seq_printf(m, "\tuCode: offset is %d; size = %d\n", - guc_fw->ucode_offset, guc_fw->ucode_size); - seq_printf(m, "\tRSA: offset is %d; size = %d\n", - guc_fw->rsa_offset, guc_fw->rsa_size); + p = drm_seq_file_printer(m); + intel_uc_fw_dump(&dev_priv->guc.fw, &p); intel_runtime_pm_get(dev_priv); @@ -2443,12 +2442,8 @@ static void i915_guc_client_info(struct seq_file *m, seq_printf(m, "\tPriority %d, GuC stage index: %u, PD offset 0x%x\n", client->priority, client->stage_id, client->proc_desc_offset); - seq_printf(m, "\tDoorbell id %d, offset: 0x%lx, cookie 0x%x\n", - client->doorbell_id, client->doorbell_offset, client->doorbell_cookie); - seq_printf(m, "\tWQ size %d, offset: 0x%x, tail %d\n", - client->wq_size, client->wq_offset, client->wq_tail); - - seq_printf(m, "\tWork queue full: %u\n", client->no_wq_space); + seq_printf(m, "\tDoorbell id %d, offset: 0x%lx\n", + client->doorbell_id, client->doorbell_offset); for_each_engine(engine, dev_priv, id) { u64 submissions = client->submissions[id]; @@ -2594,7 +2589,7 @@ static int i915_guc_log_control_get(void *data, u64 *val) if (!dev_priv->guc.log.vma) return -EINVAL; - *val = i915.guc_log_level; + *val = i915_modparams.guc_log_level; return 0; } @@ -3239,9 +3234,9 @@ static int i915_display_info(struct seq_file *m, void *unused) static int i915_engine_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct i915_gpu_error *error = &dev_priv->gpu_error; struct intel_engine_cs *engine; enum intel_engine_id id; + struct drm_printer p; intel_runtime_pm_get(dev_priv); @@ -3250,146 +3245,21 @@ static int i915_engine_info(struct seq_file *m, void *unused) seq_printf(m, "Global active requests: %d\n", dev_priv->gt.active_requests); - for_each_engine(engine, dev_priv, id) { - struct intel_breadcrumbs *b = &engine->breadcrumbs; - struct drm_i915_gem_request *rq; - struct rb_node *rb; - u64 addr; - - seq_printf(m, "%s\n", engine->name); - seq_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n", - intel_engine_get_seqno(engine), - intel_engine_last_submit(engine), - engine->hangcheck.seqno, - jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), - engine->timeline->inflight_seqnos); - seq_printf(m, "\tReset count: %d\n", - i915_reset_engine_count(error, engine)); - - rcu_read_lock(); - - seq_printf(m, "\tRequests:\n"); - - rq = list_first_entry(&engine->timeline->requests, - struct drm_i915_gem_request, link); - if (&rq->link != &engine->timeline->requests) - print_request(m, rq, "\t\tfirst "); - - rq = list_last_entry(&engine->timeline->requests, - struct drm_i915_gem_request, link); - if (&rq->link != &engine->timeline->requests) - print_request(m, rq, "\t\tlast "); - - rq = i915_gem_find_active_request(engine); - if (rq) { - print_request(m, rq, "\t\tactive "); - seq_printf(m, - "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n", - rq->head, rq->postfix, rq->tail, - rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, - rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); - } - - seq_printf(m, "\tRING_START: 0x%08x [0x%08x]\n", - I915_READ(RING_START(engine->mmio_base)), - rq ? i915_ggtt_offset(rq->ring->vma) : 0); - seq_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n", - I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR, - rq ? rq->ring->head : 0); - seq_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n", - I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR, - rq ? rq->ring->tail : 0); - seq_printf(m, "\tRING_CTL: 0x%08x [%s]\n", - I915_READ(RING_CTL(engine->mmio_base)), - I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : ""); - - rcu_read_unlock(); - - addr = intel_engine_get_active_head(engine); - seq_printf(m, "\tACTHD: 0x%08x_%08x\n", - upper_32_bits(addr), lower_32_bits(addr)); - addr = intel_engine_get_last_batch_head(engine); - seq_printf(m, "\tBBADDR: 0x%08x_%08x\n", - upper_32_bits(addr), lower_32_bits(addr)); - - if (i915.enable_execlists) { - u32 ptr, read, write; - unsigned int idx; - - seq_printf(m, "\tExeclist status: 0x%08x %08x\n", - I915_READ(RING_EXECLIST_STATUS_LO(engine)), - I915_READ(RING_EXECLIST_STATUS_HI(engine))); - - ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); - read = GEN8_CSB_READ_PTR(ptr); - write = GEN8_CSB_WRITE_PTR(ptr); - seq_printf(m, "\tExeclist CSB read %d, write %d, interrupt posted? %s\n", - read, write, - yesno(test_bit(ENGINE_IRQ_EXECLIST, - &engine->irq_posted))); - if (read >= GEN8_CSB_ENTRIES) - read = 0; - if (write >= GEN8_CSB_ENTRIES) - write = 0; - if (read > write) - write += GEN8_CSB_ENTRIES; - while (read < write) { - idx = ++read % GEN8_CSB_ENTRIES; - seq_printf(m, "\tExeclist CSB[%d]: 0x%08x, context: %d\n", - idx, - I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)), - I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx))); - } - - rcu_read_lock(); - for (idx = 0; idx < ARRAY_SIZE(engine->execlist_port); idx++) { - unsigned int count; - - rq = port_unpack(&engine->execlist_port[idx], - &count); - if (rq) { - seq_printf(m, "\t\tELSP[%d] count=%d, ", - idx, count); - print_request(m, rq, "rq: "); - } else { - seq_printf(m, "\t\tELSP[%d] idle\n", - idx); - } - } - rcu_read_unlock(); - - spin_lock_irq(&engine->timeline->lock); - for (rb = engine->execlist_first; rb; rb = rb_next(rb)){ - struct i915_priolist *p = - rb_entry(rb, typeof(*p), node); - - list_for_each_entry(rq, &p->requests, - priotree.link) - print_request(m, rq, "\t\tQ "); - } - spin_unlock_irq(&engine->timeline->lock); - } else if (INTEL_GEN(dev_priv) > 6) { - seq_printf(m, "\tPP_DIR_BASE: 0x%08x\n", - I915_READ(RING_PP_DIR_BASE(engine))); - seq_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n", - I915_READ(RING_PP_DIR_BASE_READ(engine))); - seq_printf(m, "\tPP_DIR_DCLV: 0x%08x\n", - I915_READ(RING_PP_DIR_DCLV(engine))); - } + p = drm_seq_file_printer(m); + for_each_engine(engine, dev_priv, id) + intel_engine_dump(engine, &p); - spin_lock_irq(&b->rb_lock); - for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { - struct intel_wait *w = rb_entry(rb, typeof(*w), node); + intel_runtime_pm_put(dev_priv); - seq_printf(m, "\t%s [%d] waiting for %x\n", - w->tsk->comm, w->tsk->pid, w->seqno); - } - spin_unlock_irq(&b->rb_lock); + return 0; +} - seq_puts(m, "\n"); - } +static int i915_shrinker_info(struct seq_file *m, void *unused) +{ + struct drm_i915_private *i915 = node_to_i915(m->private); - intel_runtime_pm_put(dev_priv); + seq_printf(m, "seeks = %d\n", i915->mm.shrinker.seeks); + seq_printf(m, "batch = %lu\n", i915->mm.shrinker.batch); return 0; } @@ -3403,7 +3273,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused) enum intel_engine_id id; int j, ret; - if (!i915.semaphores) { + if (!i915_modparams.semaphores) { seq_puts(m, "Semaphores are disabled\n"); return 0; } @@ -3523,6 +3393,57 @@ static int i915_wa_registers(struct seq_file *m, void *unused) return 0; } +static int i915_ipc_status_show(struct seq_file *m, void *data) +{ + struct drm_i915_private *dev_priv = m->private; + + seq_printf(m, "Isochronous Priority Control: %s\n", + yesno(dev_priv->ipc_enabled)); + return 0; +} + +static int i915_ipc_status_open(struct inode *inode, struct file *file) +{ + struct drm_i915_private *dev_priv = inode->i_private; + + if (!HAS_IPC(dev_priv)) + return -ENODEV; + + return single_open(file, i915_ipc_status_show, dev_priv); +} + +static ssize_t i915_ipc_status_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct drm_i915_private *dev_priv = m->private; + int ret; + bool enable; + + ret = kstrtobool_from_user(ubuf, len, &enable); + if (ret < 0) + return ret; + + intel_runtime_pm_get(dev_priv); + if (!dev_priv->ipc_enabled && enable) + DRM_INFO("Enabling IPC: WM will be proper only after next commit\n"); + dev_priv->wm.distrust_bios_wm = true; + dev_priv->ipc_enabled = enable; + intel_enable_ipc(dev_priv); + intel_runtime_pm_put(dev_priv); + + return len; +} + +static const struct file_operations i915_ipc_status_fops = { + .owner = THIS_MODULE, + .open = i915_ipc_status_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = i915_ipc_status_write +}; + static int i915_ddb_info(struct seq_file *m, void *unused) { struct drm_i915_private *dev_priv = node_to_i915(m->private); @@ -4203,8 +4124,7 @@ fault_irq_set(struct drm_i915_private *i915, mutex_unlock(&i915->drm.struct_mutex); /* Flush idle worker to disarm irq */ - while (flush_delayed_work(&i915->gt.idle_work)) - ; + drain_delayed_work(&i915->gt.idle_work); return 0; @@ -4259,18 +4179,20 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_ring_test_irq_fops, i915_ring_test_irq_get, i915_ring_test_irq_set, "0x%08llx\n"); -#define DROP_UNBOUND 0x1 -#define DROP_BOUND 0x2 -#define DROP_RETIRE 0x4 -#define DROP_ACTIVE 0x8 -#define DROP_FREED 0x10 -#define DROP_SHRINK_ALL 0x20 +#define DROP_UNBOUND BIT(0) +#define DROP_BOUND BIT(1) +#define DROP_RETIRE BIT(2) +#define DROP_ACTIVE BIT(3) +#define DROP_FREED BIT(4) +#define DROP_SHRINK_ALL BIT(5) +#define DROP_IDLE BIT(6) #define DROP_ALL (DROP_UNBOUND | \ DROP_BOUND | \ DROP_RETIRE | \ DROP_ACTIVE | \ DROP_FREED | \ - DROP_SHRINK_ALL) + DROP_SHRINK_ALL |\ + DROP_IDLE) static int i915_drop_caches_get(void *data, u64 *val) { @@ -4286,7 +4208,8 @@ i915_drop_caches_set(void *data, u64 val) struct drm_device *dev = &dev_priv->drm; int ret = 0; - DRM_DEBUG("Dropping caches: 0x%08llx\n", val); + DRM_DEBUG("Dropping caches: 0x%08llx [0x%08llx]\n", + val, val & DROP_ALL); /* No need to check and wait for gpu resets, only libdrm auto-restarts * on ioctls on -EAGAIN. */ @@ -4317,6 +4240,9 @@ i915_drop_caches_set(void *data, u64 val) i915_gem_shrink_all(dev_priv); fs_reclaim_release(GFP_KERNEL); + if (val & DROP_IDLE) + drain_delayed_work(&dev_priv->gt.idle_work); + if (val & DROP_FREED) { synchronize_rcu(); i915_gem_drain_freed_objects(dev_priv); @@ -4337,7 +4263,7 @@ i915_max_freq_get(void *data, u64 *val) if (INTEL_GEN(dev_priv) < 6) return -ENODEV; - *val = intel_gpu_freq(dev_priv, dev_priv->rps.max_freq_softlimit); + *val = intel_gpu_freq(dev_priv, dev_priv->gt_pm.rps.max_freq_softlimit); return 0; } @@ -4345,6 +4271,7 @@ static int i915_max_freq_set(void *data, u64 val) { struct drm_i915_private *dev_priv = data; + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 hw_max, hw_min; int ret; @@ -4353,7 +4280,7 @@ i915_max_freq_set(void *data, u64 val) DRM_DEBUG_DRIVER("Manually setting max freq to %llu\n", val); - ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); + ret = mutex_lock_interruptible(&dev_priv->pcu_lock); if (ret) return ret; @@ -4362,20 +4289,20 @@ i915_max_freq_set(void *data, u64 val) */ val = intel_freq_opcode(dev_priv, val); - hw_max = dev_priv->rps.max_freq; - hw_min = dev_priv->rps.min_freq; + hw_max = rps->max_freq; + hw_min = rps->min_freq; - if (val < hw_min || val > hw_max || val < dev_priv->rps.min_freq_softlimit) { - mutex_unlock(&dev_priv->rps.hw_lock); + if (val < hw_min || val > hw_max || val < rps->min_freq_softlimit) { + mutex_unlock(&dev_priv->pcu_lock); return -EINVAL; } - dev_priv->rps.max_freq_softlimit = val; + rps->max_freq_softlimit = val; if (intel_set_rps(dev_priv, val)) DRM_DEBUG_DRIVER("failed to update RPS to new softlimit\n"); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); return 0; } @@ -4392,7 +4319,7 @@ i915_min_freq_get(void *data, u64 *val) if (INTEL_GEN(dev_priv) < 6) return -ENODEV; - *val = intel_gpu_freq(dev_priv, dev_priv->rps.min_freq_softlimit); + *val = intel_gpu_freq(dev_priv, dev_priv->gt_pm.rps.min_freq_softlimit); return 0; } @@ -4400,6 +4327,7 @@ static int i915_min_freq_set(void *data, u64 val) { struct drm_i915_private *dev_priv = data; + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 hw_max, hw_min; int ret; @@ -4408,7 +4336,7 @@ i915_min_freq_set(void *data, u64 val) DRM_DEBUG_DRIVER("Manually setting min freq to %llu\n", val); - ret = mutex_lock_interruptible(&dev_priv->rps.hw_lock); + ret = mutex_lock_interruptible(&dev_priv->pcu_lock); if (ret) return ret; @@ -4417,21 +4345,21 @@ i915_min_freq_set(void *data, u64 val) */ val = intel_freq_opcode(dev_priv, val); - hw_max = dev_priv->rps.max_freq; - hw_min = dev_priv->rps.min_freq; + hw_max = rps->max_freq; + hw_min = rps->min_freq; if (val < hw_min || - val > hw_max || val > dev_priv->rps.max_freq_softlimit) { - mutex_unlock(&dev_priv->rps.hw_lock); + val > hw_max || val > rps->max_freq_softlimit) { + mutex_unlock(&dev_priv->pcu_lock); return -EINVAL; } - dev_priv->rps.min_freq_softlimit = val; + rps->min_freq_softlimit = val; if (intel_set_rps(dev_priv, val)) DRM_DEBUG_DRIVER("failed to update RPS to new softlimit\n"); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); return 0; } @@ -4674,26 +4602,26 @@ static int i915_sseu_status(struct seq_file *m, void *unused) static int i915_forcewake_open(struct inode *inode, struct file *file) { - struct drm_i915_private *dev_priv = inode->i_private; + struct drm_i915_private *i915 = inode->i_private; - if (INTEL_GEN(dev_priv) < 6) + if (INTEL_GEN(i915) < 6) return 0; - intel_runtime_pm_get(dev_priv); - intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + intel_runtime_pm_get(i915); + intel_uncore_forcewake_user_get(i915); return 0; } static int i915_forcewake_release(struct inode *inode, struct file *file) { - struct drm_i915_private *dev_priv = inode->i_private; + struct drm_i915_private *i915 = inode->i_private; - if (INTEL_GEN(dev_priv) < 6) + if (INTEL_GEN(i915) < 6) return 0; - intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); - intel_runtime_pm_put(dev_priv); + intel_uncore_forcewake_user_put(i915); + intel_runtime_pm_put(i915); return 0; } @@ -4783,9 +4711,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_capabilities", i915_capabilities, 0}, {"i915_gem_objects", i915_gem_object_info, 0}, {"i915_gem_gtt", i915_gem_gtt_info, 0}, - {"i915_gem_pin_display", i915_gem_gtt_info, 0, (void *)1}, {"i915_gem_stolen", i915_gem_stolen_list_info }, - {"i915_gem_request", i915_gem_request_info, 0}, {"i915_gem_seqno", i915_gem_seqno_info, 0}, {"i915_gem_fence_regs", i915_gem_fence_regs_info, 0}, {"i915_gem_interrupt", i915_interrupt_info, 0}, @@ -4823,6 +4749,7 @@ static const struct drm_info_list i915_debugfs_list[] = { {"i915_dmc_info", i915_dmc_info, 0}, {"i915_display_info", i915_display_info, 0}, {"i915_engine_info", i915_engine_info, 0}, + {"i915_shrinker_info", i915_shrinker_info, 0}, {"i915_semaphore_status", i915_semaphore_status, 0}, {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, {"i915_dp_mst_info", i915_dp_mst_info, 0}, @@ -4859,7 +4786,8 @@ static const struct i915_debugfs_files { {"i915_dp_test_type", &i915_displayport_test_type_fops}, {"i915_dp_test_active", &i915_displayport_test_active_fops}, {"i915_guc_log_control", &i915_guc_log_control_fops}, - {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops} + {"i915_hpd_storm_ctl", &i915_hpd_storm_ctl_fops}, + {"i915_ipc_status", &i915_ipc_status_fops} }; int i915_debugfs_register(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index ff70fc45ba7c..3db5851756f0 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -58,12 +58,12 @@ static unsigned int i915_load_fail_count; bool __i915_inject_load_failure(const char *func, int line) { - if (i915_load_fail_count >= i915.inject_load_failure) + if (i915_load_fail_count >= i915_modparams.inject_load_failure) return false; - if (++i915_load_fail_count == i915.inject_load_failure) { + if (++i915_load_fail_count == i915_modparams.inject_load_failure) { DRM_INFO("Injecting failure at checkpoint %u [%s:%d]\n", - i915.inject_load_failure, func, line); + i915_modparams.inject_load_failure, func, line); return true; } @@ -106,8 +106,8 @@ __i915_printk(struct drm_i915_private *dev_priv, const char *level, static bool i915_error_injected(struct drm_i915_private *dev_priv) { - return i915.inject_load_failure && - i915_load_fail_count == i915.inject_load_failure; + return i915_modparams.inject_load_failure && + i915_load_fail_count == i915_modparams.inject_load_failure; } #define i915_load_error(dev_priv, fmt, ...) \ @@ -321,7 +321,7 @@ static int i915_getparam(struct drm_device *dev, void *data, value = USES_PPGTT(dev_priv); break; case I915_PARAM_HAS_SEMAPHORES: - value = i915.semaphores; + value = i915_modparams.semaphores; break; case I915_PARAM_HAS_SECURE_BATCHES: value = capable(CAP_SYS_ADMIN); @@ -340,7 +340,8 @@ static int i915_getparam(struct drm_device *dev, void *data, return -ENODEV; break; case I915_PARAM_HAS_GPU_RESET: - value = i915.enable_hangcheck && intel_has_gpu_reset(dev_priv); + value = i915_modparams.enable_hangcheck && + intel_has_gpu_reset(dev_priv); if (value && intel_has_reset_engine(dev_priv)) value = 2; break; @@ -366,9 +367,18 @@ static int i915_getparam(struct drm_device *dev, void *data, value = i915_gem_mmap_gtt_version(); break; case I915_PARAM_HAS_SCHEDULER: - value = dev_priv->engine[RCS] && - dev_priv->engine[RCS]->schedule; + value = 0; + if (dev_priv->engine[RCS] && dev_priv->engine[RCS]->schedule) { + value |= I915_SCHEDULER_CAP_ENABLED; + value |= I915_SCHEDULER_CAP_PRIORITY; + + if (INTEL_INFO(dev_priv)->has_logical_ring_preemption && + i915_modparams.enable_execlists && + !i915_modparams.enable_guc_submission) + value |= I915_SCHEDULER_CAP_PREEMPTION; + } break; + case I915_PARAM_MMAP_VERSION: /* Remember to bump this if the version changes! */ case I915_PARAM_HAS_GEM: @@ -605,9 +615,10 @@ static void i915_gem_fini(struct drm_i915_private *dev_priv) intel_uc_fini_hw(dev_priv); i915_gem_cleanup_engines(dev_priv); i915_gem_contexts_fini(dev_priv); - i915_gem_cleanup_userptr(dev_priv); mutex_unlock(&dev_priv->drm.struct_mutex); + i915_gem_cleanup_userptr(dev_priv); + i915_gem_drain_freed_objects(dev_priv); WARN_ON(!list_empty(&dev_priv->contexts.list)); @@ -869,6 +880,10 @@ static int i915_driver_init_early(struct drm_i915_private *dev_priv, memcpy(device_info, match_info, sizeof(*device_info)); device_info->device_id = dev_priv->drm.pdev->device; + BUILD_BUG_ON(INTEL_MAX_PLATFORMS > + sizeof(device_info->platform_mask) * BITS_PER_BYTE); + device_info->platform_mask = BIT(device_info->platform); + BUG_ON(device_info->gen > sizeof(device_info->gen_mask) * BITS_PER_BYTE); device_info->gen_mask = BIT(device_info->gen - 1); @@ -1002,6 +1017,8 @@ static int i915_driver_init_mmio(struct drm_i915_private *dev_priv) intel_uncore_init(dev_priv); + intel_uc_init_mmio(dev_priv); + ret = intel_engines_init_mmio(dev_priv); if (ret) goto err_uncore; @@ -1031,9 +1048,9 @@ static void i915_driver_cleanup_mmio(struct drm_i915_private *dev_priv) static void intel_sanitize_options(struct drm_i915_private *dev_priv) { - i915.enable_execlists = + i915_modparams.enable_execlists = intel_sanitize_enable_execlists(dev_priv, - i915.enable_execlists); + i915_modparams.enable_execlists); /* * i915.enable_ppgtt is read-only, so do an early pass to validate the @@ -1041,12 +1058,15 @@ static void intel_sanitize_options(struct drm_i915_private *dev_priv) * do this now so that we can print out any log messages once rather * than every time we check intel_enable_ppgtt(). */ - i915.enable_ppgtt = - intel_sanitize_enable_ppgtt(dev_priv, i915.enable_ppgtt); - DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915.enable_ppgtt); + i915_modparams.enable_ppgtt = + intel_sanitize_enable_ppgtt(dev_priv, + i915_modparams.enable_ppgtt); + DRM_DEBUG_DRIVER("ppgtt mode: %i\n", i915_modparams.enable_ppgtt); - i915.semaphores = intel_sanitize_semaphores(dev_priv, i915.semaphores); - DRM_DEBUG_DRIVER("use GPU semaphores? %s\n", yesno(i915.semaphores)); + i915_modparams.semaphores = + intel_sanitize_semaphores(dev_priv, i915_modparams.semaphores); + DRM_DEBUG_DRIVER("use GPU semaphores? %s\n", + yesno(i915_modparams.semaphores)); intel_uc_sanitize_options(dev_priv); @@ -1277,7 +1297,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) int ret; /* Enable nuclear pageflip on ILK+ */ - if (!i915.nuclear_pageflip && match_info->gen < 5) + if (!i915_modparams.nuclear_pageflip && match_info->gen < 5) driver.driver_features &= ~DRIVER_ATOMIC; ret = -ENOMEM; @@ -1341,7 +1361,7 @@ int i915_driver_load(struct pci_dev *pdev, const struct pci_device_id *ent) intel_runtime_pm_enable(dev_priv); - dev_priv->ipc_enabled = false; + intel_init_ipc(dev_priv); if (IS_ENABLED(CONFIG_DRM_I915_DEBUG)) DRM_INFO("DRM_I915_DEBUG enabled\n"); @@ -1572,7 +1592,7 @@ static int i915_drm_suspend_late(struct drm_device *dev, bool hibernation) intel_display_set_init_power(dev_priv, false); - fw_csr = !IS_GEN9_LP(dev_priv) && + fw_csr = !IS_GEN9_LP(dev_priv) && !hibernation && suspend_to_idle(dev_priv) && dev_priv->csr.dmc_payload; /* * In case of firmware assisted context save/restore don't manually @@ -2062,11 +2082,14 @@ static int i915_pm_resume(struct device *kdev) /* freeze: before creating the hibernation_image */ static int i915_pm_freeze(struct device *kdev) { + struct drm_device *dev = &kdev_to_i915(kdev)->drm; int ret; - ret = i915_pm_suspend(kdev); - if (ret) - return ret; + if (dev->switch_power_state != DRM_SWITCH_POWER_OFF) { + ret = i915_drm_suspend(dev); + if (ret) + return ret; + } ret = i915_gem_freeze(kdev_to_i915(kdev)); if (ret) @@ -2077,11 +2100,14 @@ static int i915_pm_freeze(struct device *kdev) static int i915_pm_freeze_late(struct device *kdev) { + struct drm_device *dev = &kdev_to_i915(kdev)->drm; int ret; - ret = i915_pm_suspend_late(kdev); - if (ret) - return ret; + if (dev->switch_power_state != DRM_SWITCH_POWER_OFF) { + ret = i915_drm_suspend_late(dev, true); + if (ret) + return ret; + } ret = i915_gem_freeze_late(kdev_to_i915(kdev)); if (ret) @@ -2477,7 +2503,7 @@ static int intel_runtime_suspend(struct device *kdev) struct drm_i915_private *dev_priv = to_i915(dev); int ret; - if (WARN_ON_ONCE(!(dev_priv->rps.enabled && intel_enable_rc6()))) + if (WARN_ON_ONCE(!(dev_priv->gt_pm.rc6.enabled && intel_rc6_enabled()))) return -ENODEV; if (WARN_ON_ONCE(!HAS_RUNTIME_PM(dev_priv))) @@ -2519,12 +2545,12 @@ static int intel_runtime_suspend(struct device *kdev) intel_uncore_suspend(dev_priv); enable_rpm_wakeref_asserts(dev_priv); - WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count)); + WARN_ON_ONCE(atomic_read(&dev_priv->runtime_pm.wakeref_count)); if (intel_uncore_arm_unclaimed_mmio_detection(dev_priv)) DRM_ERROR("Unclaimed access detected prior to suspending\n"); - dev_priv->pm.suspended = true; + dev_priv->runtime_pm.suspended = true; /* * FIXME: We really should find a document that references the arguments @@ -2570,11 +2596,11 @@ static int intel_runtime_resume(struct device *kdev) DRM_DEBUG_KMS("Resuming device\n"); - WARN_ON_ONCE(atomic_read(&dev_priv->pm.wakeref_count)); + WARN_ON_ONCE(atomic_read(&dev_priv->runtime_pm.wakeref_count)); disable_rpm_wakeref_asserts(dev_priv); intel_opregion_notify_adapter(dev_priv, PCI_D0); - dev_priv->pm.suspended = false; + dev_priv->runtime_pm.suspended = false; if (intel_uncore_unclaimed_mmio(dev_priv)) DRM_DEBUG_DRIVER("Unclaimed access during suspend, bios?\n"); @@ -2609,6 +2635,8 @@ static int intel_runtime_resume(struct device *kdev) if (!IS_VALLEYVIEW(dev_priv) && !IS_CHERRYVIEW(dev_priv)) intel_hpd_init(dev_priv); + intel_enable_ipc(dev_priv); + enable_rpm_wakeref_asserts(dev_priv); if (ret) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b1fa81348ee9..54b5d4c582b6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -80,8 +80,8 @@ #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" -#define DRIVER_DATE "20170907" -#define DRIVER_TIMESTAMP 1504772900 +#define DRIVER_DATE "20171023" +#define DRIVER_TIMESTAMP 1508748913 /* Use I915_STATE_WARN(x) and I915_STATE_WARN_ON() (rather than WARN() and * WARN_ON()) for hw state sanity checks to check for unexpected conditions @@ -93,7 +93,7 @@ #define I915_STATE_WARN(condition, format...) ({ \ int __ret_warn_on = !!(condition); \ if (unlikely(__ret_warn_on)) \ - if (!WARN(i915.verbose_state_checks, format)) \ + if (!WARN(i915_modparams.verbose_state_checks, format)) \ DRM_ERROR(format); \ unlikely(__ret_warn_on); \ }) @@ -126,7 +126,7 @@ static inline uint_fixed_16_16_t u32_to_fixed16(uint32_t val) { uint_fixed_16_16_t fp; - WARN_ON(val >> 16); + WARN_ON(val > U16_MAX); fp.val = val << 16; return fp; @@ -163,8 +163,8 @@ static inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1, static inline uint_fixed_16_16_t clamp_u64_to_fixed16(uint64_t val) { uint_fixed_16_16_t fp; - WARN_ON(val >> 32); - fp.val = clamp_t(uint32_t, val, 0, ~0); + WARN_ON(val > U32_MAX); + fp.val = (uint32_t) val; return fp; } @@ -181,8 +181,8 @@ static inline uint32_t mul_round_up_u32_fixed16(uint32_t val, intermediate_val = (uint64_t) val * mul.val; intermediate_val = DIV_ROUND_UP_ULL(intermediate_val, 1 << 16); - WARN_ON(intermediate_val >> 32); - return clamp_t(uint32_t, intermediate_val, 0, ~0); + WARN_ON(intermediate_val > U32_MAX); + return (uint32_t) intermediate_val; } static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val, @@ -211,8 +211,8 @@ static inline uint32_t div_round_up_u32_fixed16(uint32_t val, interm_val = (uint64_t)val << 16; interm_val = DIV_ROUND_UP_ULL(interm_val, d.val); - WARN_ON(interm_val >> 32); - return clamp_t(uint32_t, interm_val, 0, ~0); + WARN_ON(interm_val > U32_MAX); + return (uint32_t) interm_val; } static inline uint_fixed_16_16_t mul_u32_fixed16(uint32_t val, @@ -609,7 +609,7 @@ struct drm_i915_file_private { struct intel_rps_client { atomic_t boosts; - } rps; + } rps_client; unsigned int bsd_engine; @@ -776,7 +776,6 @@ struct intel_csr { func(has_fpga_dbg); \ func(has_full_ppgtt); \ func(has_full_48bit_ppgtt); \ - func(has_gmbus_irq); \ func(has_gmch_display); \ func(has_guc); \ func(has_guc_ct); \ @@ -784,8 +783,8 @@ struct intel_csr { func(has_l3_dpf); \ func(has_llc); \ func(has_logical_ring_contexts); \ + func(has_logical_ring_preemption); \ func(has_overlay); \ - func(has_pipe_cxsr); \ func(has_pooled_eu); \ func(has_psr); \ func(has_rc6); \ @@ -797,7 +796,8 @@ struct intel_csr { func(cursor_needs_physical); \ func(hws_needs_physical); \ func(overlay_needs_physical); \ - func(supports_tv); + func(supports_tv); \ + func(has_ipc); struct sseu_dev_info { u8 slice_mask; @@ -851,21 +851,30 @@ enum intel_platform { }; struct intel_device_info { - u32 display_mmio_offset; u16 device_id; - u8 num_pipes; - u8 num_sprites[I915_MAX_PIPES]; - u8 num_scalers[I915_MAX_PIPES]; - u8 gen; u16 gen_mask; - enum intel_platform platform; + + u8 gen; u8 gt; /* GT number, 0 if undefined */ - u8 ring_mask; /* Rings supported by the HW */ u8 num_rings; + u8 ring_mask; /* Rings supported by the HW */ + + enum intel_platform platform; + u32 platform_mask; + + u32 display_mmio_offset; + + u8 num_pipes; + u8 num_sprites[I915_MAX_PIPES]; + u8 num_scalers[I915_MAX_PIPES]; + + unsigned int page_sizes; /* page sizes supported by the HW */ + #define DEFINE_FLAG(name) u8 name:1 DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG); #undef DEFINE_FLAG u16 ddb_size; /* in blocks */ + /* Register offsets for the various display pipes and transcoders */ int pipe_offsets[I915_MAX_TRANSCODERS]; int trans_offsets[I915_MAX_TRANSCODERS]; @@ -974,6 +983,7 @@ struct i915_gpu_state { pid_t pid; u32 handle; u32 hw_id; + int priority; int ban_score; int active; int guilty; @@ -996,11 +1006,13 @@ struct i915_gpu_state { long jiffies; pid_t pid; u32 context; + int priority; int ban_score; u32 seqno; u32 head; u32 tail; - } *requests, execlist[2]; + } *requests, execlist[EXECLIST_MAX_PORTS]; + unsigned int num_ports; struct drm_i915_error_waiter { char comm[TASK_COMM_LEN]; @@ -1095,6 +1107,16 @@ struct intel_fbc { int src_w; int src_h; bool visible; + /* + * Display surface base address adjustement for + * pageflips. Note that on gen4+ this only adjusts up + * to a tile, offsets within a tile are handled in + * the hw itself (with the TILEOFF register). + */ + int adjusted_x; + int adjusted_y; + + int y; } plane; struct { @@ -1178,6 +1200,14 @@ struct i915_psr { bool y_cord_support; bool colorimetry_support; bool alpm; + + void (*enable_source)(struct intel_dp *, + const struct intel_crtc_state *); + void (*disable_source)(struct intel_dp *, + const struct intel_crtc_state *); + void (*enable_sink)(struct intel_dp *); + void (*activate)(struct intel_dp *); + void (*setup_vsc)(struct intel_dp *, const struct intel_crtc_state *); }; enum intel_pch { @@ -1296,7 +1326,7 @@ struct intel_rps_ei { u32 media_c0; }; -struct intel_gen6_power_mgmt { +struct intel_rps { /* * work, interrupts_enabled and pm_iir are protected by * dev_priv->irq_lock @@ -1337,20 +1367,26 @@ struct intel_gen6_power_mgmt { enum { LOW_POWER, BETWEEN, HIGH_POWER } power; bool enabled; - struct delayed_work autoenable_work; atomic_t num_waiters; atomic_t boosts; /* manual wa residency calculations */ struct intel_rps_ei ei; +}; - /* - * Protects RPS/RC6 register access and PCU communication. - * Must be taken after struct_mutex if nested. Note that - * this lock may be held for long periods of time when - * talking to hw - so only take it when talking to hw! - */ - struct mutex hw_lock; +struct intel_rc6 { + bool enabled; +}; + +struct intel_llc_pstate { + bool enabled; +}; + +struct intel_gen6_power_mgmt { + struct intel_rps rps; + struct intel_rc6 rc6; + struct intel_llc_pstate llc_pstate; + struct delayed_work autoenable_work; }; /* defined intel_pm.c */ @@ -1463,6 +1499,9 @@ struct i915_gem_mm { * always the inner lock when overlapping with struct_mutex. */ struct mutex stolen_lock; + /* Protects bound_list/unbound_list and #drm_i915_gem_object.mm.link */ + spinlock_t obj_lock; + /** List of all objects in gtt_space. Used to restore gtt * mappings on resume */ struct list_head bound_list; @@ -1483,6 +1522,7 @@ struct i915_gem_mm { */ struct llist_head free_list; struct work_struct free_work; + spinlock_t free_lock; /** * Small stash of WC pages @@ -1492,6 +1532,11 @@ struct i915_gem_mm { /** Usable portion of the GTT for GEM */ dma_addr_t stolen_base; /* limited to low memory (32-bit) */ + /** + * tmpfs instance used for shmem backed objects + */ + struct vfsmount *gemfs; + /** PPGTT used for aliasing the PPGTT with the GTT */ struct i915_hw_ppgtt *aliasing_ppgtt; @@ -1733,6 +1778,8 @@ struct intel_vbt_data { u16 panel_id; struct mipi_config *config; struct mipi_pps_data *pps; + u16 bl_ports; + u16 cabc_ports; u8 seq_version; u32 size; u8 *data; @@ -1836,6 +1883,20 @@ struct skl_wm_level { uint8_t plane_res_l; }; +/* Stores plane specific WM parameters */ +struct skl_wm_params { + bool x_tiled, y_tiled; + bool rc_surface; + uint32_t width; + uint8_t cpp; + uint32_t plane_pixel_rate; + uint32_t y_min_scanlines; + uint32_t plane_bytes_per_line; + uint_fixed_16_16_t plane_blocks_per_line; + uint_fixed_16_16_t y_tile_minimum; + uint32_t linetime_us; +}; + /* * This struct helps tracking the state needed for runtime PM, which puts the * device in PCI D3 state. Notice that when this happens, nothing on the @@ -1914,13 +1975,7 @@ struct i915_wa_reg { u32 mask; }; -/* - * RING_MAX_NONPRIV_SLOTS is per-engine but at this point we are only - * allowing it for RCS as we don't foresee any requirement of having - * a whitelist for other engines. When it is really required for - * other engines then the limit need to be increased. - */ -#define I915_MAX_WA_REGS (16 + RING_MAX_NONPRIV_SLOTS) +#define I915_MAX_WA_REGS 16 struct i915_workarounds { struct i915_wa_reg reg[I915_MAX_WA_REGS]; @@ -2221,8 +2276,11 @@ struct drm_i915_private { wait_queue_head_t gmbus_wait_queue; struct pci_dev *bridge_dev; - struct i915_gem_context *kernel_context; struct intel_engine_cs *engine[I915_NUM_ENGINES]; + /* Context used internally to idle the GPU and setup initial state */ + struct i915_gem_context *kernel_context; + /* Context only to be used for injecting preemption commands */ + struct i915_gem_context *preempt_context; struct i915_vma *semaphore; struct drm_dma_handle *status_page_dmah; @@ -2331,6 +2389,8 @@ struct drm_i915_private { DECLARE_HASHTABLE(mm_structs, 7); struct mutex mm_lock; + struct intel_ppat ppat; + /* Kernel Modesetting */ struct intel_crtc *plane_to_crtc_mapping[I915_MAX_PIPES]; @@ -2376,8 +2436,16 @@ struct drm_i915_private { /* Cannot be determined by PCIID. You must always read a register. */ u32 edram_cap; - /* gen6+ rps state */ - struct intel_gen6_power_mgmt rps; + /* + * Protects RPS/RC6 register access and PCU communication. + * Must be taken after struct_mutex if nested. Note that + * this lock may be held for long periods of time when + * talking to hw - so only take it when talking to hw! + */ + struct mutex pcu_lock; + + /* gen6+ GT PM state */ + struct intel_gen6_power_mgmt gt_pm; /* ilk-only ips/rps state. Everything in here is protected by the global * mchdev_lock in intel_pm.c */ @@ -2488,7 +2556,7 @@ struct drm_i915_private { bool distrust_bios_wm; } wm; - struct i915_runtime_pm pm; + struct i915_runtime_pm runtime_pm; struct { bool initialized; @@ -2811,8 +2879,8 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg) #define for_each_sgt_dma(__dmap, __iter, __sgt) \ for ((__iter) = __sgt_iter((__sgt)->sgl, true); \ ((__dmap) = (__iter).dma + (__iter).curr); \ - (((__iter).curr += PAGE_SIZE) < (__iter).max) || \ - ((__iter) = __sgt_iter(__sg_next((__iter).sgp), true), 0)) + (((__iter).curr += PAGE_SIZE) >= (__iter).max) ? \ + (__iter) = __sgt_iter(__sg_next((__iter).sgp), true), 0 : 0) /** * for_each_sgt_page - iterate over the pages of the given sg_table @@ -2824,8 +2892,38 @@ static inline struct scatterlist *__sg_next(struct scatterlist *sg) for ((__iter) = __sgt_iter((__sgt)->sgl, false); \ ((__pp) = (__iter).pfn == 0 ? NULL : \ pfn_to_page((__iter).pfn + ((__iter).curr >> PAGE_SHIFT))); \ - (((__iter).curr += PAGE_SIZE) < (__iter).max) || \ - ((__iter) = __sgt_iter(__sg_next((__iter).sgp), false), 0)) + (((__iter).curr += PAGE_SIZE) >= (__iter).max) ? \ + (__iter) = __sgt_iter(__sg_next((__iter).sgp), false), 0 : 0) + +static inline unsigned int i915_sg_page_sizes(struct scatterlist *sg) +{ + unsigned int page_sizes; + + page_sizes = 0; + while (sg) { + GEM_BUG_ON(sg->offset); + GEM_BUG_ON(!IS_ALIGNED(sg->length, PAGE_SIZE)); + page_sizes |= sg->length; + sg = __sg_next(sg); + } + + return page_sizes; +} + +static inline unsigned int i915_sg_segment_size(void) +{ + unsigned int size = swiotlb_max_segment(); + + if (size == 0) + return SCATTERLIST_MAX_SEGMENT; + + size = rounddown(size, PAGE_SIZE); + /* swiotlb_max_segment_size can return 1 byte when it means one page. */ + if (size < PAGE_SIZE) + size = PAGE_SIZE; + + return size; +} static inline const struct intel_device_info * intel_info(const struct drm_i915_private *dev_priv) @@ -2842,23 +2940,21 @@ intel_info(const struct drm_i915_private *dev_priv) #define INTEL_REVID(dev_priv) ((dev_priv)->drm.pdev->revision) #define GEN_FOREVER (0) + +#define INTEL_GEN_MASK(s, e) ( \ + BUILD_BUG_ON_ZERO(!__builtin_constant_p(s)) + \ + BUILD_BUG_ON_ZERO(!__builtin_constant_p(e)) + \ + GENMASK((e) != GEN_FOREVER ? (e) - 1 : BITS_PER_LONG - 1, \ + (s) != GEN_FOREVER ? (s) - 1 : 0) \ +) + /* * Returns true if Gen is in inclusive range [Start, End]. * * Use GEN_FOREVER for unbound start and or end. */ -#define IS_GEN(dev_priv, s, e) ({ \ - unsigned int __s = (s), __e = (e); \ - BUILD_BUG_ON(!__builtin_constant_p(s)); \ - BUILD_BUG_ON(!__builtin_constant_p(e)); \ - if ((__s) != GEN_FOREVER) \ - __s = (s) - 1; \ - if ((__e) == GEN_FOREVER) \ - __e = BITS_PER_LONG - 1; \ - else \ - __e = (e) - 1; \ - !!((dev_priv)->info.gen_mask & GENMASK((__e), (__s))); \ -}) +#define IS_GEN(dev_priv, s, e) \ + (!!((dev_priv)->info.gen_mask & INTEL_GEN_MASK((s), (e)))) /* * Return true if revision is in range [since,until] inclusive. @@ -2868,37 +2964,39 @@ intel_info(const struct drm_i915_private *dev_priv) #define IS_REVID(p, since, until) \ (INTEL_REVID(p) >= (since) && INTEL_REVID(p) <= (until)) -#define IS_I830(dev_priv) ((dev_priv)->info.platform == INTEL_I830) -#define IS_I845G(dev_priv) ((dev_priv)->info.platform == INTEL_I845G) -#define IS_I85X(dev_priv) ((dev_priv)->info.platform == INTEL_I85X) -#define IS_I865G(dev_priv) ((dev_priv)->info.platform == INTEL_I865G) -#define IS_I915G(dev_priv) ((dev_priv)->info.platform == INTEL_I915G) -#define IS_I915GM(dev_priv) ((dev_priv)->info.platform == INTEL_I915GM) -#define IS_I945G(dev_priv) ((dev_priv)->info.platform == INTEL_I945G) -#define IS_I945GM(dev_priv) ((dev_priv)->info.platform == INTEL_I945GM) -#define IS_I965G(dev_priv) ((dev_priv)->info.platform == INTEL_I965G) -#define IS_I965GM(dev_priv) ((dev_priv)->info.platform == INTEL_I965GM) -#define IS_G45(dev_priv) ((dev_priv)->info.platform == INTEL_G45) -#define IS_GM45(dev_priv) ((dev_priv)->info.platform == INTEL_GM45) +#define IS_PLATFORM(dev_priv, p) ((dev_priv)->info.platform_mask & BIT(p)) + +#define IS_I830(dev_priv) IS_PLATFORM(dev_priv, INTEL_I830) +#define IS_I845G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I845G) +#define IS_I85X(dev_priv) IS_PLATFORM(dev_priv, INTEL_I85X) +#define IS_I865G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I865G) +#define IS_I915G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I915G) +#define IS_I915GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I915GM) +#define IS_I945G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I945G) +#define IS_I945GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I945GM) +#define IS_I965G(dev_priv) IS_PLATFORM(dev_priv, INTEL_I965G) +#define IS_I965GM(dev_priv) IS_PLATFORM(dev_priv, INTEL_I965GM) +#define IS_G45(dev_priv) IS_PLATFORM(dev_priv, INTEL_G45) +#define IS_GM45(dev_priv) IS_PLATFORM(dev_priv, INTEL_GM45) #define IS_G4X(dev_priv) (IS_G45(dev_priv) || IS_GM45(dev_priv)) #define IS_PINEVIEW_G(dev_priv) (INTEL_DEVID(dev_priv) == 0xa001) #define IS_PINEVIEW_M(dev_priv) (INTEL_DEVID(dev_priv) == 0xa011) -#define IS_PINEVIEW(dev_priv) ((dev_priv)->info.platform == INTEL_PINEVIEW) -#define IS_G33(dev_priv) ((dev_priv)->info.platform == INTEL_G33) +#define IS_PINEVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_PINEVIEW) +#define IS_G33(dev_priv) IS_PLATFORM(dev_priv, INTEL_G33) #define IS_IRONLAKE_M(dev_priv) (INTEL_DEVID(dev_priv) == 0x0046) -#define IS_IVYBRIDGE(dev_priv) ((dev_priv)->info.platform == INTEL_IVYBRIDGE) +#define IS_IVYBRIDGE(dev_priv) IS_PLATFORM(dev_priv, INTEL_IVYBRIDGE) #define IS_IVB_GT1(dev_priv) (IS_IVYBRIDGE(dev_priv) && \ (dev_priv)->info.gt == 1) -#define IS_VALLEYVIEW(dev_priv) ((dev_priv)->info.platform == INTEL_VALLEYVIEW) -#define IS_CHERRYVIEW(dev_priv) ((dev_priv)->info.platform == INTEL_CHERRYVIEW) -#define IS_HASWELL(dev_priv) ((dev_priv)->info.platform == INTEL_HASWELL) -#define IS_BROADWELL(dev_priv) ((dev_priv)->info.platform == INTEL_BROADWELL) -#define IS_SKYLAKE(dev_priv) ((dev_priv)->info.platform == INTEL_SKYLAKE) -#define IS_BROXTON(dev_priv) ((dev_priv)->info.platform == INTEL_BROXTON) -#define IS_KABYLAKE(dev_priv) ((dev_priv)->info.platform == INTEL_KABYLAKE) -#define IS_GEMINILAKE(dev_priv) ((dev_priv)->info.platform == INTEL_GEMINILAKE) -#define IS_COFFEELAKE(dev_priv) ((dev_priv)->info.platform == INTEL_COFFEELAKE) -#define IS_CANNONLAKE(dev_priv) ((dev_priv)->info.platform == INTEL_CANNONLAKE) +#define IS_VALLEYVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_VALLEYVIEW) +#define IS_CHERRYVIEW(dev_priv) IS_PLATFORM(dev_priv, INTEL_CHERRYVIEW) +#define IS_HASWELL(dev_priv) IS_PLATFORM(dev_priv, INTEL_HASWELL) +#define IS_BROADWELL(dev_priv) IS_PLATFORM(dev_priv, INTEL_BROADWELL) +#define IS_SKYLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_SKYLAKE) +#define IS_BROXTON(dev_priv) IS_PLATFORM(dev_priv, INTEL_BROXTON) +#define IS_KABYLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_KABYLAKE) +#define IS_GEMINILAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_GEMINILAKE) +#define IS_COFFEELAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_COFFEELAKE) +#define IS_CANNONLAKE(dev_priv) IS_PLATFORM(dev_priv, INTEL_CANNONLAKE) #define IS_MOBILE(dev_priv) ((dev_priv)->info.is_mobile) #define IS_HSW_EARLY_SDV(dev_priv) (IS_HASWELL(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0xFF00) == 0x0C00) @@ -2946,6 +3044,8 @@ intel_info(const struct drm_i915_private *dev_priv) (dev_priv)->info.gt == 3) #define IS_CFL_ULT(dev_priv) (IS_COFFEELAKE(dev_priv) && \ (INTEL_DEVID(dev_priv) & 0x00F0) == 0x00A0) +#define IS_CFL_GT2(dev_priv) (IS_COFFEELAKE(dev_priv) && \ + (dev_priv)->info.gt == 2) #define IS_ALPHA_SUPPORT(intel_info) ((intel_info)->is_alpha_support) @@ -2986,6 +3086,7 @@ intel_info(const struct drm_i915_private *dev_priv) #define CNL_REVID_A0 0x0 #define CNL_REVID_B0 0x1 +#define CNL_REVID_C0 0x2 #define IS_CNL_REVID(p, since, until) \ (IS_CANNONLAKE(p) && IS_REVID(p, since, until)) @@ -3036,9 +3137,13 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_LOGICAL_RING_CONTEXTS(dev_priv) \ ((dev_priv)->info.has_logical_ring_contexts) -#define USES_PPGTT(dev_priv) (i915.enable_ppgtt) -#define USES_FULL_PPGTT(dev_priv) (i915.enable_ppgtt >= 2) -#define USES_FULL_48BIT_PPGTT(dev_priv) (i915.enable_ppgtt == 3) +#define USES_PPGTT(dev_priv) (i915_modparams.enable_ppgtt) +#define USES_FULL_PPGTT(dev_priv) (i915_modparams.enable_ppgtt >= 2) +#define USES_FULL_48BIT_PPGTT(dev_priv) (i915_modparams.enable_ppgtt == 3) +#define HAS_PAGE_SIZES(dev_priv, sizes) ({ \ + GEM_BUG_ON((sizes) == 0); \ + ((sizes) & ~(dev_priv)->info.page_sizes) == 0; \ +}) #define HAS_OVERLAY(dev_priv) ((dev_priv)->info.has_overlay) #define OVERLAY_NEEDS_PHYSICAL(dev_priv) \ @@ -3056,9 +3161,12 @@ intel_info(const struct drm_i915_private *dev_priv) * even when in MSI mode. This results in spurious interrupt warnings if the * legacy irq no. is shared with another device. The kernel then disables that * interrupt source and so prevents the other device from working properly. + * + * Since we don't enable MSI anymore on gen4, we can always use GMBUS/AUX + * interrupts. */ -#define HAS_AUX_IRQ(dev_priv) ((dev_priv)->info.gen >= 5) -#define HAS_GMBUS_IRQ(dev_priv) ((dev_priv)->info.has_gmbus_irq) +#define HAS_AUX_IRQ(dev_priv) true +#define HAS_GMBUS_IRQ(dev_priv) (INTEL_GEN(dev_priv) >= 4) /* With the 945 and later, Y tiling got adjusted so that it was 32 128-byte * rows, which changed the alignment requirements and fence programming. @@ -3070,7 +3178,6 @@ intel_info(const struct drm_i915_private *dev_priv) #define I915_HAS_HOTPLUG(dev_priv) ((dev_priv)->info.has_hotplug) #define HAS_FW_BLC(dev_priv) (INTEL_GEN(dev_priv) > 2) -#define HAS_PIPE_CXSR(dev_priv) ((dev_priv)->info.has_pipe_cxsr) #define HAS_FBC(dev_priv) ((dev_priv)->info.has_fbc) #define HAS_CUR_FBC(dev_priv) (!HAS_GMCH_DISPLAY(dev_priv) && INTEL_INFO(dev_priv)->gen >= 7) @@ -3089,6 +3196,8 @@ intel_info(const struct drm_i915_private *dev_priv) #define HAS_RUNTIME_PM(dev_priv) ((dev_priv)->info.has_runtime_pm) #define HAS_64BIT_RELOC(dev_priv) ((dev_priv)->info.has_64bit_reloc) +#define HAS_IPC(dev_priv) ((dev_priv)->info.has_ipc) + /* * For now, anything with a GuC requires uCode loading, and then supports * command submission once loaded. But these are logically independent @@ -3234,7 +3343,7 @@ static inline void i915_queue_hangcheck(struct drm_i915_private *dev_priv) { unsigned long delay; - if (unlikely(!i915.enable_hangcheck)) + if (unlikely(!i915_modparams.enable_hangcheck)) return; /* Don't continually defer the hangcheck so that it is always run at @@ -3267,6 +3376,8 @@ static inline bool intel_vgpu_active(struct drm_i915_private *dev_priv) return dev_priv->vgpu.active; } +u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, + enum pipe pipe); void i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, u32 status_mask); @@ -3448,7 +3559,8 @@ i915_gem_object_get_dma_address(struct drm_i915_gem_object *obj, unsigned long n); void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, - struct sg_table *pages); + struct sg_table *pages, + unsigned int sg_page_sizes); int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj); static inline int __must_check @@ -3462,10 +3574,16 @@ i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) return __i915_gem_object_get_pages(obj); } +static inline bool +i915_gem_object_has_pages(struct drm_i915_gem_object *obj) +{ + return !IS_ERR_OR_NULL(READ_ONCE(obj->mm.pages)); +} + static inline void __i915_gem_object_pin_pages(struct drm_i915_gem_object *obj) { - GEM_BUG_ON(!obj->mm.pages); + GEM_BUG_ON(!i915_gem_object_has_pages(obj)); atomic_inc(&obj->mm.pages_pin_count); } @@ -3479,8 +3597,8 @@ i915_gem_object_has_pinned_pages(struct drm_i915_gem_object *obj) static inline void __i915_gem_object_unpin_pages(struct drm_i915_gem_object *obj) { + GEM_BUG_ON(!i915_gem_object_has_pages(obj)); GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); - GEM_BUG_ON(!obj->mm.pages); atomic_dec(&obj->mm.pages_pin_count); } @@ -3670,8 +3788,6 @@ i915_vm_to_ppgtt(struct i915_address_space *vm) } /* i915_gem_fence_reg.c */ -int __must_check i915_vma_get_fence(struct i915_vma *vma); -int __must_check i915_vma_put_fence(struct i915_vma *vma); struct drm_i915_fence_reg * i915_reserve_fence(struct drm_i915_private *dev_priv); void i915_unreserve_fence(struct drm_i915_fence_reg *fence); @@ -4360,4 +4476,12 @@ int remap_io_mapping(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, struct io_mapping *iomap); +static inline int intel_hws_csb_write_index(struct drm_i915_private *i915) +{ + if (INTEL_GEN(i915) >= 10) + return CNL_HWS_CSB_WRITE_INDEX; + else + return I915_HWS_CSB_WRITE_INDEX; +} + #endif diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8f074c7f6253..94b23fcbc989 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -35,6 +35,7 @@ #include "intel_drv.h" #include "intel_frontbuffer.h" #include "intel_mocs.h" +#include "i915_gemfs.h" #include <linux/dma-fence-array.h> #include <linux/kthread.h> #include <linux/reservation.h> @@ -55,7 +56,7 @@ static bool cpu_write_needs_clflush(struct drm_i915_gem_object *obj) if (!(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_WRITE)) return true; - return obj->pin_display; + return obj->pin_global; /* currently in use by HW, keep flushed */ } static int @@ -161,8 +162,7 @@ i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data, return 0; } -static struct sg_table * -i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) +static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) { struct address_space *mapping = obj->base.filp->f_mapping; drm_dma_handle_t *phys; @@ -170,19 +170,20 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) struct scatterlist *sg; char *vaddr; int i; + int err; if (WARN_ON(i915_gem_object_needs_bit17_swizzle(obj))) - return ERR_PTR(-EINVAL); + return -EINVAL; /* Always aligning to the object size, allows a single allocation * to handle all possible callers, and given typical object sizes, * the alignment of the buddy allocation will naturally match. */ phys = drm_pci_alloc(obj->base.dev, - obj->base.size, + roundup_pow_of_two(obj->base.size), roundup_pow_of_two(obj->base.size)); if (!phys) - return ERR_PTR(-ENOMEM); + return -ENOMEM; vaddr = phys->vaddr; for (i = 0; i < obj->base.size / PAGE_SIZE; i++) { @@ -191,7 +192,7 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) page = shmem_read_mapping_page(mapping, i); if (IS_ERR(page)) { - st = ERR_CAST(page); + err = PTR_ERR(page); goto err_phys; } @@ -208,13 +209,13 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) st = kmalloc(sizeof(*st), GFP_KERNEL); if (!st) { - st = ERR_PTR(-ENOMEM); + err = -ENOMEM; goto err_phys; } if (sg_alloc_table(st, 1, GFP_KERNEL)) { kfree(st); - st = ERR_PTR(-ENOMEM); + err = -ENOMEM; goto err_phys; } @@ -226,11 +227,15 @@ i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) sg_dma_len(sg) = obj->base.size; obj->phys_handle = phys; - return st; + + __i915_gem_object_set_pages(obj, st, sg->length); + + return 0; err_phys: drm_pci_free(obj->base.dev, phys); - return st; + + return err; } static void __start_cpu_write(struct drm_i915_gem_object *obj) @@ -353,7 +358,7 @@ static long i915_gem_object_wait_fence(struct dma_fence *fence, unsigned int flags, long timeout, - struct intel_rps_client *rps) + struct intel_rps_client *rps_client) { struct drm_i915_gem_request *rq; @@ -386,11 +391,11 @@ i915_gem_object_wait_fence(struct dma_fence *fence, * forcing the clocks too high for the whole system, we only allow * each client to waitboost once in a busy period. */ - if (rps) { + if (rps_client) { if (INTEL_GEN(rq->i915) >= 6) - gen6_rps_boost(rq, rps); + gen6_rps_boost(rq, rps_client); else - rps = NULL; + rps_client = NULL; } timeout = i915_wait_request(rq, flags, timeout); @@ -406,7 +411,7 @@ static long i915_gem_object_wait_reservation(struct reservation_object *resv, unsigned int flags, long timeout, - struct intel_rps_client *rps) + struct intel_rps_client *rps_client) { unsigned int seq = __read_seqcount_begin(&resv->seq); struct dma_fence *excl; @@ -425,7 +430,7 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, for (i = 0; i < count; i++) { timeout = i915_gem_object_wait_fence(shared[i], flags, timeout, - rps); + rps_client); if (timeout < 0) break; @@ -442,7 +447,8 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, } if (excl && timeout >= 0) { - timeout = i915_gem_object_wait_fence(excl, flags, timeout, rps); + timeout = i915_gem_object_wait_fence(excl, flags, timeout, + rps_client); prune_fences = timeout >= 0; } @@ -538,7 +544,7 @@ int i915_gem_object_wait(struct drm_i915_gem_object *obj, unsigned int flags, long timeout, - struct intel_rps_client *rps) + struct intel_rps_client *rps_client) { might_sleep(); #if IS_ENABLED(CONFIG_LOCKDEP) @@ -550,7 +556,7 @@ i915_gem_object_wait(struct drm_i915_gem_object *obj, timeout = i915_gem_object_wait_reservation(obj->resv, flags, timeout, - rps); + rps_client); return timeout < 0 ? timeout : 0; } @@ -558,7 +564,7 @@ static struct intel_rps_client *to_rps_client(struct drm_file *file) { struct drm_i915_file_private *fpriv = file->driver_priv; - return &fpriv->rps; + return &fpriv->rps_client; } static int @@ -694,10 +700,10 @@ flush_write_domain(struct drm_i915_gem_object *obj, unsigned int flush_domains) switch (obj->base.write_domain) { case I915_GEM_DOMAIN_GTT: - if (INTEL_GEN(dev_priv) >= 6 && !HAS_LLC(dev_priv)) { + if (!HAS_LLC(dev_priv)) { intel_runtime_pm_get(dev_priv); spin_lock_irq(&dev_priv->uncore.lock); - POSTING_READ_FW(RING_ACTHD(dev_priv->engine[RCS]->mmio_base)); + POSTING_READ_FW(RING_HEAD(dev_priv->engine[RCS]->mmio_base)); spin_unlock_irq(&dev_priv->uncore.lock); intel_runtime_pm_put(dev_priv); } @@ -1050,7 +1056,9 @@ i915_gem_gtt_pread(struct drm_i915_gem_object *obj, intel_runtime_pm_get(i915); vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, - PIN_MAPPABLE | PIN_NONBLOCK); + PIN_MAPPABLE | + PIN_NONFAULT | + PIN_NONBLOCK); if (!IS_ERR(vma)) { node.start = i915_ggtt_offset(vma); node.allocated = false; @@ -1232,9 +1240,27 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, if (ret) return ret; - intel_runtime_pm_get(i915); + if (i915_gem_object_has_struct_page(obj)) { + /* + * Avoid waking the device up if we can fallback, as + * waking/resuming is very slow (worst-case 10-100 ms + * depending on PCI sleeps and our own resume time). + * This easily dwarfs any performance advantage from + * using the cache bypass of indirect GGTT access. + */ + if (!intel_runtime_pm_get_if_in_use(i915)) { + ret = -EFAULT; + goto out_unlock; + } + } else { + /* No backing pages, no fallback, we must force GGTT access */ + intel_runtime_pm_get(i915); + } + vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, - PIN_MAPPABLE | PIN_NONBLOCK); + PIN_MAPPABLE | + PIN_NONFAULT | + PIN_NONBLOCK); if (!IS_ERR(vma)) { node.start = i915_ggtt_offset(vma); node.allocated = false; @@ -1247,7 +1273,7 @@ i915_gem_gtt_pwrite_fast(struct drm_i915_gem_object *obj, if (IS_ERR(vma)) { ret = insert_mappable_node(ggtt, &node, PAGE_SIZE); if (ret) - goto out_unlock; + goto out_rpm; GEM_BUG_ON(!node.allocated); } @@ -1310,8 +1336,9 @@ out_unpin: } else { i915_vma_unpin(vma); } -out_unlock: +out_rpm: intel_runtime_pm_put(i915); +out_unlock: mutex_unlock(&i915->drm.struct_mutex); return ret; } @@ -1527,6 +1554,8 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj) struct list_head *list; struct i915_vma *vma; + GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); + list_for_each_entry(vma, &obj->vma_list, obj_link) { if (!i915_vma_is_ggtt(vma)) break; @@ -1541,8 +1570,10 @@ static void i915_gem_object_bump_inactive_ggtt(struct drm_i915_gem_object *obj) } i915 = to_i915(obj->base.dev); + spin_lock(&i915->mm.obj_lock); list = obj->bind_count ? &i915->mm.bound_list : &i915->mm.unbound_list; - list_move_tail(&obj->global_link, list); + list_move_tail(&obj->mm.link, list); + spin_unlock(&i915->mm.obj_lock); } /** @@ -1905,22 +1936,27 @@ int i915_gem_fault(struct vm_fault *vmf) if (ret) goto err_unpin; - ret = i915_vma_get_fence(vma); + ret = i915_vma_pin_fence(vma); if (ret) goto err_unpin; - /* Mark as being mmapped into userspace for later revocation */ - assert_rpm_wakelock_held(dev_priv); - if (list_empty(&obj->userfault_link)) - list_add(&obj->userfault_link, &dev_priv->mm.userfault_list); - /* Finally, remap it using the new GTT offset */ ret = remap_io_mapping(area, area->vm_start + (vma->ggtt_view.partial.offset << PAGE_SHIFT), (ggtt->mappable_base + vma->node.start) >> PAGE_SHIFT, min_t(u64, vma->size, area->vm_end - area->vm_start), &ggtt->mappable); + if (ret) + goto err_fence; + + /* Mark as being mmapped into userspace for later revocation */ + assert_rpm_wakelock_held(dev_priv); + if (!i915_vma_set_userfault(vma) && !obj->userfault_count++) + list_add(&obj->userfault_link, &dev_priv->mm.userfault_list); + GEM_BUG_ON(!obj->userfault_count); +err_fence: + i915_vma_unpin_fence(vma); err_unpin: __i915_vma_unpin(vma); err_unlock: @@ -1972,6 +2008,25 @@ err: return ret; } +static void __i915_gem_object_release_mmap(struct drm_i915_gem_object *obj) +{ + struct i915_vma *vma; + + GEM_BUG_ON(!obj->userfault_count); + + obj->userfault_count = 0; + list_del(&obj->userfault_link); + drm_vma_node_unmap(&obj->base.vma_node, + obj->base.dev->anon_inode->i_mapping); + + list_for_each_entry(vma, &obj->vma_list, obj_link) { + if (!i915_vma_is_ggtt(vma)) + break; + + i915_vma_unset_userfault(vma); + } +} + /** * i915_gem_release_mmap - remove physical page mappings * @obj: obj in question @@ -2002,12 +2057,10 @@ i915_gem_release_mmap(struct drm_i915_gem_object *obj) lockdep_assert_held(&i915->drm.struct_mutex); intel_runtime_pm_get(i915); - if (list_empty(&obj->userfault_link)) + if (!obj->userfault_count) goto out; - list_del_init(&obj->userfault_link); - drm_vma_node_unmap(&obj->base.vma_node, - obj->base.dev->anon_inode->i_mapping); + __i915_gem_object_release_mmap(obj); /* Ensure that the CPU's PTE are revoked and there are not outstanding * memory transactions from userspace before we return. The TLB @@ -2035,11 +2088,8 @@ void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv) */ list_for_each_entry_safe(obj, on, - &dev_priv->mm.userfault_list, userfault_link) { - list_del_init(&obj->userfault_link); - drm_vma_node_unmap(&obj->base.vma_node, - obj->base.dev->anon_inode->i_mapping); - } + &dev_priv->mm.userfault_list, userfault_link) + __i915_gem_object_release_mmap(obj); /* The fence will be lost when the device powers down. If any were * in use by hardware (i.e. they are pinned), we should not be powering @@ -2062,7 +2112,7 @@ void i915_gem_runtime_suspend(struct drm_i915_private *dev_priv) if (!reg->vma) continue; - GEM_BUG_ON(!list_empty(®->vma->obj->userfault_link)); + GEM_BUG_ON(i915_vma_has_userfault(reg->vma)); reg->dirty = true; } } @@ -2167,7 +2217,7 @@ void __i915_gem_object_invalidate(struct drm_i915_gem_object *obj) struct address_space *mapping; lockdep_assert_held(&obj->mm.lock); - GEM_BUG_ON(obj->mm.pages); + GEM_BUG_ON(i915_gem_object_has_pages(obj)); switch (obj->mm.madv) { case I915_MADV_DONTNEED: @@ -2224,13 +2274,14 @@ static void __i915_gem_object_reset_page_iter(struct drm_i915_gem_object *obj) void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, enum i915_mm_subclass subclass) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); struct sg_table *pages; if (i915_gem_object_has_pinned_pages(obj)) return; GEM_BUG_ON(obj->bind_count); - if (!READ_ONCE(obj->mm.pages)) + if (!i915_gem_object_has_pages(obj)) return; /* May be called by shrinker from within get_pages() (on another bo) */ @@ -2244,6 +2295,10 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, pages = fetch_and_zero(&obj->mm.pages); GEM_BUG_ON(!pages); + spin_lock(&i915->mm.obj_lock); + list_del(&obj->mm.link); + spin_unlock(&i915->mm.obj_lock); + if (obj->mm.mapping) { void *ptr; @@ -2261,6 +2316,8 @@ void __i915_gem_object_put_pages(struct drm_i915_gem_object *obj, if (!IS_ERR(pages)) obj->ops->put_pages(obj, pages); + obj->mm.page_sizes.phys = obj->mm.page_sizes.sg = 0; + unlock: mutex_unlock(&obj->mm.lock); } @@ -2291,8 +2348,7 @@ static bool i915_sg_trim(struct sg_table *orig_st) return true; } -static struct sg_table * -i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) +static int i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) { struct drm_i915_private *dev_priv = to_i915(obj->base.dev); const unsigned long page_count = obj->base.size / PAGE_SIZE; @@ -2303,7 +2359,8 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) struct sgt_iter sgt_iter; struct page *page; unsigned long last_pfn = 0; /* suppress gcc warning */ - unsigned int max_segment; + unsigned int max_segment = i915_sg_segment_size(); + unsigned int sg_page_sizes; gfp_t noreclaim; int ret; @@ -2314,18 +2371,14 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj) GEM_BUG_ON(obj->base.read_domains & I915_GEM_GPU_DOMAINS); GEM_BUG_ON(obj->base.write_domain & I915_GEM_GPU_DOMAINS); - max_segment = swiotlb_max_segment(); - if (!max_segment) - max_segment = rounddown(UINT_MAX, PAGE_SIZE); - st = kmalloc(sizeof(*st), GFP_KERNEL); if (st == NULL) - return ERR_PTR(-ENOMEM); + return -ENOMEM; rebuild_st: if (sg_alloc_table(st, page_count, GFP_KERNEL)) { kfree(st); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } /* Get the list of pages out of our struct file. They'll be pinned @@ -2339,6 +2392,7 @@ rebuild_st: sg = st->sgl; st->nents = 0; + sg_page_sizes = 0; for (i = 0; i < page_count; i++) { const unsigned int shrink[] = { I915_SHRINK_BOUND | I915_SHRINK_UNBOUND | I915_SHRINK_PURGEABLE, @@ -2391,8 +2445,10 @@ rebuild_st: if (!i || sg->length >= max_segment || page_to_pfn(page) != last_pfn + 1) { - if (i) + if (i) { + sg_page_sizes |= sg->length; sg = sg_next(sg); + } st->nents++; sg_set_page(sg, page, PAGE_SIZE, 0); } else { @@ -2403,8 +2459,10 @@ rebuild_st: /* Check that the i965g/gm workaround works. */ WARN_ON((gfp & __GFP_DMA32) && (last_pfn >= 0x00100000UL)); } - if (sg) /* loop terminated early; short sg table */ + if (sg) { /* loop terminated early; short sg table */ + sg_page_sizes |= sg->length; sg_mark_end(sg); + } /* Trim unused sg entries to avoid wasting memory. */ i915_sg_trim(st); @@ -2433,7 +2491,9 @@ rebuild_st: if (i915_gem_object_needs_bit17_swizzle(obj)) i915_gem_object_do_bit_17_swizzle(obj, st); - return st; + __i915_gem_object_set_pages(obj, st, sg_page_sizes); + + return 0; err_sg: sg_mark_end(sg); @@ -2454,12 +2514,17 @@ err_pages: if (ret == -ENOSPC) ret = -ENOMEM; - return ERR_PTR(ret); + return ret; } void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, - struct sg_table *pages) + struct sg_table *pages, + unsigned int sg_page_sizes) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); + unsigned long supported = INTEL_INFO(i915)->page_sizes; + int i; + lockdep_assert_held(&obj->mm.lock); obj->mm.get_page.sg_pos = pages->sgl; @@ -2468,28 +2533,48 @@ void __i915_gem_object_set_pages(struct drm_i915_gem_object *obj, obj->mm.pages = pages; if (i915_gem_object_is_tiled(obj) && - to_i915(obj->base.dev)->quirks & QUIRK_PIN_SWIZZLED_PAGES) { + i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) { GEM_BUG_ON(obj->mm.quirked); __i915_gem_object_pin_pages(obj); obj->mm.quirked = true; } + + GEM_BUG_ON(!sg_page_sizes); + obj->mm.page_sizes.phys = sg_page_sizes; + + /* + * Calculate the supported page-sizes which fit into the given + * sg_page_sizes. This will give us the page-sizes which we may be able + * to use opportunistically when later inserting into the GTT. For + * example if phys=2G, then in theory we should be able to use 1G, 2M, + * 64K or 4K pages, although in practice this will depend on a number of + * other factors. + */ + obj->mm.page_sizes.sg = 0; + for_each_set_bit(i, &supported, ilog2(I915_GTT_MAX_PAGE_SIZE) + 1) { + if (obj->mm.page_sizes.phys & ~0u << i) + obj->mm.page_sizes.sg |= BIT(i); + } + GEM_BUG_ON(!HAS_PAGE_SIZES(i915, obj->mm.page_sizes.sg)); + + spin_lock(&i915->mm.obj_lock); + list_add(&obj->mm.link, &i915->mm.unbound_list); + spin_unlock(&i915->mm.obj_lock); } static int ____i915_gem_object_get_pages(struct drm_i915_gem_object *obj) { - struct sg_table *pages; + int err; if (unlikely(obj->mm.madv != I915_MADV_WILLNEED)) { DRM_DEBUG("Attempting to obtain a purgeable object\n"); return -EFAULT; } - pages = obj->ops->get_pages(obj); - if (unlikely(IS_ERR(pages))) - return PTR_ERR(pages); + err = obj->ops->get_pages(obj); + GEM_BUG_ON(!err && IS_ERR_OR_NULL(obj->mm.pages)); - __i915_gem_object_set_pages(obj, pages); - return 0; + return err; } /* Ensure that the associated pages are gathered from the backing storage @@ -2507,7 +2592,7 @@ int __i915_gem_object_get_pages(struct drm_i915_gem_object *obj) if (err) return err; - if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) { + if (unlikely(!i915_gem_object_has_pages(obj))) { GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj)); err = ____i915_gem_object_get_pages(obj); @@ -2592,7 +2677,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, type &= ~I915_MAP_OVERRIDE; if (!atomic_inc_not_zero(&obj->mm.pages_pin_count)) { - if (unlikely(IS_ERR_OR_NULL(obj->mm.pages))) { + if (unlikely(!i915_gem_object_has_pages(obj))) { GEM_BUG_ON(i915_gem_object_has_pinned_pages(obj)); ret = ____i915_gem_object_get_pages(obj); @@ -2604,7 +2689,7 @@ void *i915_gem_object_pin_map(struct drm_i915_gem_object *obj, atomic_inc(&obj->mm.pages_pin_count); pinned = false; } - GEM_BUG_ON(!obj->mm.pages); + GEM_BUG_ON(!i915_gem_object_has_pages(obj)); ptr = page_unpack_bits(obj->mm.mapping, &has_type); if (ptr && has_type != type) { @@ -2659,9 +2744,12 @@ i915_gem_object_pwrite_gtt(struct drm_i915_gem_object *obj, * allows it to avoid the cost of retrieving a page (either swapin * or clearing-before-use) before it is overwritten. */ - if (READ_ONCE(obj->mm.pages)) + if (i915_gem_object_has_pages(obj)) return -ENODEV; + if (obj->mm.madv != I915_MADV_WILLNEED) + return -EFAULT; + /* Before the pages are instantiated the object is treated as being * in the CPU domain. The pages will be clflushed as required before * use, and we can freely write into the pages directly. If userspace @@ -2800,7 +2888,17 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine) { struct drm_i915_gem_request *request = NULL; - /* Prevent the signaler thread from updating the request + /* + * During the reset sequence, we must prevent the engine from + * entering RC6. As the context state is undefined until we restart + * the engine, if it does enter RC6 during the reset, the state + * written to the powercontext is undefined and so we may lose + * GPU state upon resume, i.e. fail to restart after a reset. + */ + intel_uncore_forcewake_get(engine->i915, FORCEWAKE_ALL); + + /* + * Prevent the signaler thread from updating the request * state (by calling dma_fence_signal) as we are processing * the reset. The write from the GPU of the seqno is * asynchronous and the signaler thread may see a different @@ -2811,7 +2909,8 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine) */ kthread_park(engine->breadcrumbs.signaler); - /* Prevent request submission to the hardware until we have + /* + * Prevent request submission to the hardware until we have * completed the reset in i915_gem_reset_finish(). If a request * is completed by one engine, it may then queue a request * to a second via its engine->irq_tasklet *just* as we are @@ -2819,8 +2918,8 @@ i915_gem_reset_prepare_engine(struct intel_engine_cs *engine) * Turning off the engine->irq_tasklet until the reset is over * prevents the race. */ - tasklet_kill(&engine->irq_tasklet); - tasklet_disable(&engine->irq_tasklet); + tasklet_kill(&engine->execlists.irq_tasklet); + tasklet_disable(&engine->execlists.irq_tasklet); if (engine->irq_seqno_barrier) engine->irq_seqno_barrier(engine); @@ -2999,8 +3098,10 @@ void i915_gem_reset(struct drm_i915_private *dev_priv) void i915_gem_reset_finish_engine(struct intel_engine_cs *engine) { - tasklet_enable(&engine->irq_tasklet); + tasklet_enable(&engine->execlists.irq_tasklet); kthread_unpark(engine->breadcrumbs.signaler); + + intel_uncore_forcewake_put(engine->i915, FORCEWAKE_ALL); } void i915_gem_reset_finish(struct drm_i915_private *dev_priv) @@ -3018,87 +3119,76 @@ void i915_gem_reset_finish(struct drm_i915_private *dev_priv) static void nop_submit_request(struct drm_i915_gem_request *request) { - GEM_BUG_ON(!i915_terminally_wedged(&request->i915->gpu_error)); dma_fence_set_error(&request->fence, -EIO); + i915_gem_request_submit(request); - intel_engine_init_global_seqno(request->engine, request->global_seqno); } -static void engine_set_wedged(struct intel_engine_cs *engine) +static void nop_complete_submit_request(struct drm_i915_gem_request *request) { - struct drm_i915_gem_request *request; unsigned long flags; - /* We need to be sure that no thread is running the old callback as - * we install the nop handler (otherwise we would submit a request - * to hardware that will never complete). In order to prevent this - * race, we wait until the machine is idle before making the swap - * (using stop_machine()). - */ - engine->submit_request = nop_submit_request; + dma_fence_set_error(&request->fence, -EIO); - /* Mark all executing requests as skipped */ - spin_lock_irqsave(&engine->timeline->lock, flags); - list_for_each_entry(request, &engine->timeline->requests, link) - if (!i915_gem_request_completed(request)) - dma_fence_set_error(&request->fence, -EIO); - spin_unlock_irqrestore(&engine->timeline->lock, flags); + spin_lock_irqsave(&request->engine->timeline->lock, flags); + __i915_gem_request_submit(request); + intel_engine_init_global_seqno(request->engine, request->global_seqno); + spin_unlock_irqrestore(&request->engine->timeline->lock, flags); +} + +void i915_gem_set_wedged(struct drm_i915_private *i915) +{ + struct intel_engine_cs *engine; + enum intel_engine_id id; /* - * Clear the execlists queue up before freeing the requests, as those - * are the ones that keep the context and ringbuffer backing objects - * pinned in place. + * First, stop submission to hw, but do not yet complete requests by + * rolling the global seqno forward (since this would complete requests + * for which we haven't set the fence error to EIO yet). */ + for_each_engine(engine, i915, id) + engine->submit_request = nop_submit_request; - if (i915.enable_execlists) { - struct execlist_port *port = engine->execlist_port; - unsigned long flags; - unsigned int n; - - spin_lock_irqsave(&engine->timeline->lock, flags); - - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) - i915_gem_request_put(port_request(&port[n])); - memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); - engine->execlist_queue = RB_ROOT; - engine->execlist_first = NULL; + /* + * Make sure no one is running the old callback before we proceed with + * cancelling requests and resetting the completion tracking. Otherwise + * we might submit a request to the hardware which never completes. + */ + synchronize_rcu(); - spin_unlock_irqrestore(&engine->timeline->lock, flags); + for_each_engine(engine, i915, id) { + /* Mark all executing requests as skipped */ + engine->cancel_requests(engine); - /* The port is checked prior to scheduling a tasklet, but - * just in case we have suspended the tasklet to do the - * wedging make sure that when it wakes, it decides there - * is no work to do by clearing the irq_posted bit. + /* + * Only once we've force-cancelled all in-flight requests can we + * start to complete all requests. */ - clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); + engine->submit_request = nop_complete_submit_request; } - /* Mark all pending requests as complete so that any concurrent - * (lockless) lookup doesn't try and wait upon the request as we - * reset it. + /* + * Make sure no request can slip through without getting completed by + * either this call here to intel_engine_init_global_seqno, or the one + * in nop_complete_submit_request. */ - intel_engine_init_global_seqno(engine, - intel_engine_last_submit(engine)); -} + synchronize_rcu(); -static int __i915_gem_set_wedged_BKL(void *data) -{ - struct drm_i915_private *i915 = data; - struct intel_engine_cs *engine; - enum intel_engine_id id; + for_each_engine(engine, i915, id) { + unsigned long flags; - for_each_engine(engine, i915, id) - engine_set_wedged(engine); + /* Mark all pending requests as complete so that any concurrent + * (lockless) lookup doesn't try and wait upon the request as we + * reset it. + */ + spin_lock_irqsave(&engine->timeline->lock, flags); + intel_engine_init_global_seqno(engine, + intel_engine_last_submit(engine)); + spin_unlock_irqrestore(&engine->timeline->lock, flags); + } set_bit(I915_WEDGED, &i915->gpu_error.flags); wake_up_all(&i915->gpu_error.reset_queue); - - return 0; -} - -void i915_gem_set_wedged(struct drm_i915_private *dev_priv) -{ - stop_machine(__i915_gem_set_wedged_BKL, dev_priv, NULL); } bool i915_gem_unset_wedged(struct drm_i915_private *i915) @@ -3435,7 +3525,7 @@ static void __i915_gem_object_flush_for_display(struct drm_i915_gem_object *obj) void i915_gem_object_flush_if_display(struct drm_i915_gem_object *obj) { - if (!READ_ONCE(obj->pin_display)) + if (!READ_ONCE(obj->pin_global)) return; mutex_lock(&obj->base.dev->struct_mutex); @@ -3802,10 +3892,10 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, lockdep_assert_held(&obj->base.dev->struct_mutex); - /* Mark the pin_display early so that we account for the + /* Mark the global pin early so that we account for the * display coherency whilst setting up the cache domains. */ - obj->pin_display++; + obj->pin_global++; /* The display engine is not coherent with the LLC cache on gen6. As * a result, we make sure that the pinning that is about to occur is @@ -3821,7 +3911,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, I915_CACHE_WT : I915_CACHE_NONE); if (ret) { vma = ERR_PTR(ret); - goto err_unpin_display; + goto err_unpin_global; } /* As the user may map the buffer once pinned in the display plane @@ -3852,7 +3942,7 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, vma = i915_gem_object_ggtt_pin(obj, view, 0, alignment, flags); } if (IS_ERR(vma)) - goto err_unpin_display; + goto err_unpin_global; vma->display_alignment = max_t(u64, vma->display_alignment, alignment); @@ -3867,8 +3957,8 @@ i915_gem_object_pin_to_display_plane(struct drm_i915_gem_object *obj, return vma; -err_unpin_display: - obj->pin_display--; +err_unpin_global: + obj->pin_global--; return vma; } @@ -3877,10 +3967,10 @@ i915_gem_object_unpin_from_display_plane(struct i915_vma *vma) { lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); - if (WARN_ON(vma->obj->pin_display == 0)) + if (WARN_ON(vma->obj->pin_global == 0)) return; - if (--vma->obj->pin_display == 0) + if (--vma->obj->pin_global == 0) vma->display_alignment = I915_GTT_MIN_ALIGNMENT; /* Bump the LRU to try and avoid premature eviction whilst flipping */ @@ -3999,42 +4089,47 @@ i915_gem_object_ggtt_pin(struct drm_i915_gem_object *obj, lockdep_assert_held(&obj->base.dev->struct_mutex); + if (!view && flags & PIN_MAPPABLE) { + /* If the required space is larger than the available + * aperture, we will not able to find a slot for the + * object and unbinding the object now will be in + * vain. Worse, doing so may cause us to ping-pong + * the object in and out of the Global GTT and + * waste a lot of cycles under the mutex. + */ + if (obj->base.size > dev_priv->ggtt.mappable_end) + return ERR_PTR(-E2BIG); + + /* If NONBLOCK is set the caller is optimistically + * trying to cache the full object within the mappable + * aperture, and *must* have a fallback in place for + * situations where we cannot bind the object. We + * can be a little more lax here and use the fallback + * more often to avoid costly migrations of ourselves + * and other objects within the aperture. + * + * Half-the-aperture is used as a simple heuristic. + * More interesting would to do search for a free + * block prior to making the commitment to unbind. + * That caters for the self-harm case, and with a + * little more heuristics (e.g. NOFAULT, NOEVICT) + * we could try to minimise harm to others. + */ + if (flags & PIN_NONBLOCK && + obj->base.size > dev_priv->ggtt.mappable_end / 2) + return ERR_PTR(-ENOSPC); + } + vma = i915_vma_instance(obj, vm, view); if (unlikely(IS_ERR(vma))) return vma; if (i915_vma_misplaced(vma, size, alignment, flags)) { - if (flags & PIN_NONBLOCK && - (i915_vma_is_pinned(vma) || i915_vma_is_active(vma))) - return ERR_PTR(-ENOSPC); + if (flags & PIN_NONBLOCK) { + if (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)) + return ERR_PTR(-ENOSPC); - if (flags & PIN_MAPPABLE) { - /* If the required space is larger than the available - * aperture, we will not able to find a slot for the - * object and unbinding the object now will be in - * vain. Worse, doing so may cause us to ping-pong - * the object in and out of the Global GTT and - * waste a lot of cycles under the mutex. - */ - if (vma->fence_size > dev_priv->ggtt.mappable_end) - return ERR_PTR(-E2BIG); - - /* If NONBLOCK is set the caller is optimistically - * trying to cache the full object within the mappable - * aperture, and *must* have a fallback in place for - * situations where we cannot bind the object. We - * can be a little more lax here and use the fallback - * more often to avoid costly migrations of ourselves - * and other objects within the aperture. - * - * Half-the-aperture is used as a simple heuristic. - * More interesting would to do search for a free - * block prior to making the commitment to unbind. - * That caters for the self-harm case, and with a - * little more heuristics (e.g. NOFAULT, NOEVICT) - * we could try to minimise harm to others. - */ - if (flags & PIN_NONBLOCK && + if (flags & PIN_MAPPABLE && vma->fence_size > dev_priv->ggtt.mappable_end / 2) return ERR_PTR(-ENOSPC); } @@ -4215,7 +4310,7 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, if (err) goto out; - if (obj->mm.pages && + if (i915_gem_object_has_pages(obj) && i915_gem_object_is_tiled(obj) && dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES) { if (obj->mm.madv == I915_MADV_WILLNEED) { @@ -4234,7 +4329,8 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data, obj->mm.madv = args->madv; /* if the object is no longer attached, discard its backing storage */ - if (obj->mm.madv == I915_MADV_DONTNEED && !obj->mm.pages) + if (obj->mm.madv == I915_MADV_DONTNEED && + !i915_gem_object_has_pages(obj)) i915_gem_object_truncate(obj); args->retained = obj->mm.madv != __I915_MADV_PURGED; @@ -4260,8 +4356,6 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj, { mutex_init(&obj->mm.lock); - INIT_LIST_HEAD(&obj->global_link); - INIT_LIST_HEAD(&obj->userfault_link); INIT_LIST_HEAD(&obj->vma_list); INIT_LIST_HEAD(&obj->lut_list); INIT_LIST_HEAD(&obj->batch_pool_link); @@ -4291,6 +4385,30 @@ static const struct drm_i915_gem_object_ops i915_gem_object_ops = { .pwrite = i915_gem_object_pwrite_gtt, }; +static int i915_gem_object_create_shmem(struct drm_device *dev, + struct drm_gem_object *obj, + size_t size) +{ + struct drm_i915_private *i915 = to_i915(dev); + unsigned long flags = VM_NORESERVE; + struct file *filp; + + drm_gem_private_object_init(dev, obj, size); + + if (i915->mm.gemfs) + filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size, + flags); + else + filp = shmem_file_setup("i915", size, flags); + + if (IS_ERR(filp)) + return PTR_ERR(filp); + + obj->filp = filp; + + return 0; +} + struct drm_i915_gem_object * i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size) { @@ -4315,7 +4433,7 @@ i915_gem_object_create(struct drm_i915_private *dev_priv, u64 size) if (obj == NULL) return ERR_PTR(-ENOMEM); - ret = drm_gem_object_init(&dev_priv->drm, &obj->base, size); + ret = i915_gem_object_create_shmem(&dev_priv->drm, &obj->base, size); if (ret) goto fail; @@ -4392,13 +4510,14 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, { struct drm_i915_gem_object *obj, *on; - mutex_lock(&i915->drm.struct_mutex); intel_runtime_pm_get(i915); - llist_for_each_entry(obj, freed, freed) { + llist_for_each_entry_safe(obj, on, freed, freed) { struct i915_vma *vma, *vn; trace_i915_gem_object_destroy(obj); + mutex_lock(&i915->drm.struct_mutex); + GEM_BUG_ON(i915_gem_object_is_active(obj)); list_for_each_entry_safe(vma, vn, &obj->vma_list, obj_link) { @@ -4409,15 +4528,22 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, GEM_BUG_ON(!list_empty(&obj->vma_list)); GEM_BUG_ON(!RB_EMPTY_ROOT(&obj->vma_tree)); - list_del(&obj->global_link); - } - intel_runtime_pm_put(i915); - mutex_unlock(&i915->drm.struct_mutex); + /* This serializes freeing with the shrinker. Since the free + * is delayed, first by RCU then by the workqueue, we want the + * shrinker to be able to free pages of unreferenced objects, + * or else we may oom whilst there are plenty of deferred + * freed objects. + */ + if (i915_gem_object_has_pages(obj)) { + spin_lock(&i915->mm.obj_lock); + list_del_init(&obj->mm.link); + spin_unlock(&i915->mm.obj_lock); + } - cond_resched(); + mutex_unlock(&i915->drm.struct_mutex); - llist_for_each_entry_safe(obj, on, freed, freed) { GEM_BUG_ON(obj->bind_count); + GEM_BUG_ON(obj->userfault_count); GEM_BUG_ON(atomic_read(&obj->frontbuffer_bits)); GEM_BUG_ON(!list_empty(&obj->lut_list)); @@ -4427,7 +4553,7 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, if (WARN_ON(i915_gem_object_has_pinned_pages(obj))) atomic_set(&obj->mm.pages_pin_count, 0); __i915_gem_object_put_pages(obj, I915_MM_NORMAL); - GEM_BUG_ON(obj->mm.pages); + GEM_BUG_ON(i915_gem_object_has_pages(obj)); if (obj->base.import_attach) drm_prime_gem_destroy(&obj->base, NULL); @@ -4438,16 +4564,29 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915, kfree(obj->bit_17); i915_gem_object_free(obj); + + if (on) + cond_resched(); } + intel_runtime_pm_put(i915); } static void i915_gem_flush_free_objects(struct drm_i915_private *i915) { struct llist_node *freed; - freed = llist_del_all(&i915->mm.free_list); - if (unlikely(freed)) + /* Free the oldest, most stale object to keep the free_list short */ + freed = NULL; + if (!llist_empty(&i915->mm.free_list)) { /* quick test for hotpath */ + /* Only one consumer of llist_del_first() allowed */ + spin_lock(&i915->mm.free_lock); + freed = llist_del_first(&i915->mm.free_list); + spin_unlock(&i915->mm.free_lock); + } + if (unlikely(freed)) { + freed->next = NULL; __i915_gem_free_objects(i915, freed); + } } static void __i915_gem_free_work(struct work_struct *work) @@ -4464,11 +4603,17 @@ static void __i915_gem_free_work(struct work_struct *work) * unbound now. */ + spin_lock(&i915->mm.free_lock); while ((freed = llist_del_all(&i915->mm.free_list))) { + spin_unlock(&i915->mm.free_lock); + __i915_gem_free_objects(i915, freed); if (need_resched()) - break; + return; + + spin_lock(&i915->mm.free_lock); } + spin_unlock(&i915->mm.free_lock); } static void __i915_gem_free_object_rcu(struct rcu_head *head) @@ -4587,8 +4732,7 @@ int i915_gem_suspend(struct drm_i915_private *dev_priv) /* As the idle_work is rearming if it detects a race, play safe and * repeat the flush until it is definitely idle. */ - while (flush_delayed_work(&dev_priv->gt.idle_work)) - ; + drain_delayed_work(&dev_priv->gt.idle_work); /* Assert that we sucessfully flushed all the work and * reset the GPU back to its idle, low power state. @@ -4635,6 +4779,7 @@ void i915_gem_resume(struct drm_i915_private *dev_priv) mutex_lock(&dev->struct_mutex); i915_gem_restore_gtt_mappings(dev_priv); + i915_gem_restore_fences(dev_priv); /* As we didn't flush the kernel context before suspend, we cannot * guarantee that the context image is complete. So let's just reset @@ -4748,6 +4893,10 @@ int i915_gem_init_hw(struct drm_i915_private *dev_priv) init_unused_rings(dev_priv); BUG_ON(!dev_priv->kernel_context); + if (i915_terminally_wedged(&dev_priv->gpu_error)) { + ret = -EIO; + goto out; + } ret = i915_ppgtt_init_hw(dev_priv); if (ret) { @@ -4778,7 +4927,7 @@ bool intel_sanitize_semaphores(struct drm_i915_private *dev_priv, int value) return false; /* TODO: make semaphores and Execlists play nicely together */ - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) return false; if (value >= 0) @@ -4797,9 +4946,18 @@ int i915_gem_init(struct drm_i915_private *dev_priv) mutex_lock(&dev_priv->drm.struct_mutex); + /* + * We need to fallback to 4K pages since gvt gtt handling doesn't + * support huge page entries - we will need to check either hypervisor + * mm can support huge guest page or just do emulation in gvt. + */ + if (intel_vgpu_active(dev_priv)) + mkwrite_device_info(dev_priv)->page_sizes = + I915_GTT_PAGE_SIZE_4K; + dev_priv->mm.unordered_timeline = dma_fence_context_alloc(1); - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { dev_priv->gt.resume = intel_legacy_submission_resume; dev_priv->gt.cleanup_engine = intel_engine_cleanup; } else { @@ -4837,8 +4995,10 @@ int i915_gem_init(struct drm_i915_private *dev_priv) * wedged. But we only want to do this where the GPU is angry, * for all other failure, such as an allocation failure, bail. */ - DRM_ERROR("Failed to initialize GPU, declaring it wedged\n"); - i915_gem_set_wedged(dev_priv); + if (!i915_terminally_wedged(&dev_priv->gpu_error)) { + DRM_ERROR("Failed to initialize GPU, declaring it wedged\n"); + i915_gem_set_wedged(dev_priv); + } ret = 0; } @@ -4938,11 +5098,15 @@ i915_gem_load_init(struct drm_i915_private *dev_priv) goto err_priorities; INIT_WORK(&dev_priv->mm.free_work, __i915_gem_free_work); + + spin_lock_init(&dev_priv->mm.obj_lock); + spin_lock_init(&dev_priv->mm.free_lock); init_llist_head(&dev_priv->mm.free_list); INIT_LIST_HEAD(&dev_priv->mm.unbound_list); INIT_LIST_HEAD(&dev_priv->mm.bound_list); INIT_LIST_HEAD(&dev_priv->mm.fence_list); INIT_LIST_HEAD(&dev_priv->mm.userfault_list); + INIT_DELAYED_WORK(&dev_priv->gt.retire_work, i915_gem_retire_work_handler); INIT_DELAYED_WORK(&dev_priv->gt.idle_work, @@ -4954,6 +5118,10 @@ i915_gem_load_init(struct drm_i915_private *dev_priv) spin_lock_init(&dev_priv->fb_tracking.lock); + err = i915_gemfs_init(dev_priv); + if (err) + DRM_NOTE("Unable to create a private tmpfs mount, hugepage support will be disabled(%d).\n", err); + return 0; err_priorities: @@ -4992,6 +5160,8 @@ void i915_gem_load_cleanup(struct drm_i915_private *dev_priv) /* And ensure that our DESTROY_BY_RCU slabs are truly destroyed */ rcu_barrier(); + + i915_gemfs_fini(dev_priv); } int i915_gem_freeze(struct drm_i915_private *dev_priv) @@ -5030,12 +5200,12 @@ int i915_gem_freeze_late(struct drm_i915_private *dev_priv) i915_gem_shrink(dev_priv, -1UL, NULL, I915_SHRINK_UNBOUND); i915_gem_drain_freed_objects(dev_priv); - mutex_lock(&dev_priv->drm.struct_mutex); + spin_lock(&dev_priv->mm.obj_lock); for (p = phases; *p; p++) { - list_for_each_entry(obj, *p, global_link) + list_for_each_entry(obj, *p, mm.link) __start_cpu_write(obj); } - mutex_unlock(&dev_priv->drm.struct_mutex); + spin_unlock(&dev_priv->mm.obj_lock); return 0; } @@ -5354,7 +5524,17 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align) goto err_unlock; } - pages = obj->mm.pages; + pages = fetch_and_zero(&obj->mm.pages); + if (pages) { + struct drm_i915_private *i915 = to_i915(obj->base.dev); + + __i915_gem_object_reset_page_iter(obj); + + spin_lock(&i915->mm.obj_lock); + list_del(&obj->mm.link); + spin_unlock(&i915->mm.obj_lock); + } + obj->ops = &i915_gem_phys_ops; err = ____i915_gem_object_get_pages(obj); @@ -5381,6 +5561,7 @@ err_unlock: #include "selftests/scatterlist.c" #include "selftests/mock_gem_device.c" #include "selftests/huge_gem_object.c" +#include "selftests/huge_pages.c" #include "selftests/i915_gem_object.c" #include "selftests/i915_gem_coherency.c" #endif diff --git a/drivers/gpu/drm/i915/i915_gem_clflush.c b/drivers/gpu/drm/i915/i915_gem_clflush.c index 8a04d33055be..f663cd919795 100644 --- a/drivers/gpu/drm/i915/i915_gem_clflush.c +++ b/drivers/gpu/drm/i915/i915_gem_clflush.c @@ -70,6 +70,7 @@ static const struct dma_fence_ops i915_clflush_ops = { static void __i915_do_clflush(struct drm_i915_gem_object *obj) { + GEM_BUG_ON(!i915_gem_object_has_pages(obj)); drm_clflush_sg(obj->mm.pages); intel_fb_obj_flush(obj, ORIGIN_CPU); } diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index 58a2a44f88bd..e304dcbc6042 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -106,14 +106,9 @@ static void lut_close(struct i915_gem_context *ctx) radix_tree_for_each_slot(slot, &ctx->handles_vma, &iter, 0) { struct i915_vma *vma = rcu_dereference_raw(*slot); - struct drm_i915_gem_object *obj = vma->obj; radix_tree_iter_delete(&ctx->handles_vma, &iter, slot); - - if (!i915_vma_is_ggtt(vma)) - i915_vma_close(vma); - - __i915_gem_object_release_unless_active(obj); + __i915_gem_object_release_unless_active(vma->obj); } } @@ -198,6 +193,11 @@ static void context_close(struct i915_gem_context *ctx) { i915_gem_context_set_closed(ctx); + /* + * The LUT uses the VMA as a backpointer to unref the object, + * so we need to clear the LUT before we close all the VMA (inside + * the ppgtt). + */ lut_close(ctx); if (ctx->ppgtt) i915_ppgtt_close(&ctx->ppgtt->base); @@ -314,7 +314,7 @@ __create_hw_context(struct drm_i915_private *dev_priv, * present or not in use we still need a small bias as ring wraparound * at offset 0 sometimes hangs. No idea why. */ - if (HAS_GUC(dev_priv) && i915.enable_guc_loading) + if (HAS_GUC(dev_priv) && i915_modparams.enable_guc_loading) ctx->ggtt_offset_bias = GUC_WOPCM_TOP; else ctx->ggtt_offset_bias = I915_GTT_PAGE_SIZE; @@ -407,7 +407,7 @@ i915_gem_context_create_gvt(struct drm_device *dev) i915_gem_context_set_closed(ctx); /* not user accessible */ i915_gem_context_clear_bannable(ctx); i915_gem_context_set_force_single_submission(ctx); - if (!i915.enable_guc_submission) + if (!i915_modparams.enable_guc_submission) ctx->ring_size = 512 * PAGE_SIZE; /* Max ring buffer size */ GEM_BUG_ON(i915_gem_context_is_kernel(ctx)); @@ -416,14 +416,43 @@ out: return ctx; } +static struct i915_gem_context * +create_kernel_context(struct drm_i915_private *i915, int prio) +{ + struct i915_gem_context *ctx; + + ctx = i915_gem_create_context(i915, NULL); + if (IS_ERR(ctx)) + return ctx; + + i915_gem_context_clear_bannable(ctx); + ctx->priority = prio; + ctx->ring_size = PAGE_SIZE; + + GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); + + return ctx; +} + +static void +destroy_kernel_context(struct i915_gem_context **ctxp) +{ + struct i915_gem_context *ctx; + + /* Keep the context ref so that we can free it immediately ourselves */ + ctx = i915_gem_context_get(fetch_and_zero(ctxp)); + GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); + + context_close(ctx); + i915_gem_context_free(ctx); +} + int i915_gem_contexts_init(struct drm_i915_private *dev_priv) { struct i915_gem_context *ctx; + int err; - /* Init should only be called once per module load. Eventually the - * restriction on the context_disabled check can be loosened. */ - if (WARN_ON(dev_priv->kernel_context)) - return 0; + GEM_BUG_ON(dev_priv->kernel_context); INIT_LIST_HEAD(&dev_priv->contexts.list); INIT_WORK(&dev_priv->contexts.free_work, contexts_free_worker); @@ -431,7 +460,7 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) if (intel_vgpu_active(dev_priv) && HAS_LOGICAL_RING_CONTEXTS(dev_priv)) { - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { DRM_INFO("Only EXECLIST mode is supported in vgpu.\n"); return -EINVAL; } @@ -441,28 +470,38 @@ int i915_gem_contexts_init(struct drm_i915_private *dev_priv) BUILD_BUG_ON(MAX_CONTEXT_HW_ID > INT_MAX); ida_init(&dev_priv->contexts.hw_ida); - ctx = i915_gem_create_context(dev_priv, NULL); + /* lowest priority; idle task */ + ctx = create_kernel_context(dev_priv, I915_PRIORITY_MIN); if (IS_ERR(ctx)) { - DRM_ERROR("Failed to create default global context (error %ld)\n", - PTR_ERR(ctx)); - return PTR_ERR(ctx); + DRM_ERROR("Failed to create default global context\n"); + err = PTR_ERR(ctx); + goto err; } - - /* For easy recognisablity, we want the kernel context to be 0 and then + /* + * For easy recognisablity, we want the kernel context to be 0 and then * all user contexts will have non-zero hw_id. */ GEM_BUG_ON(ctx->hw_id); - - i915_gem_context_clear_bannable(ctx); - ctx->priority = I915_PRIORITY_MIN; /* lowest priority; idle task */ dev_priv->kernel_context = ctx; - GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); + /* highest priority; preempting task */ + ctx = create_kernel_context(dev_priv, INT_MAX); + if (IS_ERR(ctx)) { + DRM_ERROR("Failed to create default preempt context\n"); + err = PTR_ERR(ctx); + goto err_kernel_context; + } + dev_priv->preempt_context = ctx; DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->engine[RCS]->context_size ? "logical" : "fake"); return 0; + +err_kernel_context: + destroy_kernel_context(&dev_priv->kernel_context); +err: + return err; } void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) @@ -483,7 +522,7 @@ void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) } /* Force the GPU state to be restored on enabling */ - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { struct i915_gem_context *ctx; list_for_each_entry(ctx, &dev_priv->contexts.list, link) { @@ -507,15 +546,10 @@ void i915_gem_contexts_lost(struct drm_i915_private *dev_priv) void i915_gem_contexts_fini(struct drm_i915_private *i915) { - struct i915_gem_context *ctx; - lockdep_assert_held(&i915->drm.struct_mutex); - /* Keep the context so that we can free it immediately ourselves */ - ctx = i915_gem_context_get(fetch_and_zero(&i915->kernel_context)); - GEM_BUG_ON(!i915_gem_context_is_kernel(ctx)); - context_close(ctx); - i915_gem_context_free(ctx); + destroy_kernel_context(&i915->preempt_context); + destroy_kernel_context(&i915->kernel_context); /* Must free all deferred contexts (via flush_workqueue) first */ ida_destroy(&i915->contexts.hw_ida); @@ -568,7 +602,7 @@ mi_set_context(struct drm_i915_gem_request *req, u32 flags) enum intel_engine_id id; const int num_rings = /* Use an extended w/a on gen7 if signalling from other rings */ - (i915.semaphores && INTEL_GEN(dev_priv) == 7) ? + (i915_modparams.semaphores && INTEL_GEN(dev_priv) == 7) ? INTEL_INFO(dev_priv)->num_rings - 1 : 0; int len; @@ -837,7 +871,7 @@ int i915_switch_context(struct drm_i915_gem_request *req) struct intel_engine_cs *engine = req->engine; lockdep_assert_held(&req->i915->drm.struct_mutex); - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) return 0; if (!req->ctx->engine[engine->id].state) { @@ -1036,6 +1070,9 @@ int i915_gem_context_getparam_ioctl(struct drm_device *dev, void *data, case I915_CONTEXT_PARAM_BANNABLE: args->value = i915_gem_context_is_bannable(ctx); break; + case I915_CONTEXT_PARAM_PRIORITY: + args->value = ctx->priority; + break; default: ret = -EINVAL; break; @@ -1091,6 +1128,26 @@ int i915_gem_context_setparam_ioctl(struct drm_device *dev, void *data, else i915_gem_context_clear_bannable(ctx); break; + + case I915_CONTEXT_PARAM_PRIORITY: + { + int priority = args->value; + + if (args->size) + ret = -EINVAL; + else if (!to_i915(dev)->engine[RCS]->schedule) + ret = -ENODEV; + else if (priority > I915_CONTEXT_MAX_USER_PRIORITY || + priority < I915_CONTEXT_MIN_USER_PRIORITY) + ret = -EINVAL; + else if (priority > I915_CONTEXT_DEFAULT_PRIORITY && + !capable(CAP_SYS_NICE)) + ret = -EPERM; + else + ctx->priority = priority; + } + break; + default: ret = -EINVAL; break; diff --git a/drivers/gpu/drm/i915/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/i915_gem_dmabuf.c index 6176e589cf09..864439a214c8 100644 --- a/drivers/gpu/drm/i915/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/i915_gem_dmabuf.c @@ -256,11 +256,21 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, return drm_gem_dmabuf_export(dev, &exp_info); } -static struct sg_table * -i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) +static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) { - return dma_buf_map_attachment(obj->base.import_attach, - DMA_BIDIRECTIONAL); + struct sg_table *pages; + unsigned int sg_page_sizes; + + pages = dma_buf_map_attachment(obj->base.import_attach, + DMA_BIDIRECTIONAL); + if (IS_ERR(pages)) + return PTR_ERR(pages); + + sg_page_sizes = i915_sg_page_sizes(pages->sgl); + + __i915_gem_object_set_pages(obj, pages, sg_page_sizes); + + return 0; } static void i915_gem_object_put_pages_dmabuf(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c index 4df039ef2ce3..8daa8a78cdc0 100644 --- a/drivers/gpu/drm/i915/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/i915_gem_evict.c @@ -33,21 +33,24 @@ #include "intel_drv.h" #include "i915_trace.h" -static bool ggtt_is_idle(struct drm_i915_private *dev_priv) +I915_SELFTEST_DECLARE(static struct igt_evict_ctl { + bool fail_if_busy:1; +} igt_evict_ctl;) + +static bool ggtt_is_idle(struct drm_i915_private *i915) { - struct i915_ggtt *ggtt = &dev_priv->ggtt; - struct intel_engine_cs *engine; - enum intel_engine_id id; + struct intel_engine_cs *engine; + enum intel_engine_id id; - for_each_engine(engine, dev_priv, id) { - struct intel_timeline *tl; + if (i915->gt.active_requests) + return false; - tl = &ggtt->base.timeline.engine[engine->id]; - if (i915_gem_active_isset(&tl->last_request)) - return false; - } + for_each_engine(engine, i915, id) { + if (engine->last_retired_context != i915->kernel_context) + return false; + } - return true; + return true; } static int ggtt_flush(struct drm_i915_private *i915) @@ -82,7 +85,7 @@ mark_free(struct drm_mm_scan *scan, if (i915_vma_is_pinned(vma)) return false; - if (flags & PIN_NONFAULT && !list_empty(&vma->obj->userfault_link)) + if (flags & PIN_NONFAULT && i915_vma_has_userfault(vma)) return false; list_add(&vma->evict_link, unwind); @@ -157,7 +160,8 @@ i915_gem_evict_something(struct i915_address_space *vm, min_size, alignment, cache_level, start, end, mode); - /* Retire before we search the active list. Although we have + /* + * Retire before we search the active list. Although we have * reasonable accuracy in our retirement lists, we may have * a stray pin (preventing eviction) that can only be resolved by * retiring. @@ -182,7 +186,8 @@ search_again: BUG_ON(ret); } - /* Can we unpin some objects such as idle hw contents, + /* + * Can we unpin some objects such as idle hw contents, * or pending flips? But since only the GGTT has global entries * such as scanouts, rinbuffers and contexts, we can skip the * purge when inspecting per-process local address spaces. @@ -190,19 +195,36 @@ search_again: if (!i915_is_ggtt(vm) || flags & PIN_NONBLOCK) return -ENOSPC; - if (ggtt_is_idle(dev_priv)) { - /* If we still have pending pageflip completions, drop - * back to userspace to give our workqueues time to - * acquire our locks and unpin the old scanouts. - */ - return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC; - } + /* + * Not everything in the GGTT is tracked via VMA using + * i915_vma_move_to_active(), otherwise we could evict as required + * with minimal stalling. Instead we are forced to idle the GPU and + * explicitly retire outstanding requests which will then remove + * the pinning for active objects such as contexts and ring, + * enabling us to evict them on the next iteration. + * + * To ensure that all user contexts are evictable, we perform + * a switch to the perma-pinned kernel context. This all also gives + * us a termination condition, when the last retired context is + * the kernel's there is no more we can evict. + */ + if (!ggtt_is_idle(dev_priv)) { + if (I915_SELFTEST_ONLY(igt_evict_ctl.fail_if_busy)) + return -EBUSY; - ret = ggtt_flush(dev_priv); - if (ret) - return ret; + ret = ggtt_flush(dev_priv); + if (ret) + return ret; - goto search_again; + goto search_again; + } + + /* + * If we still have pending pageflip completions, drop + * back to userspace to give our workqueues time to + * acquire our locks and unpin the old scanouts. + */ + return intel_has_pending_fb_unpin(dev_priv) ? -EAGAIN : -ENOSPC; found: /* drm_mm doesn't allow any other other operations while @@ -315,6 +337,11 @@ int i915_gem_evict_for_node(struct i915_address_space *vm, break; } + if (flags & PIN_NONFAULT && i915_vma_has_userfault(vma)) { + ret = -ENOSPC; + break; + } + /* Overlap of objects in the same batch? */ if (i915_vma_is_pinned(vma)) { ret = -ENOSPC; diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index ca0eab343644..3d7190764f10 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -58,6 +58,7 @@ enum { #define __EXEC_HAS_RELOC BIT(31) #define __EXEC_VALIDATED BIT(30) +#define __EXEC_INTERNAL_FLAGS (~0u << 30) #define UPDATE PIN_OFFSET_FIXED #define BATCH_OFFSET_BIAS (256*1024) @@ -366,12 +367,12 @@ eb_pin_vma(struct i915_execbuffer *eb, return false; if (unlikely(exec_flags & EXEC_OBJECT_NEEDS_FENCE)) { - if (unlikely(i915_vma_get_fence(vma))) { + if (unlikely(i915_vma_pin_fence(vma))) { i915_vma_unpin(vma); return false; } - if (i915_vma_pin_fence(vma)) + if (vma->fence) exec_flags |= __EXEC_OBJECT_HAS_FENCE; } @@ -384,7 +385,7 @@ static inline void __eb_unreserve_vma(struct i915_vma *vma, unsigned int flags) GEM_BUG_ON(!(flags & __EXEC_OBJECT_HAS_PIN)); if (unlikely(flags & __EXEC_OBJECT_HAS_FENCE)) - i915_vma_unpin_fence(vma); + __i915_vma_unpin_fence(vma); __i915_vma_unpin(vma); } @@ -562,13 +563,13 @@ static int eb_reserve_vma(const struct i915_execbuffer *eb, } if (unlikely(exec_flags & EXEC_OBJECT_NEEDS_FENCE)) { - err = i915_vma_get_fence(vma); + err = i915_vma_pin_fence(vma); if (unlikely(err)) { i915_vma_unpin(vma); return err; } - if (i915_vma_pin_fence(vma)) + if (vma->fence) exec_flags |= __EXEC_OBJECT_HAS_FENCE; } @@ -679,7 +680,7 @@ static int eb_select_context(struct i915_execbuffer *eb) static int eb_lookup_vmas(struct i915_execbuffer *eb) { struct radix_tree_root *handles_vma = &eb->ctx->handles_vma; - struct drm_i915_gem_object *uninitialized_var(obj); + struct drm_i915_gem_object *obj; unsigned int i; int err; @@ -725,19 +726,17 @@ static int eb_lookup_vmas(struct i915_execbuffer *eb) goto err_obj; } + /* transfer ref to ctx */ vma->open_count++; list_add(&lut->obj_link, &obj->lut_list); list_add(&lut->ctx_link, &eb->ctx->handles_list); lut->ctx = eb->ctx; lut->handle = handle; - /* transfer ref to ctx */ - obj = NULL; - add_vma: err = eb_add_vma(eb, i, vma); if (unlikely(err)) - goto err_obj; + goto err_vma; GEM_BUG_ON(vma != eb->vma[i]); GEM_BUG_ON(vma->exec_flags != &eb->flags[i]); @@ -766,8 +765,7 @@ add_vma: return eb_reserve(eb); err_obj: - if (obj) - i915_gem_object_put(obj); + i915_gem_object_put(obj); err_vma: eb->vma[i] = NULL; return err; @@ -976,7 +974,9 @@ static void *reloc_iomap(struct drm_i915_gem_object *obj, return ERR_PTR(err); vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, - PIN_MAPPABLE | PIN_NONBLOCK); + PIN_MAPPABLE | + PIN_NONBLOCK | + PIN_NONFAULT); if (IS_ERR(vma)) { memset(&cache->node, 0, sizeof(cache->node)); err = drm_mm_insert_node_in_range @@ -1587,7 +1587,7 @@ static int eb_prefault_relocations(const struct i915_execbuffer *eb) const unsigned int count = eb->buffer_count; unsigned int i; - if (unlikely(i915.prefault_disable)) + if (unlikely(i915_modparams.prefault_disable)) return 0; for (i = 0; i < count; i++) { @@ -2188,6 +2188,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, int out_fence_fd = -1; int err; + BUILD_BUG_ON(__EXEC_INTERNAL_FLAGS & ~__I915_EXEC_ILLEGAL_FLAGS); BUILD_BUG_ON(__EXEC_OBJECT_INTERNAL_FLAGS & ~__EXEC_OBJECT_UNKNOWN_FLAGS); diff --git a/drivers/gpu/drm/i915/i915_gem_fence_reg.c b/drivers/gpu/drm/i915/i915_gem_fence_reg.c index 2783d63bd1ad..012250f25255 100644 --- a/drivers/gpu/drm/i915/i915_gem_fence_reg.c +++ b/drivers/gpu/drm/i915/i915_gem_fence_reg.c @@ -240,7 +240,8 @@ static int fence_update(struct drm_i915_fence_reg *fence, /* Ensure that all userspace CPU access is completed before * stealing the fence. */ - i915_gem_release_mmap(fence->vma->obj); + GEM_BUG_ON(fence->vma->fence != fence); + i915_vma_revoke_mmap(fence->vma); fence->vma->fence = NULL; fence->vma = NULL; @@ -280,8 +281,7 @@ static int fence_update(struct drm_i915_fence_reg *fence, * * 0 on success, negative error code on failure. */ -int -i915_vma_put_fence(struct i915_vma *vma) +int i915_vma_put_fence(struct i915_vma *vma) { struct drm_i915_fence_reg *fence = vma->fence; @@ -299,6 +299,8 @@ static struct drm_i915_fence_reg *fence_find(struct drm_i915_private *dev_priv) struct drm_i915_fence_reg *fence; list_for_each_entry(fence, &dev_priv->mm.fence_list, link) { + GEM_BUG_ON(fence->vma && fence->vma->fence != fence); + if (fence->pin_count) continue; @@ -313,7 +315,7 @@ static struct drm_i915_fence_reg *fence_find(struct drm_i915_private *dev_priv) } /** - * i915_vma_get_fence - set up fencing for a vma + * i915_vma_pin_fence - set up fencing for a vma * @vma: vma to map through a fence reg * * When mapping objects through the GTT, userspace wants to be able to write @@ -331,10 +333,11 @@ static struct drm_i915_fence_reg *fence_find(struct drm_i915_private *dev_priv) * 0 on success, negative error code on failure. */ int -i915_vma_get_fence(struct i915_vma *vma) +i915_vma_pin_fence(struct i915_vma *vma) { struct drm_i915_fence_reg *fence; struct i915_vma *set = i915_gem_object_is_tiled(vma->obj) ? vma : NULL; + int err; /* Note that we revoke fences on runtime suspend. Therefore the user * must keep the device awake whilst using the fence. @@ -344,6 +347,8 @@ i915_vma_get_fence(struct i915_vma *vma) /* Just update our place in the LRU if our fence is getting reused. */ if (vma->fence) { fence = vma->fence; + GEM_BUG_ON(fence->vma != vma); + fence->pin_count++; if (!fence->dirty) { list_move_tail(&fence->link, &fence->i915->mm.fence_list); @@ -353,10 +358,25 @@ i915_vma_get_fence(struct i915_vma *vma) fence = fence_find(vma->vm->i915); if (IS_ERR(fence)) return PTR_ERR(fence); + + GEM_BUG_ON(fence->pin_count); + fence->pin_count++; } else return 0; - return fence_update(fence, set); + err = fence_update(fence, set); + if (err) + goto out_unpin; + + GEM_BUG_ON(fence->vma != set); + GEM_BUG_ON(vma->fence != (set ? fence : NULL)); + + if (set) + return 0; + +out_unpin: + fence->pin_count--; + return err; } /** @@ -429,8 +449,10 @@ void i915_gem_revoke_fences(struct drm_i915_private *dev_priv) for (i = 0; i < dev_priv->num_fence_regs; i++) { struct drm_i915_fence_reg *fence = &dev_priv->fence_regs[i]; + GEM_BUG_ON(fence->vma && fence->vma->fence != fence); + if (fence->vma) - i915_gem_release_mmap(fence->vma->obj); + i915_vma_revoke_mmap(fence->vma); } } @@ -450,13 +472,15 @@ void i915_gem_restore_fences(struct drm_i915_private *dev_priv) struct drm_i915_fence_reg *reg = &dev_priv->fence_regs[i]; struct i915_vma *vma = reg->vma; + GEM_BUG_ON(vma && vma->fence != reg); + /* * Commit delayed tiling changes if we have an object still * attached to the fence, otherwise just clear the fence. */ if (vma && !i915_gem_object_is_tiled(vma->obj)) { GEM_BUG_ON(!reg->dirty); - GEM_BUG_ON(!list_empty(&vma->obj->userfault_link)); + GEM_BUG_ON(i915_vma_has_userfault(vma)); list_move(®->link, &dev_priv->mm.fence_list); vma->fence = NULL; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 40d446ba0b85..5eaa6893daaa 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -135,11 +135,12 @@ static inline void i915_ggtt_invalidate(struct drm_i915_private *i915) int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, int enable_ppgtt) { - bool has_aliasing_ppgtt; bool has_full_ppgtt; bool has_full_48bit_ppgtt; - has_aliasing_ppgtt = dev_priv->info.has_aliasing_ppgtt; + if (!dev_priv->info.has_aliasing_ppgtt) + return 0; + has_full_ppgtt = dev_priv->info.has_full_ppgtt; has_full_48bit_ppgtt = dev_priv->info.has_full_48bit_ppgtt; @@ -149,9 +150,6 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, has_full_48bit_ppgtt = intel_vgpu_has_full_48bit_ppgtt(dev_priv); } - if (!has_aliasing_ppgtt) - return 0; - /* * We don't allow disabling PPGTT for gen9+ as it's a requirement for * execlists, the sole mechanism available to submit work. @@ -180,7 +178,7 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, return 0; } - if (INTEL_GEN(dev_priv) >= 8 && i915.enable_execlists) { + if (INTEL_GEN(dev_priv) >= 8 && i915_modparams.enable_execlists) { if (has_full_48bit_ppgtt) return 3; @@ -188,7 +186,7 @@ int intel_sanitize_enable_ppgtt(struct drm_i915_private *dev_priv, return 2; } - return has_aliasing_ppgtt ? 1 : 0; + return 1; } static int ppgtt_bind_vma(struct i915_vma *vma, @@ -205,8 +203,6 @@ static int ppgtt_bind_vma(struct i915_vma *vma, return ret; } - vma->pages = vma->obj->mm.pages; - /* Currently applicable only to VLV */ pte_flags = 0; if (vma->obj->gt_ro) @@ -222,6 +218,30 @@ static void ppgtt_unbind_vma(struct i915_vma *vma) vma->vm->clear_range(vma->vm, vma->node.start, vma->size); } +static int ppgtt_set_pages(struct i915_vma *vma) +{ + GEM_BUG_ON(vma->pages); + + vma->pages = vma->obj->mm.pages; + + vma->page_sizes = vma->obj->mm.page_sizes; + + return 0; +} + +static void clear_pages(struct i915_vma *vma) +{ + GEM_BUG_ON(!vma->pages); + + if (vma->pages != vma->obj->mm.pages) { + sg_free_table(vma->pages); + kfree(vma->pages); + } + vma->pages = NULL; + + memset(&vma->page_sizes, 0, sizeof(vma->page_sizes)); +} + static gen8_pte_t gen8_pte_encode(dma_addr_t addr, enum i915_cache_level level) { @@ -230,13 +250,13 @@ static gen8_pte_t gen8_pte_encode(dma_addr_t addr, switch (level) { case I915_CACHE_NONE: - pte |= PPAT_UNCACHED_INDEX; + pte |= PPAT_UNCACHED; break; case I915_CACHE_WT: - pte |= PPAT_DISPLAY_ELLC_INDEX; + pte |= PPAT_DISPLAY_ELLC; break; default: - pte |= PPAT_CACHED_INDEX; + pte |= PPAT_CACHED; break; } @@ -249,9 +269,9 @@ static gen8_pde_t gen8_pde_encode(const dma_addr_t addr, gen8_pde_t pde = _PAGE_PRESENT | _PAGE_RW; pde |= addr; if (level != I915_CACHE_NONE) - pde |= PPAT_CACHED_PDE_INDEX; + pde |= PPAT_CACHED_PDE; else - pde |= PPAT_UNCACHED_INDEX; + pde |= PPAT_UNCACHED; return pde; } @@ -481,10 +501,8 @@ static void fill_page_dma(struct i915_address_space *vm, const u64 val) { u64 * const vaddr = kmap_atomic(p->page); - int i; - for (i = 0; i < 512; i++) - vaddr[i] = val; + memset64(vaddr, val, PAGE_SIZE / sizeof(val)); kunmap_atomic(vaddr); } @@ -499,22 +517,63 @@ static void fill_page_dma_32(struct i915_address_space *vm, static int setup_scratch_page(struct i915_address_space *vm, gfp_t gfp) { - struct page *page; + struct page *page = NULL; dma_addr_t addr; + int order; - page = alloc_page(gfp | __GFP_ZERO); - if (unlikely(!page)) - return -ENOMEM; + /* + * In order to utilize 64K pages for an object with a size < 2M, we will + * need to support a 64K scratch page, given that every 16th entry for a + * page-table operating in 64K mode must point to a properly aligned 64K + * region, including any PTEs which happen to point to scratch. + * + * This is only relevant for the 48b PPGTT where we support + * huge-gtt-pages, see also i915_vma_insert(). + * + * TODO: we should really consider write-protecting the scratch-page and + * sharing between ppgtt + */ + if (i915_vm_is_48bit(vm) && + HAS_PAGE_SIZES(vm->i915, I915_GTT_PAGE_SIZE_64K)) { + order = get_order(I915_GTT_PAGE_SIZE_64K); + page = alloc_pages(gfp | __GFP_ZERO | __GFP_NOWARN, order); + if (page) { + addr = dma_map_page(vm->dma, page, 0, + I915_GTT_PAGE_SIZE_64K, + PCI_DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(vm->dma, addr))) { + __free_pages(page, order); + page = NULL; + } - addr = dma_map_page(vm->dma, page, 0, PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - if (unlikely(dma_mapping_error(vm->dma, addr))) { - __free_page(page); - return -ENOMEM; + if (!IS_ALIGNED(addr, I915_GTT_PAGE_SIZE_64K)) { + dma_unmap_page(vm->dma, addr, + I915_GTT_PAGE_SIZE_64K, + PCI_DMA_BIDIRECTIONAL); + __free_pages(page, order); + page = NULL; + } + } + } + + if (!page) { + order = 0; + page = alloc_page(gfp | __GFP_ZERO); + if (unlikely(!page)) + return -ENOMEM; + + addr = dma_map_page(vm->dma, page, 0, PAGE_SIZE, + PCI_DMA_BIDIRECTIONAL); + if (unlikely(dma_mapping_error(vm->dma, addr))) { + __free_page(page); + return -ENOMEM; + } } vm->scratch_page.page = page; vm->scratch_page.daddr = addr; + vm->scratch_page.order = order; + return 0; } @@ -522,8 +581,9 @@ static void cleanup_scratch_page(struct i915_address_space *vm) { struct i915_page_dma *p = &vm->scratch_page; - dma_unmap_page(vm->dma, p->daddr, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - __free_page(p->page); + dma_unmap_page(vm->dma, p->daddr, BIT(p->order) << PAGE_SHIFT, + PCI_DMA_BIDIRECTIONAL); + __free_pages(p->page, p->order); } static struct i915_page_table *alloc_pt(struct i915_address_space *vm) @@ -991,6 +1051,105 @@ static void gen8_ppgtt_insert_3lvl(struct i915_address_space *vm, gen8_ppgtt_insert_pte_entries(ppgtt, &ppgtt->pdp, &iter, &idx, cache_level); + + vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; +} + +static void gen8_ppgtt_insert_huge_entries(struct i915_vma *vma, + struct i915_page_directory_pointer **pdps, + struct sgt_dma *iter, + enum i915_cache_level cache_level) +{ + const gen8_pte_t pte_encode = gen8_pte_encode(0, cache_level); + u64 start = vma->node.start; + dma_addr_t rem = iter->sg->length; + + do { + struct gen8_insert_pte idx = gen8_insert_pte(start); + struct i915_page_directory_pointer *pdp = pdps[idx.pml4e]; + struct i915_page_directory *pd = pdp->page_directory[idx.pdpe]; + unsigned int page_size; + bool maybe_64K = false; + gen8_pte_t encode = pte_encode; + gen8_pte_t *vaddr; + u16 index, max; + + if (vma->page_sizes.sg & I915_GTT_PAGE_SIZE_2M && + IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_2M) && + rem >= I915_GTT_PAGE_SIZE_2M && !idx.pte) { + index = idx.pde; + max = I915_PDES; + page_size = I915_GTT_PAGE_SIZE_2M; + + encode |= GEN8_PDE_PS_2M; + + vaddr = kmap_atomic_px(pd); + } else { + struct i915_page_table *pt = pd->page_table[idx.pde]; + + index = idx.pte; + max = GEN8_PTES; + page_size = I915_GTT_PAGE_SIZE; + + if (!index && + vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K && + IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) && + (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) || + rem >= (max - index) << PAGE_SHIFT)) + maybe_64K = true; + + vaddr = kmap_atomic_px(pt); + } + + do { + GEM_BUG_ON(iter->sg->length < page_size); + vaddr[index++] = encode | iter->dma; + + start += page_size; + iter->dma += page_size; + rem -= page_size; + if (iter->dma >= iter->max) { + iter->sg = __sg_next(iter->sg); + if (!iter->sg) + break; + + rem = iter->sg->length; + iter->dma = sg_dma_address(iter->sg); + iter->max = iter->dma + rem; + + if (maybe_64K && index < max && + !(IS_ALIGNED(iter->dma, I915_GTT_PAGE_SIZE_64K) && + (IS_ALIGNED(rem, I915_GTT_PAGE_SIZE_64K) || + rem >= (max - index) << PAGE_SHIFT))) + maybe_64K = false; + + if (unlikely(!IS_ALIGNED(iter->dma, page_size))) + break; + } + } while (rem >= page_size && index < max); + + kunmap_atomic(vaddr); + + /* + * Is it safe to mark the 2M block as 64K? -- Either we have + * filled whole page-table with 64K entries, or filled part of + * it and have reached the end of the sg table and we have + * enough padding. + */ + if (maybe_64K && + (index == max || + (i915_vm_has_scratch_64K(vma->vm) && + !iter->sg && IS_ALIGNED(vma->node.start + + vma->node.size, + I915_GTT_PAGE_SIZE_2M)))) { + vaddr = kmap_atomic_px(pd); + vaddr[idx.pde] |= GEN8_PDE_IPS_64K; + kunmap_atomic(vaddr); + page_size = I915_GTT_PAGE_SIZE_64K; + } + + vma->page_sizes.gtt |= page_size; + } while (iter->sg); } static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm, @@ -1005,11 +1164,18 @@ static void gen8_ppgtt_insert_4lvl(struct i915_address_space *vm, .max = iter.dma + iter.sg->length, }; struct i915_page_directory_pointer **pdps = ppgtt->pml4.pdps; - struct gen8_insert_pte idx = gen8_insert_pte(vma->node.start); - while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++], &iter, - &idx, cache_level)) - GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4); + if (vma->page_sizes.sg > I915_GTT_PAGE_SIZE) { + gen8_ppgtt_insert_huge_entries(vma, pdps, &iter, cache_level); + } else { + struct gen8_insert_pte idx = gen8_insert_pte(vma->node.start); + + while (gen8_ppgtt_insert_pte_entries(ppgtt, pdps[idx.pml4e++], + &iter, &idx, cache_level)) + GEM_BUG_ON(idx.pml4e >= GEN8_PML4ES_PER_PML4); + + vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; + } } static void gen8_free_page_tables(struct i915_address_space *vm, @@ -1168,19 +1334,22 @@ static int gen8_ppgtt_alloc_pd(struct i915_address_space *vm, unsigned int pde; gen8_for_each_pde(pt, pd, start, length, pde) { + int count = gen8_pte_count(start, length); + if (pt == vm->scratch_pt) { pt = alloc_pt(vm); if (IS_ERR(pt)) goto unwind; - gen8_initialize_pt(vm, pt); + if (count < GEN8_PTES || intel_vgpu_active(vm->i915)) + gen8_initialize_pt(vm, pt); gen8_ppgtt_set_pde(vm, pd, pt, pde); pd->used_pdes++; GEM_BUG_ON(pd->used_pdes > I915_PDES); } - pt->used_ptes += gen8_pte_count(start, length); + pt->used_ptes += count; } return 0; @@ -1451,6 +1620,8 @@ static int gen8_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.cleanup = gen8_ppgtt_cleanup; ppgtt->base.unbind_vma = ppgtt_unbind_vma; ppgtt->base.bind_vma = ppgtt_bind_vma; + ppgtt->base.set_pages = ppgtt_set_pages; + ppgtt->base.clear_pages = clear_pages; ppgtt->debug_dump = gen8_dump_ppgtt; return 0; @@ -1725,6 +1896,8 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, } } while (1); kunmap_atomic(vaddr); + + vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; } static int gen6_alloc_va_range(struct i915_address_space *vm, @@ -1893,6 +2066,8 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) ppgtt->base.insert_entries = gen6_ppgtt_insert_entries; ppgtt->base.unbind_vma = ppgtt_unbind_vma; ppgtt->base.bind_vma = ppgtt_bind_vma; + ppgtt->base.set_pages = ppgtt_set_pages; + ppgtt->base.clear_pages = clear_pages; ppgtt->base.cleanup = gen6_ppgtt_cleanup; ppgtt->debug_dump = gen6_dump_ppgtt; @@ -1960,6 +2135,23 @@ static void gtt_write_workarounds(struct drm_i915_private *dev_priv) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL); else if (IS_GEN9_LP(dev_priv)) I915_WRITE(GEN8_L3_LRA_1_GPGPU, GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT); + + /* + * To support 64K PTEs we need to first enable the use of the + * Intermediate-Page-Size(IPS) bit of the PDE field via some magical + * mmio, otherwise the page-walker will simply ignore the IPS bit. This + * shouldn't be needed after GEN10. + * + * 64K pages were first introduced from BDW+, although technically they + * only *work* from gen9+. For pre-BDW we instead have the option for + * 32K pages, but we don't currently have any support for it in our + * driver. + */ + if (HAS_PAGE_SIZES(dev_priv, I915_GTT_PAGE_SIZE_64K) && + INTEL_GEN(dev_priv) <= 10) + I915_WRITE(GEN8_GAMW_ECO_DEV_RW_IA, + I915_READ(GEN8_GAMW_ECO_DEV_RW_IA) | + GAMW_ECO_ENABLE_64K_IPS_FIELD); } int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv) @@ -1969,7 +2161,7 @@ int i915_ppgtt_init_hw(struct drm_i915_private *dev_priv) /* In the case of execlists, PPGTT is enabled by the context descriptor * and the PDPs are contained within the context itself. We don't * need to do anything here. */ - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) return 0; if (!USES_PPGTT(dev_priv)) @@ -2404,12 +2596,6 @@ static int ggtt_bind_vma(struct i915_vma *vma, struct drm_i915_gem_object *obj = vma->obj; u32 pte_flags; - if (unlikely(!vma->pages)) { - int ret = i915_get_ggtt_vma_pages(vma); - if (ret) - return ret; - } - /* Currently applicable only to VLV */ pte_flags = 0; if (obj->gt_ro) @@ -2419,6 +2605,8 @@ static int ggtt_bind_vma(struct i915_vma *vma, vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags); intel_runtime_pm_put(i915); + vma->page_sizes.gtt = I915_GTT_PAGE_SIZE; + /* * Without aliasing PPGTT there's no difference between * GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally @@ -2446,12 +2634,6 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, u32 pte_flags; int ret; - if (unlikely(!vma->pages)) { - ret = i915_get_ggtt_vma_pages(vma); - if (ret) - return ret; - } - /* Currently applicable only to VLV */ pte_flags = 0; if (vma->obj->gt_ro) @@ -2466,7 +2648,7 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, vma->node.start, vma->size); if (ret) - goto err_pages; + return ret; } appgtt->base.insert_entries(&appgtt->base, vma, cache_level, @@ -2480,17 +2662,6 @@ static int aliasing_gtt_bind_vma(struct i915_vma *vma, } return 0; - -err_pages: - if (!(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND))) { - if (vma->pages != vma->obj->mm.pages) { - GEM_BUG_ON(!vma->pages); - sg_free_table(vma->pages); - kfree(vma->pages); - } - vma->pages = NULL; - } - return ret; } static void aliasing_gtt_unbind_vma(struct i915_vma *vma) @@ -2528,6 +2699,21 @@ void i915_gem_gtt_finish_pages(struct drm_i915_gem_object *obj, dma_unmap_sg(kdev, pages->sgl, pages->nents, PCI_DMA_BIDIRECTIONAL); } +static int ggtt_set_pages(struct i915_vma *vma) +{ + int ret; + + GEM_BUG_ON(vma->pages); + + ret = i915_get_ggtt_vma_pages(vma); + if (ret) + return ret; + + vma->page_sizes = vma->obj->mm.page_sizes; + + return 0; +} + static void i915_gtt_color_adjust(const struct drm_mm_node *node, unsigned long color, u64 *start, @@ -2816,41 +3002,209 @@ static int ggtt_probe_common(struct i915_ggtt *ggtt, u64 size) return 0; } -static void cnl_setup_private_ppat(struct drm_i915_private *dev_priv) +static struct intel_ppat_entry * +__alloc_ppat_entry(struct intel_ppat *ppat, unsigned int index, u8 value) +{ + struct intel_ppat_entry *entry = &ppat->entries[index]; + + GEM_BUG_ON(index >= ppat->max_entries); + GEM_BUG_ON(test_bit(index, ppat->used)); + + entry->ppat = ppat; + entry->value = value; + kref_init(&entry->ref); + set_bit(index, ppat->used); + set_bit(index, ppat->dirty); + + return entry; +} + +static void __free_ppat_entry(struct intel_ppat_entry *entry) +{ + struct intel_ppat *ppat = entry->ppat; + unsigned int index = entry - ppat->entries; + + GEM_BUG_ON(index >= ppat->max_entries); + GEM_BUG_ON(!test_bit(index, ppat->used)); + + entry->value = ppat->clear_value; + clear_bit(index, ppat->used); + set_bit(index, ppat->dirty); +} + +/** + * intel_ppat_get - get a usable PPAT entry + * @i915: i915 device instance + * @value: the PPAT value required by the caller + * + * The function tries to search if there is an existing PPAT entry which + * matches with the required value. If perfectly matched, the existing PPAT + * entry will be used. If only partially matched, it will try to check if + * there is any available PPAT index. If yes, it will allocate a new PPAT + * index for the required entry and update the HW. If not, the partially + * matched entry will be used. + */ +const struct intel_ppat_entry * +intel_ppat_get(struct drm_i915_private *i915, u8 value) +{ + struct intel_ppat *ppat = &i915->ppat; + struct intel_ppat_entry *entry; + unsigned int scanned, best_score; + int i; + + GEM_BUG_ON(!ppat->max_entries); + + scanned = best_score = 0; + for_each_set_bit(i, ppat->used, ppat->max_entries) { + unsigned int score; + + score = ppat->match(ppat->entries[i].value, value); + if (score > best_score) { + entry = &ppat->entries[i]; + if (score == INTEL_PPAT_PERFECT_MATCH) { + kref_get(&entry->ref); + return entry; + } + best_score = score; + } + scanned++; + } + + if (scanned == ppat->max_entries) { + if (!best_score) + return ERR_PTR(-ENOSPC); + + kref_get(&entry->ref); + return entry; + } + + i = find_first_zero_bit(ppat->used, ppat->max_entries); + entry = __alloc_ppat_entry(ppat, i, value); + ppat->update_hw(i915); + return entry; +} + +static void release_ppat(struct kref *kref) +{ + struct intel_ppat_entry *entry = + container_of(kref, struct intel_ppat_entry, ref); + struct drm_i915_private *i915 = entry->ppat->i915; + + __free_ppat_entry(entry); + entry->ppat->update_hw(i915); +} + +/** + * intel_ppat_put - put back the PPAT entry got from intel_ppat_get() + * @entry: an intel PPAT entry + * + * Put back the PPAT entry got from intel_ppat_get(). If the PPAT index of the + * entry is dynamically allocated, its reference count will be decreased. Once + * the reference count becomes into zero, the PPAT index becomes free again. + */ +void intel_ppat_put(const struct intel_ppat_entry *entry) +{ + struct intel_ppat *ppat = entry->ppat; + unsigned int index = entry - ppat->entries; + + GEM_BUG_ON(!ppat->max_entries); + + kref_put(&ppat->entries[index].ref, release_ppat); +} + +static void cnl_private_pat_update_hw(struct drm_i915_private *dev_priv) { + struct intel_ppat *ppat = &dev_priv->ppat; + int i; + + for_each_set_bit(i, ppat->dirty, ppat->max_entries) { + I915_WRITE(GEN10_PAT_INDEX(i), ppat->entries[i].value); + clear_bit(i, ppat->dirty); + } +} + +static void bdw_private_pat_update_hw(struct drm_i915_private *dev_priv) +{ + struct intel_ppat *ppat = &dev_priv->ppat; + u64 pat = 0; + int i; + + for (i = 0; i < ppat->max_entries; i++) + pat |= GEN8_PPAT(i, ppat->entries[i].value); + + bitmap_clear(ppat->dirty, 0, ppat->max_entries); + + I915_WRITE(GEN8_PRIVATE_PAT_LO, lower_32_bits(pat)); + I915_WRITE(GEN8_PRIVATE_PAT_HI, upper_32_bits(pat)); +} + +static unsigned int bdw_private_pat_match(u8 src, u8 dst) +{ + unsigned int score = 0; + enum { + AGE_MATCH = BIT(0), + TC_MATCH = BIT(1), + CA_MATCH = BIT(2), + }; + + /* Cache attribute has to be matched. */ + if (GEN8_PPAT_GET_CA(src) != GEN8_PPAT_GET_CA(dst)) + return 0; + + score |= CA_MATCH; + + if (GEN8_PPAT_GET_TC(src) == GEN8_PPAT_GET_TC(dst)) + score |= TC_MATCH; + + if (GEN8_PPAT_GET_AGE(src) == GEN8_PPAT_GET_AGE(dst)) + score |= AGE_MATCH; + + if (score == (AGE_MATCH | TC_MATCH | CA_MATCH)) + return INTEL_PPAT_PERFECT_MATCH; + + return score; +} + +static unsigned int chv_private_pat_match(u8 src, u8 dst) +{ + return (CHV_PPAT_GET_SNOOP(src) == CHV_PPAT_GET_SNOOP(dst)) ? + INTEL_PPAT_PERFECT_MATCH : 0; +} + +static void cnl_setup_private_ppat(struct intel_ppat *ppat) +{ + ppat->max_entries = 8; + ppat->update_hw = cnl_private_pat_update_hw; + ppat->match = bdw_private_pat_match; + ppat->clear_value = GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3); + /* XXX: spec is unclear if this is still needed for CNL+ */ - if (!USES_PPGTT(dev_priv)) { - I915_WRITE(GEN10_PAT_INDEX(0), GEN8_PPAT_UC); + if (!USES_PPGTT(ppat->i915)) { + __alloc_ppat_entry(ppat, 0, GEN8_PPAT_UC); return; } - I915_WRITE(GEN10_PAT_INDEX(0), GEN8_PPAT_WB | GEN8_PPAT_LLC); - I915_WRITE(GEN10_PAT_INDEX(1), GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); - I915_WRITE(GEN10_PAT_INDEX(2), GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); - I915_WRITE(GEN10_PAT_INDEX(3), GEN8_PPAT_UC); - I915_WRITE(GEN10_PAT_INDEX(4), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)); - I915_WRITE(GEN10_PAT_INDEX(5), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)); - I915_WRITE(GEN10_PAT_INDEX(6), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)); - I915_WRITE(GEN10_PAT_INDEX(7), GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); + __alloc_ppat_entry(ppat, 0, GEN8_PPAT_WB | GEN8_PPAT_LLC); + __alloc_ppat_entry(ppat, 1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); + __alloc_ppat_entry(ppat, 2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); + __alloc_ppat_entry(ppat, 3, GEN8_PPAT_UC); + __alloc_ppat_entry(ppat, 4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)); + __alloc_ppat_entry(ppat, 5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)); + __alloc_ppat_entry(ppat, 6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)); + __alloc_ppat_entry(ppat, 7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); } /* The GGTT and PPGTT need a private PPAT setup in order to handle cacheability * bits. When using advanced contexts each context stores its own PAT, but * writing this data shouldn't be harmful even in those cases. */ -static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv) +static void bdw_setup_private_ppat(struct intel_ppat *ppat) { - u64 pat; + ppat->max_entries = 8; + ppat->update_hw = bdw_private_pat_update_hw; + ppat->match = bdw_private_pat_match; + ppat->clear_value = GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3); - pat = GEN8_PPAT(0, GEN8_PPAT_WB | GEN8_PPAT_LLC) | /* for normal objects, no eLLC */ - GEN8_PPAT(1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC) | /* for something pointing to ptes? */ - GEN8_PPAT(2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC) | /* for scanout with eLLC */ - GEN8_PPAT(3, GEN8_PPAT_UC) | /* Uncached objects, mostly for scanout */ - GEN8_PPAT(4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)) | - GEN8_PPAT(5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)) | - GEN8_PPAT(6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)) | - GEN8_PPAT(7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); - - if (!USES_PPGTT(dev_priv)) + if (!USES_PPGTT(ppat->i915)) { /* Spec: "For GGTT, there is NO pat_sel[2:0] from the entry, * so RTL will always use the value corresponding to * pat_sel = 000". @@ -2864,17 +3218,26 @@ static void bdw_setup_private_ppat(struct drm_i915_private *dev_priv) * So we can still hold onto all our assumptions wrt cpu * clflushing on LLC machines. */ - pat = GEN8_PPAT(0, GEN8_PPAT_UC); + __alloc_ppat_entry(ppat, 0, GEN8_PPAT_UC); + return; + } - /* XXX: spec defines this as 2 distinct registers. It's unclear if a 64b - * write would work. */ - I915_WRITE(GEN8_PRIVATE_PAT_LO, pat); - I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32); + __alloc_ppat_entry(ppat, 0, GEN8_PPAT_WB | GEN8_PPAT_LLC); /* for normal objects, no eLLC */ + __alloc_ppat_entry(ppat, 1, GEN8_PPAT_WC | GEN8_PPAT_LLCELLC); /* for something pointing to ptes? */ + __alloc_ppat_entry(ppat, 2, GEN8_PPAT_WT | GEN8_PPAT_LLCELLC); /* for scanout with eLLC */ + __alloc_ppat_entry(ppat, 3, GEN8_PPAT_UC); /* Uncached objects, mostly for scanout */ + __alloc_ppat_entry(ppat, 4, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(0)); + __alloc_ppat_entry(ppat, 5, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(1)); + __alloc_ppat_entry(ppat, 6, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(2)); + __alloc_ppat_entry(ppat, 7, GEN8_PPAT_WB | GEN8_PPAT_LLCELLC | GEN8_PPAT_AGE(3)); } -static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) +static void chv_setup_private_ppat(struct intel_ppat *ppat) { - u64 pat; + ppat->max_entries = 8; + ppat->update_hw = bdw_private_pat_update_hw; + ppat->match = chv_private_pat_match; + ppat->clear_value = CHV_PPAT_SNOOP; /* * Map WB on BDW to snooped on CHV. @@ -2894,17 +3257,15 @@ static void chv_setup_private_ppat(struct drm_i915_private *dev_priv) * Which means we must set the snoop bit in PAT entry 0 * in order to keep the global status page working. */ - pat = GEN8_PPAT(0, CHV_PPAT_SNOOP) | - GEN8_PPAT(1, 0) | - GEN8_PPAT(2, 0) | - GEN8_PPAT(3, 0) | - GEN8_PPAT(4, CHV_PPAT_SNOOP) | - GEN8_PPAT(5, CHV_PPAT_SNOOP) | - GEN8_PPAT(6, CHV_PPAT_SNOOP) | - GEN8_PPAT(7, CHV_PPAT_SNOOP); - I915_WRITE(GEN8_PRIVATE_PAT_LO, pat); - I915_WRITE(GEN8_PRIVATE_PAT_HI, pat >> 32); + __alloc_ppat_entry(ppat, 0, CHV_PPAT_SNOOP); + __alloc_ppat_entry(ppat, 1, 0); + __alloc_ppat_entry(ppat, 2, 0); + __alloc_ppat_entry(ppat, 3, 0); + __alloc_ppat_entry(ppat, 4, CHV_PPAT_SNOOP); + __alloc_ppat_entry(ppat, 5, CHV_PPAT_SNOOP); + __alloc_ppat_entry(ppat, 6, CHV_PPAT_SNOOP); + __alloc_ppat_entry(ppat, 7, CHV_PPAT_SNOOP); } static void gen6_gmch_remove(struct i915_address_space *vm) @@ -2915,6 +3276,31 @@ static void gen6_gmch_remove(struct i915_address_space *vm) cleanup_scratch_page(vm); } +static void setup_private_pat(struct drm_i915_private *dev_priv) +{ + struct intel_ppat *ppat = &dev_priv->ppat; + int i; + + ppat->i915 = dev_priv; + + if (INTEL_GEN(dev_priv) >= 10) + cnl_setup_private_ppat(ppat); + else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) + chv_setup_private_ppat(ppat); + else + bdw_setup_private_ppat(ppat); + + GEM_BUG_ON(ppat->max_entries > INTEL_MAX_PPAT_ENTRIES); + + for_each_clear_bit(i, ppat->used, ppat->max_entries) { + ppat->entries[i].value = ppat->clear_value; + ppat->entries[i].ppat = ppat; + set_bit(i, ppat->dirty); + } + + ppat->update_hw(dev_priv); +} + static int gen8_gmch_probe(struct i915_ggtt *ggtt) { struct drm_i915_private *dev_priv = ggtt->base.i915; @@ -2947,17 +3333,11 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) } ggtt->base.total = (size / sizeof(gen8_pte_t)) << PAGE_SHIFT; - - if (INTEL_GEN(dev_priv) >= 10) - cnl_setup_private_ppat(dev_priv); - else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) - chv_setup_private_ppat(dev_priv); - else - bdw_setup_private_ppat(dev_priv); - ggtt->base.cleanup = gen6_gmch_remove; ggtt->base.bind_vma = ggtt_bind_vma; ggtt->base.unbind_vma = ggtt_unbind_vma; + ggtt->base.set_pages = ggtt_set_pages; + ggtt->base.clear_pages = clear_pages; ggtt->base.insert_page = gen8_ggtt_insert_page; ggtt->base.clear_range = nop_clear_range; if (!USES_FULL_PPGTT(dev_priv) || intel_scanout_needs_vtd_wa(dev_priv)) @@ -2975,6 +3355,8 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt) ggtt->invalidate = gen6_ggtt_invalidate; + setup_private_pat(dev_priv); + return ggtt_probe_common(ggtt, size); } @@ -3014,6 +3396,8 @@ static int gen6_gmch_probe(struct i915_ggtt *ggtt) ggtt->base.insert_entries = gen6_ggtt_insert_entries; ggtt->base.bind_vma = ggtt_bind_vma; ggtt->base.unbind_vma = ggtt_unbind_vma; + ggtt->base.set_pages = ggtt_set_pages; + ggtt->base.clear_pages = clear_pages; ggtt->base.cleanup = gen6_gmch_remove; ggtt->invalidate = gen6_ggtt_invalidate; @@ -3059,6 +3443,8 @@ static int i915_gmch_probe(struct i915_ggtt *ggtt) ggtt->base.clear_range = i915_ggtt_clear_range; ggtt->base.bind_vma = ggtt_bind_vma; ggtt->base.unbind_vma = ggtt_unbind_vma; + ggtt->base.set_pages = ggtt_set_pages; + ggtt->base.clear_pages = clear_pages; ggtt->base.cleanup = i915_gmch_remove; ggtt->invalidate = gmch_ggtt_invalidate; @@ -3095,7 +3481,7 @@ int i915_ggtt_probe_hw(struct drm_i915_private *dev_priv) * currently don't have any bits spare to pass in this upper * restriction! */ - if (HAS_GUC(dev_priv) && i915.enable_guc_loading) { + if (HAS_GUC(dev_priv) && i915_modparams.enable_guc_loading) { ggtt->base.total = min_t(u64, ggtt->base.total, GUC_GGTT_TOP); ggtt->mappable_end = min(ggtt->mappable_end, ggtt->base.total); } @@ -3208,8 +3594,7 @@ void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv) ggtt->base.closed = true; /* skip rewriting PTE on VMA unbind */ /* clflush objects bound into the GGTT and rebind them. */ - list_for_each_entry_safe(obj, on, - &dev_priv->mm.bound_list, global_link) { + list_for_each_entry_safe(obj, on, &dev_priv->mm.bound_list, mm.link) { bool ggtt_bound = false; struct i915_vma *vma; @@ -3232,13 +3617,10 @@ void i915_gem_restore_gtt_mappings(struct drm_i915_private *dev_priv) ggtt->base.closed = false; if (INTEL_GEN(dev_priv) >= 8) { - if (INTEL_GEN(dev_priv) >= 10) - cnl_setup_private_ppat(dev_priv); - else if (IS_CHERRYVIEW(dev_priv) || IS_GEN9_LP(dev_priv)) - chv_setup_private_ppat(dev_priv); - else - bdw_setup_private_ppat(dev_priv); + struct intel_ppat *ppat = &dev_priv->ppat; + bitmap_set(ppat->dirty, 0, ppat->max_entries); + dev_priv->ppat.update_hw(dev_priv); return; } diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index b4e3aa7c0ce1..93211a96fdad 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -42,7 +42,13 @@ #include "i915_gem_request.h" #include "i915_selftest.h" -#define I915_GTT_PAGE_SIZE 4096UL +#define I915_GTT_PAGE_SIZE_4K BIT(12) +#define I915_GTT_PAGE_SIZE_64K BIT(16) +#define I915_GTT_PAGE_SIZE_2M BIT(21) + +#define I915_GTT_PAGE_SIZE I915_GTT_PAGE_SIZE_4K +#define I915_GTT_MAX_PAGE_SIZE I915_GTT_PAGE_SIZE_2M + #define I915_GTT_MIN_ALIGNMENT I915_GTT_PAGE_SIZE #define I915_FENCE_REG_NONE -1 @@ -126,13 +132,13 @@ typedef u64 gen8_ppgtt_pml4e_t; * tables */ #define GEN8_PDPE_MASK 0x1ff -#define PPAT_UNCACHED_INDEX (_PAGE_PWT | _PAGE_PCD) -#define PPAT_CACHED_PDE_INDEX 0 /* WB LLC */ -#define PPAT_CACHED_INDEX _PAGE_PAT /* WB LLCeLLC */ -#define PPAT_DISPLAY_ELLC_INDEX _PAGE_PCD /* WT eLLC */ +#define PPAT_UNCACHED (_PAGE_PWT | _PAGE_PCD) +#define PPAT_CACHED_PDE 0 /* WB LLC */ +#define PPAT_CACHED _PAGE_PAT /* WB LLCeLLC */ +#define PPAT_DISPLAY_ELLC _PAGE_PCD /* WT eLLC */ #define CHV_PPAT_SNOOP (1<<6) -#define GEN8_PPAT_AGE(x) (x<<4) +#define GEN8_PPAT_AGE(x) ((x)<<4) #define GEN8_PPAT_LLCeLLC (3<<2) #define GEN8_PPAT_LLCELLC (2<<2) #define GEN8_PPAT_LLC (1<<2) @@ -143,6 +149,14 @@ typedef u64 gen8_ppgtt_pml4e_t; #define GEN8_PPAT_ELLC_OVERRIDE (0<<2) #define GEN8_PPAT(i, x) ((u64)(x) << ((i) * 8)) +#define GEN8_PPAT_GET_CA(x) ((x) & 3) +#define GEN8_PPAT_GET_TC(x) ((x) & (3 << 2)) +#define GEN8_PPAT_GET_AGE(x) ((x) & (3 << 4)) +#define CHV_PPAT_GET_SNOOP(x) ((x) & (1 << 6)) + +#define GEN8_PDE_IPS_64K BIT(11) +#define GEN8_PDE_PS_2M BIT(7) + struct sg_table; struct intel_rotation_info { @@ -202,6 +216,7 @@ struct i915_vma; struct i915_page_dma { struct page *page; + int order; union { dma_addr_t daddr; @@ -324,6 +339,8 @@ struct i915_address_space { int (*bind_vma)(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags); + int (*set_pages)(struct i915_vma *vma); + void (*clear_pages)(struct i915_vma *vma); I915_SELFTEST_DECLARE(struct fault_attr fault_attr); }; @@ -336,6 +353,12 @@ i915_vm_is_48bit(const struct i915_address_space *vm) return (vm->total - 1) >> 32; } +static inline bool +i915_vm_has_scratch_64K(struct i915_address_space *vm) +{ + return vm->scratch_page.order == get_order(I915_GTT_PAGE_SIZE_64K); +} + /* The Graphics Translation Table is the way in which GEN hardware translates a * Graphics Virtual Address into a Physical Address. In addition to the normal * collateral associated with any va->pa translations GEN hardware also has a @@ -536,6 +559,37 @@ i915_vm_to_ggtt(struct i915_address_space *vm) return container_of(vm, struct i915_ggtt, base); } +#define INTEL_MAX_PPAT_ENTRIES 8 +#define INTEL_PPAT_PERFECT_MATCH (~0U) + +struct intel_ppat; + +struct intel_ppat_entry { + struct intel_ppat *ppat; + struct kref ref; + u8 value; +}; + +struct intel_ppat { + struct intel_ppat_entry entries[INTEL_MAX_PPAT_ENTRIES]; + DECLARE_BITMAP(used, INTEL_MAX_PPAT_ENTRIES); + DECLARE_BITMAP(dirty, INTEL_MAX_PPAT_ENTRIES); + unsigned int max_entries; + u8 clear_value; + /* + * Return a score to show how two PPAT values match, + * a INTEL_PPAT_PERFECT_MATCH indicates a perfect match + */ + unsigned int (*match)(u8 src, u8 dst); + void (*update_hw)(struct drm_i915_private *i915); + + struct drm_i915_private *i915; +}; + +const struct intel_ppat_entry * +intel_ppat_get(struct drm_i915_private *i915, u8 value); +void intel_ppat_put(const struct intel_ppat_entry *entry); + int i915_gem_init_aliasing_ppgtt(struct drm_i915_private *i915); void i915_gem_fini_aliasing_ppgtt(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/i915_gem_internal.c b/drivers/gpu/drm/i915/i915_gem_internal.c index c1f64ddaf8aa..ee83ec838ee7 100644 --- a/drivers/gpu/drm/i915/i915_gem_internal.c +++ b/drivers/gpu/drm/i915/i915_gem_internal.c @@ -44,12 +44,12 @@ static void internal_free_pages(struct sg_table *st) kfree(st); } -static struct sg_table * -i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) +static int i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) { struct drm_i915_private *i915 = to_i915(obj->base.dev); struct sg_table *st; struct scatterlist *sg; + unsigned int sg_page_sizes; unsigned int npages; int max_order; gfp_t gfp; @@ -78,16 +78,17 @@ i915_gem_object_get_pages_internal(struct drm_i915_gem_object *obj) create_st: st = kmalloc(sizeof(*st), GFP_KERNEL); if (!st) - return ERR_PTR(-ENOMEM); + return -ENOMEM; npages = obj->base.size / PAGE_SIZE; if (sg_alloc_table(st, npages, GFP_KERNEL)) { kfree(st); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } sg = st->sgl; st->nents = 0; + sg_page_sizes = 0; do { int order = min(fls(npages) - 1, max_order); @@ -105,6 +106,7 @@ create_st: } while (1); sg_set_page(sg, page, PAGE_SIZE << order, 0); + sg_page_sizes |= PAGE_SIZE << order; st->nents++; npages -= 1 << order; @@ -132,13 +134,17 @@ create_st: * object are only valid whilst active and pinned. */ obj->mm.madv = I915_MADV_DONTNEED; - return st; + + __i915_gem_object_set_pages(obj, st, sg_page_sizes); + + return 0; err: sg_set_page(sg, NULL, 0, 0); sg_mark_end(sg); internal_free_pages(st); - return ERR_PTR(-ENOMEM); + + return -ENOMEM; } static void i915_gem_object_put_pages_internal(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem_object.h b/drivers/gpu/drm/i915/i915_gem_object.h index c30d8f808185..63ce38c1cce9 100644 --- a/drivers/gpu/drm/i915/i915_gem_object.h +++ b/drivers/gpu/drm/i915/i915_gem_object.h @@ -69,7 +69,7 @@ struct drm_i915_gem_object_ops { * being released or under memory pressure (where we attempt to * reap pages for the shrinker). */ - struct sg_table *(*get_pages)(struct drm_i915_gem_object *); + int (*get_pages)(struct drm_i915_gem_object *); void (*put_pages)(struct drm_i915_gem_object *, struct sg_table *); int (*pwrite)(struct drm_i915_gem_object *, @@ -114,7 +114,6 @@ struct drm_i915_gem_object { /** Stolen memory for this object, instead of being backed by shmem. */ struct drm_mm_node *stolen; - struct list_head global_link; union { struct rcu_head rcu; struct llist_node freed; @@ -123,6 +122,7 @@ struct drm_i915_gem_object { /** * Whether the object is currently in the GGTT mmap. */ + unsigned int userfault_count; struct list_head userfault_link; struct list_head batch_pool_link; @@ -160,7 +160,8 @@ struct drm_i915_gem_object { /** Count of VMA actually bound by this object */ unsigned int bind_count; unsigned int active_count; - unsigned int pin_display; + /** Count of how many global VMA are currently pinned for use by HW */ + unsigned int pin_global; struct { struct mutex lock; /* protects the pages and their use */ @@ -169,6 +170,35 @@ struct drm_i915_gem_object { struct sg_table *pages; void *mapping; + /* TODO: whack some of this into the error state */ + struct i915_page_sizes { + /** + * The sg mask of the pages sg_table. i.e the mask of + * of the lengths for each sg entry. + */ + unsigned int phys; + + /** + * The gtt page sizes we are allowed to use given the + * sg mask and the supported page sizes. This will + * express the smallest unit we can use for the whole + * object, as well as the larger sizes we may be able + * to use opportunistically. + */ + unsigned int sg; + + /** + * The actual gtt page size usage. Since we can have + * multiple vma associated with this object we need to + * prevent any trampling of state, hence a copy of this + * struct also lives in each vma, therefore the gtt + * value here should only be read/write through the vma. + */ + unsigned int gtt; + } page_sizes; + + I915_SELFTEST_DECLARE(unsigned int page_mask); + struct i915_gem_object_page_iter { struct scatterlist *sg_pos; unsigned int sg_idx; /* in pages, but 32bit eek! */ @@ -178,6 +208,12 @@ struct drm_i915_gem_object { } get_page; /** + * Element within i915->mm.unbound_list or i915->mm.bound_list, + * locked by i915->mm.obj_lock. + */ + struct list_head link; + + /** * Advice: are the backing pages purgeable? */ unsigned int madv:2; diff --git a/drivers/gpu/drm/i915/i915_gem_render_state.c b/drivers/gpu/drm/i915/i915_gem_render_state.c index 4dd4c2159a92..3703dc91eeda 100644 --- a/drivers/gpu/drm/i915/i915_gem_render_state.c +++ b/drivers/gpu/drm/i915/i915_gem_render_state.c @@ -229,7 +229,7 @@ int i915_gem_render_state_emit(struct drm_i915_gem_request *req) return 0; /* Recreate the page after shrinking */ - if (!so->vma->obj->mm.pages) + if (!i915_gem_object_has_pages(so->vma->obj)) so->batch_offset = -1; ret = i915_vma_pin(so->vma, 0, 0, PIN_GLOBAL | PIN_HIGH); diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index 813a3b546d6e..d140fcf5c6a3 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -186,7 +186,7 @@ i915_priotree_init(struct i915_priotree *pt) INIT_LIST_HEAD(&pt->signalers_list); INIT_LIST_HEAD(&pt->waiters_list); INIT_LIST_HEAD(&pt->link); - pt->priority = INT_MIN; + pt->priority = I915_PRIORITY_INVALID; } static int reset_all_global_seqno(struct drm_i915_private *i915, u32 seqno) @@ -416,7 +416,7 @@ static void i915_gem_request_retire(struct drm_i915_gem_request *request) spin_lock_irq(&request->lock); if (request->waitboost) - atomic_dec(&request->i915->rps.num_waiters); + atomic_dec(&request->i915->gt_pm.rps.num_waiters); dma_fence_signal_locked(&request->fence); spin_unlock_irq(&request->lock); @@ -556,7 +556,16 @@ submit_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) switch (state) { case FENCE_COMPLETE: trace_i915_gem_request_submit(request); + /* + * We need to serialize use of the submit_request() callback with its + * hotplugging performed during an emergency i915_gem_set_wedged(). + * We use the RCU mechanism to mark the critical section in order to + * force i915_gem_set_wedged() to wait until the submit_request() is + * completed before proceeding. + */ + rcu_read_lock(); request->engine->submit_request(request); + rcu_read_unlock(); break; case FENCE_FREE: @@ -587,6 +596,13 @@ i915_gem_request_alloc(struct intel_engine_cs *engine, lockdep_assert_held(&dev_priv->drm.struct_mutex); + /* + * Preempt contexts are reserved for exclusive use to inject a + * preemption context switch. They are never to be used for any trivial + * request! + */ + GEM_BUG_ON(ctx == dev_priv->preempt_context); + /* ABI: Before userspace accesses the GPU (e.g. execbuffer), report * EIO if the GPU is already wedged. */ @@ -1021,12 +1037,28 @@ static bool busywait_stop(unsigned long timeout, unsigned int cpu) return this_cpu != cpu; } -bool __i915_spin_request(const struct drm_i915_gem_request *req, - u32 seqno, int state, unsigned long timeout_us) +static bool __i915_spin_request(const struct drm_i915_gem_request *req, + u32 seqno, int state, unsigned long timeout_us) { struct intel_engine_cs *engine = req->engine; unsigned int irq, cpu; + GEM_BUG_ON(!seqno); + + /* + * Only wait for the request if we know it is likely to complete. + * + * We don't track the timestamps around requests, nor the average + * request length, so we do not have a good indicator that this + * request will complete within the timeout. What we do know is the + * order in which requests are executed by the engine and so we can + * tell if the request has started. If the request hasn't started yet, + * it is a fair assumption that it will not complete within our + * relatively short timeout. + */ + if (!i915_seqno_passed(intel_engine_get_seqno(engine), seqno - 1)) + return false; + /* When waiting for high frequency requests, e.g. during synchronous * rendering split between the CPU and GPU, the finite amount of time * required to set up the irq and wait upon it limits the response @@ -1040,12 +1072,8 @@ bool __i915_spin_request(const struct drm_i915_gem_request *req, irq = atomic_read(&engine->irq_count); timeout_us += local_clock_us(&cpu); do { - if (seqno != i915_gem_request_global_seqno(req)) - break; - - if (i915_seqno_passed(intel_engine_get_seqno(req->engine), - seqno)) - return true; + if (i915_seqno_passed(intel_engine_get_seqno(engine), seqno)) + return seqno == i915_gem_request_global_seqno(req); /* Seqno are meant to be ordered *before* the interrupt. If * we see an interrupt without a corresponding seqno advance, @@ -1156,7 +1184,7 @@ restart: GEM_BUG_ON(!i915_sw_fence_signaled(&req->submit)); /* Optimistic short spin before touching IRQs */ - if (i915_spin_request(req, state, 5)) + if (__i915_spin_request(req, wait.seqno, state, 5)) goto complete; set_current_state(state); @@ -1213,7 +1241,7 @@ wakeup: continue; /* Only spin if we know the GPU is processing this request */ - if (i915_spin_request(req, state, 2)) + if (__i915_spin_request(req, wait.seqno, state, 2)) break; if (!intel_wait_check_request(&wait, req)) { diff --git a/drivers/gpu/drm/i915/i915_gem_request.h b/drivers/gpu/drm/i915/i915_gem_request.h index 49a4c8994ff0..26249f39de67 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.h +++ b/drivers/gpu/drm/i915/i915_gem_request.h @@ -30,6 +30,8 @@ #include "i915_gem.h" #include "i915_sw_fence.h" +#include <uapi/drm/i915_drm.h> + struct drm_file; struct drm_i915_gem_object; struct drm_i915_gem_request; @@ -69,9 +71,14 @@ struct i915_priotree { struct list_head waiters_list; /* those after us, they depend upon us */ struct list_head link; int priority; -#define I915_PRIORITY_MAX 1024 -#define I915_PRIORITY_NORMAL 0 -#define I915_PRIORITY_MIN (-I915_PRIORITY_MAX) +}; + +enum { + I915_PRIORITY_MIN = I915_CONTEXT_MIN_USER_PRIORITY - 1, + I915_PRIORITY_NORMAL = I915_CONTEXT_DEFAULT_PRIORITY, + I915_PRIORITY_MAX = I915_CONTEXT_MAX_USER_PRIORITY + 1, + + I915_PRIORITY_INVALID = INT_MIN }; struct i915_gem_capture_list { @@ -313,26 +320,6 @@ static inline bool i915_seqno_passed(u32 seq1, u32 seq2) } static inline bool -__i915_gem_request_started(const struct drm_i915_gem_request *req, u32 seqno) -{ - GEM_BUG_ON(!seqno); - return i915_seqno_passed(intel_engine_get_seqno(req->engine), - seqno - 1); -} - -static inline bool -i915_gem_request_started(const struct drm_i915_gem_request *req) -{ - u32 seqno; - - seqno = i915_gem_request_global_seqno(req); - if (!seqno) - return false; - - return __i915_gem_request_started(req, seqno); -} - -static inline bool __i915_gem_request_completed(const struct drm_i915_gem_request *req, u32 seqno) { GEM_BUG_ON(!seqno); @@ -352,21 +339,6 @@ i915_gem_request_completed(const struct drm_i915_gem_request *req) return __i915_gem_request_completed(req, seqno); } -bool __i915_spin_request(const struct drm_i915_gem_request *request, - u32 seqno, int state, unsigned long timeout_us); -static inline bool i915_spin_request(const struct drm_i915_gem_request *request, - int state, unsigned long timeout_us) -{ - u32 seqno; - - seqno = i915_gem_request_global_seqno(request); - if (!seqno) - return 0; - - return (__i915_gem_request_started(request, seqno) && - __i915_spin_request(request, seqno, state, timeout_us)); -} - /* We treat requests as fences. This is not be to confused with our * "fence registers" but pipeline synchronisation objects ala GL_ARB_sync. * We use the fences to synchronize access from the CPU with activity on the diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 74002b2d1b6f..3770e3323fc8 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -71,25 +71,6 @@ static void shrinker_unlock(struct drm_i915_private *dev_priv, bool unlock) mutex_unlock(&dev_priv->drm.struct_mutex); } -static bool any_vma_pinned(struct drm_i915_gem_object *obj) -{ - struct i915_vma *vma; - - list_for_each_entry(vma, &obj->vma_list, obj_link) { - /* Only GGTT vma may be permanently pinned, and are always - * at the start of the list. We can stop hunting as soon - * as we see a ppGTT vma. - */ - if (!i915_vma_is_ggtt(vma)) - break; - - if (i915_vma_is_pinned(vma)) - return true; - } - - return false; -} - static bool swap_available(void) { return get_nr_swap_pages() > 0; @@ -97,9 +78,6 @@ static bool swap_available(void) static bool can_release_pages(struct drm_i915_gem_object *obj) { - if (!obj->mm.pages) - return false; - /* Consider only shrinkable ojects. */ if (!i915_gem_object_is_shrinkable(obj)) return false; @@ -115,7 +93,13 @@ static bool can_release_pages(struct drm_i915_gem_object *obj) if (atomic_read(&obj->mm.pages_pin_count) > obj->bind_count) return false; - if (any_vma_pinned(obj)) + /* If any vma are "permanently" pinned, it will prevent us from + * reclaiming the obj->mm.pages. We only allow scanout objects to claim + * a permanent pin, along with a few others like the context objects. + * To simplify the scan, and to avoid walking the list of vma under the + * object, we just check the count of its permanently pinned. + */ + if (READ_ONCE(obj->pin_global)) return false; /* We can only return physical pages to the system if we can either @@ -129,7 +113,7 @@ static bool unsafe_drop_pages(struct drm_i915_gem_object *obj) { if (i915_gem_object_unbind(obj) == 0) __i915_gem_object_put_pages(obj, I915_MM_SHRINKER); - return !READ_ONCE(obj->mm.pages); + return !i915_gem_object_has_pages(obj); } /** @@ -178,6 +162,18 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, if (!shrinker_lock(dev_priv, &unlock)) return 0; + /* + * When shrinking the active list, also consider active contexts. + * Active contexts are pinned until they are retired, and so can + * not be simply unbound to retire and unpin their pages. To shrink + * the contexts, we must wait until the gpu is idle. + * + * We don't care about errors here; if we cannot wait upon the GPU, + * we will free as much as we can and hope to get a second chance. + */ + if (flags & I915_SHRINK_ACTIVE) + i915_gem_wait_for_idle(dev_priv, I915_WAIT_LOCKED); + trace_i915_gem_shrink(dev_priv, target, flags); i915_gem_retire_requests(dev_priv); @@ -217,15 +213,20 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, continue; INIT_LIST_HEAD(&still_in_list); + + /* + * We serialize our access to unreferenced objects through + * the use of the struct_mutex. While the objects are not + * yet freed (due to RCU then a workqueue) we still want + * to be able to shrink their pages, so they remain on + * the unbound/bound list until actually freed. + */ + spin_lock(&dev_priv->mm.obj_lock); while (count < target && (obj = list_first_entry_or_null(phase->list, typeof(*obj), - global_link))) { - list_move_tail(&obj->global_link, &still_in_list); - if (!obj->mm.pages) { - list_del_init(&obj->global_link); - continue; - } + mm.link))) { + list_move_tail(&obj->mm.link, &still_in_list); if (flags & I915_SHRINK_PURGEABLE && obj->mm.madv != I915_MADV_DONTNEED) @@ -243,20 +244,24 @@ i915_gem_shrink(struct drm_i915_private *dev_priv, if (!can_release_pages(obj)) continue; + spin_unlock(&dev_priv->mm.obj_lock); + if (unsafe_drop_pages(obj)) { /* May arrive from get_pages on another bo */ mutex_lock_nested(&obj->mm.lock, I915_MM_SHRINKER); - if (!obj->mm.pages) { + if (!i915_gem_object_has_pages(obj)) { __i915_gem_object_invalidate(obj); - list_del_init(&obj->global_link); count += obj->base.size >> PAGE_SHIFT; } mutex_unlock(&obj->mm.lock); - scanned += obj->base.size >> PAGE_SHIFT; } + scanned += obj->base.size >> PAGE_SHIFT; + + spin_lock(&dev_priv->mm.obj_lock); } list_splice_tail(&still_in_list, phase->list); + spin_unlock(&dev_priv->mm.obj_lock); } if (flags & I915_SHRINK_BOUND) @@ -302,28 +307,39 @@ unsigned long i915_gem_shrink_all(struct drm_i915_private *dev_priv) static unsigned long i915_gem_shrinker_count(struct shrinker *shrinker, struct shrink_control *sc) { - struct drm_i915_private *dev_priv = + struct drm_i915_private *i915 = container_of(shrinker, struct drm_i915_private, mm.shrinker); struct drm_i915_gem_object *obj; - unsigned long count; - bool unlock; - - if (!shrinker_lock(dev_priv, &unlock)) - return 0; - - i915_gem_retire_requests(dev_priv); + unsigned long num_objects = 0; + unsigned long count = 0; - count = 0; - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) - if (can_release_pages(obj)) + spin_lock(&i915->mm.obj_lock); + list_for_each_entry(obj, &i915->mm.unbound_list, mm.link) + if (can_release_pages(obj)) { count += obj->base.size >> PAGE_SHIFT; + num_objects++; + } - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { - if (!i915_gem_object_is_active(obj) && can_release_pages(obj)) + list_for_each_entry(obj, &i915->mm.bound_list, mm.link) + if (!i915_gem_object_is_active(obj) && can_release_pages(obj)) { count += obj->base.size >> PAGE_SHIFT; - } + num_objects++; + } + spin_unlock(&i915->mm.obj_lock); - shrinker_unlock(dev_priv, unlock); + /* Update our preferred vmscan batch size for the next pass. + * Our rough guess for an effective batch size is roughly 2 + * available GEM objects worth of pages. That is we don't want + * the shrinker to fire, until it is worth the cost of freeing an + * entire GEM object. + */ + if (num_objects) { + unsigned long avg = 2 * count / num_objects; + + i915->mm.shrinker.batch = + max((i915->mm.shrinker.batch + avg) >> 1, + 128ul /* default SHRINK_BATCH */); + } return count; } @@ -400,10 +416,6 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) container_of(nb, struct drm_i915_private, mm.oom_notifier); struct drm_i915_gem_object *obj; unsigned long unevictable, bound, unbound, freed_pages; - bool unlock; - - if (!shrinker_lock_uninterruptible(dev_priv, &unlock, 5000)) - return NOTIFY_DONE; freed_pages = i915_gem_shrink_all(dev_priv); @@ -412,26 +424,20 @@ i915_gem_shrinker_oom(struct notifier_block *nb, unsigned long event, void *ptr) * being pointed to by hardware. */ unbound = bound = unevictable = 0; - list_for_each_entry(obj, &dev_priv->mm.unbound_list, global_link) { - if (!obj->mm.pages) - continue; - + spin_lock(&dev_priv->mm.obj_lock); + list_for_each_entry(obj, &dev_priv->mm.unbound_list, mm.link) { if (!can_release_pages(obj)) unevictable += obj->base.size >> PAGE_SHIFT; else unbound += obj->base.size >> PAGE_SHIFT; } - list_for_each_entry(obj, &dev_priv->mm.bound_list, global_link) { - if (!obj->mm.pages) - continue; - + list_for_each_entry(obj, &dev_priv->mm.bound_list, mm.link) { if (!can_release_pages(obj)) unevictable += obj->base.size >> PAGE_SHIFT; else bound += obj->base.size >> PAGE_SHIFT; } - - shrinker_unlock(dev_priv, unlock); + spin_unlock(&dev_priv->mm.obj_lock); if (freed_pages || unbound || bound) pr_info("Purging GPU memory, %lu pages freed, " @@ -498,6 +504,7 @@ void i915_gem_shrinker_init(struct drm_i915_private *dev_priv) dev_priv->mm.shrinker.scan_objects = i915_gem_shrinker_scan; dev_priv->mm.shrinker.count_objects = i915_gem_shrinker_count; dev_priv->mm.shrinker.seeks = DEFAULT_SEEKS; + dev_priv->mm.shrinker.batch = 4096; WARN_ON(register_shrinker(&dev_priv->mm.shrinker)); dev_priv->mm.oom_notifier.notifier_call = i915_gem_shrinker_oom; diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c index 507c9f0d8df1..03e7abc7e043 100644 --- a/drivers/gpu/drm/i915/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/i915_gem_stolen.c @@ -539,12 +539,18 @@ i915_pages_create_for_stolen(struct drm_device *dev, return st; } -static struct sg_table * -i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj) +static int i915_gem_object_get_pages_stolen(struct drm_i915_gem_object *obj) { - return i915_pages_create_for_stolen(obj->base.dev, - obj->stolen->start, - obj->stolen->size); + struct sg_table *pages = + i915_pages_create_for_stolen(obj->base.dev, + obj->stolen->start, + obj->stolen->size); + if (IS_ERR(pages)) + return PTR_ERR(pages); + + __i915_gem_object_set_pages(obj, pages, obj->stolen->size); + + return 0; } static void i915_gem_object_put_pages_stolen(struct drm_i915_gem_object *obj, @@ -718,8 +724,11 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv vma->flags |= I915_VMA_GLOBAL_BIND; __i915_vma_set_map_and_fenceable(vma); list_move_tail(&vma->vm_link, &ggtt->base.inactive_list); - list_move_tail(&obj->global_link, &dev_priv->mm.bound_list); + + spin_lock(&dev_priv->mm.obj_lock); + list_move_tail(&obj->mm.link, &dev_priv->mm.bound_list); obj->bind_count++; + spin_unlock(&dev_priv->mm.obj_lock); return obj; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index fb5231f98c0d..1294cf695df0 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -269,7 +269,7 @@ i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, * due to the change in swizzling. */ mutex_lock(&obj->mm.lock); - if (obj->mm.pages && + if (i915_gem_object_has_pages(obj) && obj->mm.madv == I915_MADV_WILLNEED && i915->quirks & QUIRK_PIN_SWIZZLED_PAGES) { if (tiling == I915_TILING_NONE) { diff --git a/drivers/gpu/drm/i915/i915_gem_userptr.c b/drivers/gpu/drm/i915/i915_gem_userptr.c index 709efe2357ea..e26b23171b56 100644 --- a/drivers/gpu/drm/i915/i915_gem_userptr.c +++ b/drivers/gpu/drm/i915/i915_gem_userptr.c @@ -82,11 +82,11 @@ static void cancel_userptr(struct work_struct *work) /* We are inside a kthread context and can't be interrupted */ if (i915_gem_object_unbind(obj) == 0) __i915_gem_object_put_pages(obj, I915_MM_NORMAL); - WARN_ONCE(obj->mm.pages, - "Failed to release pages: bind_count=%d, pages_pin_count=%d, pin_display=%d\n", + WARN_ONCE(i915_gem_object_has_pages(obj), + "Failed to release pages: bind_count=%d, pages_pin_count=%d, pin_global=%d\n", obj->bind_count, atomic_read(&obj->mm.pages_pin_count), - obj->pin_display); + obj->pin_global); mutex_unlock(&obj->base.dev->struct_mutex); @@ -164,7 +164,6 @@ static struct i915_mmu_notifier * i915_mmu_notifier_create(struct mm_struct *mm) { struct i915_mmu_notifier *mn; - int ret; mn = kmalloc(sizeof(*mn), GFP_KERNEL); if (mn == NULL) @@ -179,14 +178,6 @@ i915_mmu_notifier_create(struct mm_struct *mm) return ERR_PTR(-ENOMEM); } - /* Protected by mmap_sem (write-lock) */ - ret = __mmu_notifier_register(&mn->mn, mm); - if (ret) { - destroy_workqueue(mn->wq); - kfree(mn); - return ERR_PTR(ret); - } - return mn; } @@ -210,23 +201,42 @@ i915_gem_userptr_release__mmu_notifier(struct drm_i915_gem_object *obj) static struct i915_mmu_notifier * i915_mmu_notifier_find(struct i915_mm_struct *mm) { - struct i915_mmu_notifier *mn = mm->mn; + struct i915_mmu_notifier *mn; + int err = 0; mn = mm->mn; if (mn) return mn; + mn = i915_mmu_notifier_create(mm->mm); + if (IS_ERR(mn)) + err = PTR_ERR(mn); + down_write(&mm->mm->mmap_sem); mutex_lock(&mm->i915->mm_lock); - if ((mn = mm->mn) == NULL) { - mn = i915_mmu_notifier_create(mm->mm); - if (!IS_ERR(mn)) - mm->mn = mn; + if (mm->mn == NULL && !err) { + /* Protected by mmap_sem (write-lock) */ + err = __mmu_notifier_register(&mn->mn, mm->mm); + if (!err) { + /* Protected by mm_lock */ + mm->mn = fetch_and_zero(&mn); + } + } else if (mm->mn) { + /* + * Someone else raced and successfully installed the mmu + * notifier, we can cancel our own errors. + */ + err = 0; } mutex_unlock(&mm->i915->mm_lock); up_write(&mm->mm->mmap_sem); - return mn; + if (mn && !IS_ERR(mn)) { + destroy_workqueue(mn->wq); + kfree(mn); + } + + return err ? ERR_PTR(err) : mm->mn; } static int @@ -399,64 +409,47 @@ struct get_pages_work { struct task_struct *task; }; -#if IS_ENABLED(CONFIG_SWIOTLB) -#define swiotlb_active() swiotlb_nr_tbl() -#else -#define swiotlb_active() 0 -#endif - -static int -st_set_pages(struct sg_table **st, struct page **pvec, int num_pages) -{ - struct scatterlist *sg; - int ret, n; - - *st = kmalloc(sizeof(**st), GFP_KERNEL); - if (*st == NULL) - return -ENOMEM; - - if (swiotlb_active()) { - ret = sg_alloc_table(*st, num_pages, GFP_KERNEL); - if (ret) - goto err; - - for_each_sg((*st)->sgl, sg, num_pages, n) - sg_set_page(sg, pvec[n], PAGE_SIZE, 0); - } else { - ret = sg_alloc_table_from_pages(*st, pvec, num_pages, - 0, num_pages << PAGE_SHIFT, - GFP_KERNEL); - if (ret) - goto err; - } - - return 0; - -err: - kfree(*st); - *st = NULL; - return ret; -} - static struct sg_table * -__i915_gem_userptr_set_pages(struct drm_i915_gem_object *obj, - struct page **pvec, int num_pages) +__i915_gem_userptr_alloc_pages(struct drm_i915_gem_object *obj, + struct page **pvec, int num_pages) { - struct sg_table *pages; + unsigned int max_segment = i915_sg_segment_size(); + struct sg_table *st; + unsigned int sg_page_sizes; int ret; - ret = st_set_pages(&pages, pvec, num_pages); - if (ret) + st = kmalloc(sizeof(*st), GFP_KERNEL); + if (!st) + return ERR_PTR(-ENOMEM); + +alloc_table: + ret = __sg_alloc_table_from_pages(st, pvec, num_pages, + 0, num_pages << PAGE_SHIFT, + max_segment, + GFP_KERNEL); + if (ret) { + kfree(st); return ERR_PTR(ret); + } - ret = i915_gem_gtt_prepare_pages(obj, pages); + ret = i915_gem_gtt_prepare_pages(obj, st); if (ret) { - sg_free_table(pages); - kfree(pages); + sg_free_table(st); + + if (max_segment > PAGE_SIZE) { + max_segment = PAGE_SIZE; + goto alloc_table; + } + + kfree(st); return ERR_PTR(ret); } - return pages; + sg_page_sizes = i915_sg_page_sizes(st->sgl); + + __i915_gem_object_set_pages(obj, st, sg_page_sizes); + + return st; } static int @@ -540,9 +533,9 @@ __i915_gem_userptr_get_pages_worker(struct work_struct *_work) struct sg_table *pages = ERR_PTR(ret); if (pinned == npages) { - pages = __i915_gem_userptr_set_pages(obj, pvec, npages); + pages = __i915_gem_userptr_alloc_pages(obj, pvec, + npages); if (!IS_ERR(pages)) { - __i915_gem_object_set_pages(obj, pages); pinned = 0; pages = NULL; } @@ -603,8 +596,7 @@ __i915_gem_userptr_get_pages_schedule(struct drm_i915_gem_object *obj) return ERR_PTR(-EAGAIN); } -static struct sg_table * -i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) +static int i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) { const int num_pages = obj->base.size >> PAGE_SHIFT; struct mm_struct *mm = obj->userptr.mm->mm; @@ -633,9 +625,9 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) if (obj->userptr.work) { /* active flag should still be held for the pending work */ if (IS_ERR(obj->userptr.work)) - return ERR_CAST(obj->userptr.work); + return PTR_ERR(obj->userptr.work); else - return ERR_PTR(-EAGAIN); + return -EAGAIN; } pvec = NULL; @@ -661,7 +653,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) pages = __i915_gem_userptr_get_pages_schedule(obj); active = pages == ERR_PTR(-EAGAIN); } else { - pages = __i915_gem_userptr_set_pages(obj, pvec, num_pages); + pages = __i915_gem_userptr_alloc_pages(obj, pvec, num_pages); active = !IS_ERR(pages); } if (active) @@ -671,7 +663,7 @@ i915_gem_userptr_get_pages(struct drm_i915_gem_object *obj) release_pages(pvec, pinned, 0); kvfree(pvec); - return pages; + return PTR_ERR_OR_ZERO(pages); } static void @@ -834,7 +826,9 @@ int i915_gem_init_userptr(struct drm_i915_private *dev_priv) hash_init(dev_priv->mm_structs); dev_priv->mm.userptr_wq = - alloc_workqueue("i915-userptr-acquire", WQ_HIGHPRI, 0); + alloc_workqueue("i915-userptr-acquire", + WQ_HIGHPRI | WQ_MEM_RECLAIM, + 0); if (!dev_priv->mm.userptr_wq) return -ENOMEM; diff --git a/drivers/gpu/drm/i915/i915_gemfs.c b/drivers/gpu/drm/i915/i915_gemfs.c new file mode 100644 index 000000000000..e2993857df37 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gemfs.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION 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 <linux/fs.h> +#include <linux/mount.h> +#include <linux/pagemap.h> + +#include "i915_drv.h" +#include "i915_gemfs.h" + +int i915_gemfs_init(struct drm_i915_private *i915) +{ + struct file_system_type *type; + struct vfsmount *gemfs; + + type = get_fs_type("tmpfs"); + if (!type) + return -ENODEV; + + gemfs = kern_mount(type); + if (IS_ERR(gemfs)) + return PTR_ERR(gemfs); + + /* + * Enable huge-pages for objects that are at least HPAGE_PMD_SIZE, most + * likely 2M. Note that within_size may overallocate huge-pages, if say + * we allocate an object of size 2M + 4K, we may get 2M + 2M, but under + * memory pressure shmem should split any huge-pages which can be + * shrunk. + */ + + if (has_transparent_hugepage()) { + struct super_block *sb = gemfs->mnt_sb; + char options[] = "huge=within_size"; + int flags = 0; + int err; + + err = sb->s_op->remount_fs(sb, &flags, options); + if (err) { + kern_unmount(gemfs); + return err; + } + } + + i915->mm.gemfs = gemfs; + + return 0; +} + +void i915_gemfs_fini(struct drm_i915_private *i915) +{ + kern_unmount(i915->mm.gemfs); +} diff --git a/drivers/gpu/drm/i915/i915_gemfs.h b/drivers/gpu/drm/i915/i915_gemfs.h new file mode 100644 index 000000000000..cca8bdc5b93e --- /dev/null +++ b/drivers/gpu/drm/i915/i915_gemfs.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef __I915_GEMFS_H__ +#define __I915_GEMFS_H__ + +struct drm_i915_private; + +int i915_gemfs_init(struct drm_i915_private *i915); + +void i915_gemfs_fini(struct drm_i915_private *i915); + +#endif diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 0c779671fe2d..653fb69e7ecb 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -377,9 +377,9 @@ static void error_print_request(struct drm_i915_error_state_buf *m, if (!erq->seqno) return; - err_printf(m, "%s pid %d, ban score %d, seqno %8x:%08x, emitted %dms ago, head %08x, tail %08x\n", + err_printf(m, "%s pid %d, ban score %d, seqno %8x:%08x, prio %d, emitted %dms ago, head %08x, tail %08x\n", prefix, erq->pid, erq->ban_score, - erq->context, erq->seqno, + erq->context, erq->seqno, erq->priority, jiffies_to_msecs(jiffies - erq->jiffies), erq->head, erq->tail); } @@ -388,14 +388,16 @@ static void error_print_context(struct drm_i915_error_state_buf *m, const char *header, const struct drm_i915_error_context *ctx) { - err_printf(m, "%s%s[%d] user_handle %d hw_id %d, ban score %d guilty %d active %d\n", + err_printf(m, "%s%s[%d] user_handle %d hw_id %d, prio %d, ban score %d guilty %d active %d\n", header, ctx->comm, ctx->pid, ctx->handle, ctx->hw_id, - ctx->ban_score, ctx->guilty, ctx->active); + ctx->priority, ctx->ban_score, ctx->guilty, ctx->active); } static void error_print_engine(struct drm_i915_error_state_buf *m, const struct drm_i915_error_engine *ee) { + int n; + err_printf(m, "%s command stream:\n", engine_str(ee->engine_id)); err_printf(m, " START: 0x%08x\n", ee->start); err_printf(m, " HEAD: 0x%08x [0x%08x]\n", ee->head, ee->rq_head); @@ -465,8 +467,11 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, jiffies_to_msecs(jiffies - ee->hangcheck_timestamp)); err_printf(m, " engine reset count: %u\n", ee->reset_count); - error_print_request(m, " ELSP[0]: ", &ee->execlist[0]); - error_print_request(m, " ELSP[1]: ", &ee->execlist[1]); + for (n = 0; n < ee->num_ports; n++) { + err_printf(m, " ELSP[%d]:", n); + error_print_request(m, " ", &ee->execlist[n]); + } + error_print_context(m, " Active context: ", &ee->context); } @@ -567,7 +572,7 @@ static __always_inline void err_print_param(struct drm_i915_error_state_buf *m, static void err_print_params(struct drm_i915_error_state_buf *m, const struct i915_params *p) { -#define PRINT(T, x) err_print_param(m, #x, #T, &p->x); +#define PRINT(T, x, ...) err_print_param(m, #x, #T, &p->x); I915_PARAMS_FOR_EACH(PRINT); #undef PRINT } @@ -861,7 +866,7 @@ void __i915_gpu_state_free(struct kref *error_ref) kfree(error->overlay); kfree(error->display); -#define FREE(T, x) free_param(#T, &error->params.x); +#define FREE(T, x, ...) free_param(#T, &error->params.x); I915_PARAMS_FOR_EACH(FREE); #undef FREE @@ -1266,6 +1271,7 @@ static void record_request(struct drm_i915_gem_request *request, struct drm_i915_error_request *erq) { erq->context = request->ctx->hw_id; + erq->priority = request->priotree.priority; erq->ban_score = atomic_read(&request->ctx->ban_score); erq->seqno = request->global_seqno; erq->jiffies = request->emitted_jiffies; @@ -1327,17 +1333,19 @@ static void engine_record_requests(struct intel_engine_cs *engine, static void error_record_engine_execlists(struct intel_engine_cs *engine, struct drm_i915_error_engine *ee) { - const struct execlist_port *port = engine->execlist_port; + const struct intel_engine_execlists * const execlists = &engine->execlists; unsigned int n; - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) { - struct drm_i915_gem_request *rq = port_request(&port[n]); + for (n = 0; n < execlists_num_ports(execlists); n++) { + struct drm_i915_gem_request *rq = port_request(&execlists->port[n]); if (!rq) break; record_request(rq, &ee->execlist[n]); } + + ee->num_ports = n; } static void record_context(struct drm_i915_error_context *e, @@ -1357,6 +1365,7 @@ static void record_context(struct drm_i915_error_context *e, e->handle = ctx->user_handle; e->hw_id = ctx->hw_id; + e->priority = ctx->priority; e->ban_score = atomic_read(&ctx->ban_score); e->guilty = atomic_read(&ctx->guilty_count); e->active = atomic_read(&ctx->active_count); @@ -1554,7 +1563,7 @@ static void i915_gem_capture_guc_log_buffer(struct drm_i915_private *dev_priv, struct i915_gpu_state *error) { /* Capturing log buf contents won't be useful if logging was disabled */ - if (!dev_priv->guc.log.vma || (i915.guc_log_level < 0)) + if (!dev_priv->guc.log.vma || (i915_modparams.guc_log_level < 0)) return; error->guc_log = i915_error_object_create(dev_priv, @@ -1665,8 +1674,8 @@ static void i915_capture_gen_state(struct drm_i915_private *dev_priv, struct i915_gpu_state *error) { error->awake = dev_priv->gt.awake; - error->wakelock = atomic_read(&dev_priv->pm.wakeref_count); - error->suspended = dev_priv->pm.suspended; + error->wakelock = atomic_read(&dev_priv->runtime_pm.wakeref_count); + error->suspended = dev_priv->runtime_pm.suspended; error->iommu = -1; #ifdef CONFIG_INTEL_IOMMU @@ -1696,8 +1705,8 @@ static int capture(void *data) ktime_to_timeval(ktime_sub(ktime_get(), error->i915->gt.last_init_time)); - error->params = i915; -#define DUP(T, x) dup_param(#T, &error->params.x); + error->params = i915_modparams; +#define DUP(T, x, ...) dup_param(#T, &error->params.x); I915_PARAMS_FOR_EACH(DUP); #undef DUP @@ -1751,7 +1760,7 @@ void i915_capture_error_state(struct drm_i915_private *dev_priv, struct i915_gpu_state *error; unsigned long flags; - if (!i915.error_capture) + if (!i915_modparams.error_capture) return; if (READ_ONCE(dev_priv->gpu_error.first_error)) diff --git a/drivers/gpu/drm/i915/i915_guc_submission.c b/drivers/gpu/drm/i915/i915_guc_submission.c index 48a1e9349a2c..f84c267728fd 100644 --- a/drivers/gpu/drm/i915/i915_guc_submission.c +++ b/drivers/gpu/drm/i915/i915_guc_submission.c @@ -21,12 +21,13 @@ * IN THE SOFTWARE. * */ -#include <linux/circ_buf.h> -#include "i915_drv.h" -#include "intel_uc.h" +#include <linux/circ_buf.h> #include <trace/events/dma_fence.h> +#include "i915_guc_submission.h" +#include "i915_drv.h" + /** * DOC: GuC-based command submission * @@ -192,13 +193,12 @@ static int __create_doorbell(struct i915_guc_client *client) doorbell = __get_doorbell(client); doorbell->db_status = GUC_DOORBELL_ENABLED; - doorbell->cookie = client->doorbell_cookie; + doorbell->cookie = 0; err = __guc_allocate_doorbell(client->guc, client->stage_id); - if (err) { + if (err) doorbell->db_status = GUC_DOORBELL_DISABLED; - doorbell->cookie = 0; - } + return err; } @@ -306,7 +306,7 @@ static void guc_proc_desc_init(struct intel_guc *guc, desc->db_base_addr = 0; desc->stage_id = client->stage_id; - desc->wq_size_bytes = client->wq_size; + desc->wq_size_bytes = GUC_WQ_SIZE; desc->wq_status = WQ_STATUS_ACTIVE; desc->priority = client->priority; } @@ -338,7 +338,7 @@ static void guc_stage_desc_init(struct intel_guc *guc, for_each_engine_masked(engine, dev_priv, client->engines, tmp) { struct intel_context *ce = &ctx->engine[engine->id]; - uint32_t guc_engine_id = engine->guc_id; + u32 guc_engine_id = engine->guc_id; struct guc_execlist_context *lrc = &desc->lrc[guc_engine_id]; /* TODO: We have a design issue to be solved here. Only when we @@ -388,13 +388,13 @@ static void guc_stage_desc_init(struct intel_guc *guc, gfx_addr = guc_ggtt_offset(client->vma); desc->db_trigger_phy = sg_dma_address(client->vma->pages->sgl) + client->doorbell_offset; - desc->db_trigger_cpu = (uintptr_t)__get_doorbell(client); + desc->db_trigger_cpu = ptr_to_u64(__get_doorbell(client)); desc->db_trigger_uk = gfx_addr + client->doorbell_offset; desc->process_desc = gfx_addr + client->proc_desc_offset; - desc->wq_addr = gfx_addr + client->wq_offset; - desc->wq_size = client->wq_size; + desc->wq_addr = gfx_addr + GUC_DB_SIZE; + desc->wq_size = GUC_WQ_SIZE; - desc->desc_private = (uintptr_t)client; + desc->desc_private = ptr_to_u64(client); } static void guc_stage_desc_fini(struct intel_guc *guc, @@ -406,82 +406,23 @@ static void guc_stage_desc_fini(struct intel_guc *guc, memset(desc, 0, sizeof(*desc)); } -/** - * i915_guc_wq_reserve() - reserve space in the GuC's workqueue - * @request: request associated with the commands - * - * Return: 0 if space is available - * -EAGAIN if space is not currently available - * - * This function must be called (and must return 0) before a request - * is submitted to the GuC via i915_guc_submit() below. Once a result - * of 0 has been returned, it must be balanced by a corresponding - * call to submit(). - * - * Reservation allows the caller to determine in advance that space - * will be available for the next submission before committing resources - * to it, and helps avoid late failures with complicated recovery paths. - */ -int i915_guc_wq_reserve(struct drm_i915_gem_request *request) -{ - const size_t wqi_size = sizeof(struct guc_wq_item); - struct i915_guc_client *client = request->i915->guc.execbuf_client; - struct guc_process_desc *desc = __get_process_desc(client); - u32 freespace; - int ret; - - spin_lock_irq(&client->wq_lock); - freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); - freespace -= client->wq_rsvd; - if (likely(freespace >= wqi_size)) { - client->wq_rsvd += wqi_size; - ret = 0; - } else { - client->no_wq_space++; - ret = -EAGAIN; - } - spin_unlock_irq(&client->wq_lock); - - return ret; -} - -static void guc_client_update_wq_rsvd(struct i915_guc_client *client, int size) -{ - unsigned long flags; - - spin_lock_irqsave(&client->wq_lock, flags); - client->wq_rsvd += size; - spin_unlock_irqrestore(&client->wq_lock, flags); -} - -void i915_guc_wq_unreserve(struct drm_i915_gem_request *request) -{ - const int wqi_size = sizeof(struct guc_wq_item); - struct i915_guc_client *client = request->i915->guc.execbuf_client; - - GEM_BUG_ON(READ_ONCE(client->wq_rsvd) < wqi_size); - guc_client_update_wq_rsvd(client, -wqi_size); -} - /* Construct a Work Item and append it to the GuC's Work Queue */ static void guc_wq_item_append(struct i915_guc_client *client, struct drm_i915_gem_request *rq) { /* wqi_len is in DWords, and does not include the one-word header */ const size_t wqi_size = sizeof(struct guc_wq_item); - const u32 wqi_len = wqi_size/sizeof(u32) - 1; + const u32 wqi_len = wqi_size / sizeof(u32) - 1; struct intel_engine_cs *engine = rq->engine; + struct i915_gem_context *ctx = rq->ctx; struct guc_process_desc *desc = __get_process_desc(client); struct guc_wq_item *wqi; - u32 freespace, tail, wq_off; + u32 ring_tail, wq_off; - /* Free space is guaranteed, see i915_guc_wq_reserve() above */ - freespace = CIRC_SPACE(client->wq_tail, desc->head, client->wq_size); - GEM_BUG_ON(freespace < wqi_size); + lockdep_assert_held(&client->wq_lock); - /* The GuC firmware wants the tail index in QWords, not bytes */ - tail = intel_ring_set_tail(rq->ring, rq->tail) >> 3; - GEM_BUG_ON(tail > WQ_RING_TAIL_MAX); + ring_tail = intel_ring_set_tail(rq->ring, rq->tail) / sizeof(u64); + GEM_BUG_ON(ring_tail > WQ_RING_TAIL_MAX); /* For now workqueue item is 4 DWs; workqueue buffer is 2 pages. So we * should not have the case where structure wqi is across page, neither @@ -491,29 +432,29 @@ static void guc_wq_item_append(struct i915_guc_client *client, * workqueue buffer dw by dw. */ BUILD_BUG_ON(wqi_size != 16); - GEM_BUG_ON(client->wq_rsvd < wqi_size); - /* postincrement WQ tail for next time */ - wq_off = client->wq_tail; + /* Free space is guaranteed. */ + wq_off = READ_ONCE(desc->tail); + GEM_BUG_ON(CIRC_SPACE(wq_off, READ_ONCE(desc->head), + GUC_WQ_SIZE) < wqi_size); GEM_BUG_ON(wq_off & (wqi_size - 1)); - client->wq_tail += wqi_size; - client->wq_tail &= client->wq_size - 1; - client->wq_rsvd -= wqi_size; /* WQ starts from the page after doorbell / process_desc */ wqi = client->vaddr + wq_off + GUC_DB_SIZE; /* Now fill in the 4-word work queue item */ wqi->header = WQ_TYPE_INORDER | - (wqi_len << WQ_LEN_SHIFT) | - (engine->guc_id << WQ_TARGET_SHIFT) | - WQ_NO_WCFLUSH_WAIT; + (wqi_len << WQ_LEN_SHIFT) | + (engine->guc_id << WQ_TARGET_SHIFT) | + WQ_NO_WCFLUSH_WAIT; - /* The GuC wants only the low-order word of the context descriptor */ - wqi->context_desc = (u32)intel_lr_context_descriptor(rq->ctx, engine); + wqi->context_desc = lower_32_bits(intel_lr_context_descriptor(ctx, engine)); - wqi->submit_element_info = tail << WQ_RING_TAIL_SHIFT; + wqi->submit_element_info = ring_tail << WQ_RING_TAIL_SHIFT; wqi->fence_id = rq->global_seqno; + + /* Postincrement WQ tail for next time. */ + WRITE_ONCE(desc->tail, (wq_off + wqi_size) & (GUC_WQ_SIZE - 1)); } static void guc_reset_wq(struct i915_guc_client *client) @@ -522,106 +463,64 @@ static void guc_reset_wq(struct i915_guc_client *client) desc->head = 0; desc->tail = 0; - - client->wq_tail = 0; } -static int guc_ring_doorbell(struct i915_guc_client *client) +static void guc_ring_doorbell(struct i915_guc_client *client) { - struct guc_process_desc *desc = __get_process_desc(client); - union guc_doorbell_qw db_cmp, db_exc, db_ret; - union guc_doorbell_qw *db; - int attempt = 2, ret = -EAGAIN; + struct guc_doorbell_info *db; + u32 cookie; - /* Update the tail so it is visible to GuC */ - desc->tail = client->wq_tail; - - /* current cookie */ - db_cmp.db_status = GUC_DOORBELL_ENABLED; - db_cmp.cookie = client->doorbell_cookie; - - /* cookie to be updated */ - db_exc.db_status = GUC_DOORBELL_ENABLED; - db_exc.cookie = client->doorbell_cookie + 1; - if (db_exc.cookie == 0) - db_exc.cookie = 1; + lockdep_assert_held(&client->wq_lock); /* pointer of current doorbell cacheline */ - db = (union guc_doorbell_qw *)__get_doorbell(client); - - while (attempt--) { - /* lets ring the doorbell */ - db_ret.value_qw = atomic64_cmpxchg((atomic64_t *)db, - db_cmp.value_qw, db_exc.value_qw); - - /* if the exchange was successfully executed */ - if (db_ret.value_qw == db_cmp.value_qw) { - /* db was successfully rung */ - client->doorbell_cookie = db_exc.cookie; - ret = 0; - break; - } - - /* XXX: doorbell was lost and need to acquire it again */ - if (db_ret.db_status == GUC_DOORBELL_DISABLED) - break; + db = __get_doorbell(client); - DRM_WARN("Cookie mismatch. Expected %d, found %d\n", - db_cmp.cookie, db_ret.cookie); + /* we're not expecting the doorbell cookie to change behind our back */ + cookie = READ_ONCE(db->cookie); + WARN_ON_ONCE(xchg(&db->cookie, cookie + 1) != cookie); - /* update the cookie to newly read cookie from GuC */ - db_cmp.cookie = db_ret.cookie; - db_exc.cookie = db_ret.cookie + 1; - if (db_exc.cookie == 0) - db_exc.cookie = 1; - } - - return ret; + /* XXX: doorbell was lost and need to acquire it again */ + GEM_BUG_ON(db->db_status != GUC_DOORBELL_ENABLED); } /** - * __i915_guc_submit() - Submit commands through GuC - * @rq: request associated with the commands - * - * The caller must have already called i915_guc_wq_reserve() above with - * a result of 0 (success), guaranteeing that there is space in the work - * queue for the new request, so enqueuing the item cannot fail. - * - * Bad Things Will Happen if the caller violates this protocol e.g. calls - * submit() when _reserve() says there's no space, or calls _submit() - * a different number of times from (successful) calls to _reserve(). + * i915_guc_submit() - Submit commands through GuC + * @engine: engine associated with the commands * * The only error here arises if the doorbell hardware isn't functioning * as expected, which really shouln't happen. */ -static void __i915_guc_submit(struct drm_i915_gem_request *rq) +static void i915_guc_submit(struct intel_engine_cs *engine) { - struct drm_i915_private *dev_priv = rq->i915; - struct intel_engine_cs *engine = rq->engine; - unsigned int engine_id = engine->id; - struct intel_guc *guc = &rq->i915->guc; + struct drm_i915_private *dev_priv = engine->i915; + struct intel_guc *guc = &dev_priv->guc; struct i915_guc_client *client = guc->execbuf_client; - unsigned long flags; - int b_ret; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; + const unsigned int engine_id = engine->id; + unsigned int n; - /* WA to flush out the pending GMADR writes to ring buffer. */ - if (i915_vma_is_map_and_fenceable(rq->ring->vma)) - POSTING_READ_FW(GUC_STATUS); + for (n = 0; n < execlists_num_ports(execlists); n++) { + struct drm_i915_gem_request *rq; + unsigned int count; - spin_lock_irqsave(&client->wq_lock, flags); + rq = port_unpack(&port[n], &count); + if (rq && count == 0) { + port_set(&port[n], port_pack(rq, ++count)); - guc_wq_item_append(client, rq); - b_ret = guc_ring_doorbell(client); + if (i915_vma_is_map_and_fenceable(rq->ring->vma)) + POSTING_READ_FW(GUC_STATUS); - client->submissions[engine_id] += 1; + spin_lock(&client->wq_lock); - spin_unlock_irqrestore(&client->wq_lock, flags); -} + guc_wq_item_append(client, rq); + guc_ring_doorbell(client); -static void i915_guc_submit(struct drm_i915_gem_request *rq) -{ - __i915_gem_request_submit(rq); - __i915_guc_submit(rq); + client->submissions[engine_id] += 1; + + spin_unlock(&client->wq_lock); + } + } } static void nested_enable_signaling(struct drm_i915_gem_request *rq) @@ -655,27 +554,33 @@ static void port_assign(struct execlist_port *port, if (port_isset(port)) i915_gem_request_put(port_request(port)); - port_set(port, i915_gem_request_get(rq)); + port_set(port, port_pack(i915_gem_request_get(rq), port_count(port))); nested_enable_signaling(rq); } -static bool i915_guc_dequeue(struct intel_engine_cs *engine) +static void i915_guc_dequeue(struct intel_engine_cs *engine) { - struct execlist_port *port = engine->execlist_port; - struct drm_i915_gem_request *last = port_request(port); - struct rb_node *rb; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; + struct drm_i915_gem_request *last = NULL; + const struct execlist_port * const last_port = + &execlists->port[execlists->port_mask]; bool submit = false; + struct rb_node *rb; + + if (port_isset(port)) + port++; spin_lock_irq(&engine->timeline->lock); - rb = engine->execlist_first; - GEM_BUG_ON(rb_first(&engine->execlist_queue) != rb); + rb = execlists->first; + GEM_BUG_ON(rb_first(&execlists->queue) != rb); while (rb) { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); struct drm_i915_gem_request *rq, *rn; list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { if (last && rq->ctx != last->ctx) { - if (port != engine->execlist_port) { + if (port == last_port) { __list_del_many(&p->requests, &rq->priotree.link); goto done; @@ -689,50 +594,51 @@ static bool i915_guc_dequeue(struct intel_engine_cs *engine) INIT_LIST_HEAD(&rq->priotree.link); rq->priotree.priority = INT_MAX; - i915_guc_submit(rq); - trace_i915_gem_request_in(rq, port_index(port, engine)); + __i915_gem_request_submit(rq); + trace_i915_gem_request_in(rq, port_index(port, execlists)); last = rq; submit = true; } rb = rb_next(rb); - rb_erase(&p->node, &engine->execlist_queue); + rb_erase(&p->node, &execlists->queue); INIT_LIST_HEAD(&p->requests); if (p->priority != I915_PRIORITY_NORMAL) kmem_cache_free(engine->i915->priorities, p); } done: - engine->execlist_first = rb; - if (submit) + execlists->first = rb; + if (submit) { port_assign(port, last); + execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); + i915_guc_submit(engine); + } spin_unlock_irq(&engine->timeline->lock); - - return submit; } static void i915_guc_irq_handler(unsigned long data) { - struct intel_engine_cs *engine = (struct intel_engine_cs *)data; - struct execlist_port *port = engine->execlist_port; + struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; + const struct execlist_port * const last_port = + &execlists->port[execlists->port_mask]; struct drm_i915_gem_request *rq; - bool submit; - do { - rq = port_request(&port[0]); - while (rq && i915_gem_request_completed(rq)) { - trace_i915_gem_request_out(rq); - i915_gem_request_put(rq); + rq = port_request(&port[0]); + while (rq && i915_gem_request_completed(rq)) { + trace_i915_gem_request_out(rq); + i915_gem_request_put(rq); - port[0] = port[1]; - memset(&port[1], 0, sizeof(port[1])); + execlists_port_complete(execlists, port); - rq = port_request(&port[0]); - } + rq = port_request(&port[0]); + } + if (!rq) + execlists_clear_active(execlists, EXECLISTS_ACTIVE_USER); - submit = false; - if (!port_count(&port[1])) - submit = i915_guc_dequeue(engine); - } while (submit); + if (!port_isset(last_port)) + i915_guc_dequeue(engine); } /* @@ -741,48 +647,6 @@ static void i915_guc_irq_handler(unsigned long data) * path of i915_guc_submit() above. */ -/** - * intel_guc_allocate_vma() - Allocate a GGTT VMA for GuC usage - * @guc: the guc - * @size: size of area to allocate (both virtual space and memory) - * - * This is a wrapper to create an object for use with the GuC. In order to - * use it inside the GuC, an object needs to be pinned lifetime, so we allocate - * both some backing storage and a range inside the Global GTT. We must pin - * it in the GGTT somewhere other than than [0, GUC_WOPCM_TOP) because that - * range is reserved inside GuC. - * - * Return: A i915_vma if successful, otherwise an ERR_PTR. - */ -struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) -{ - struct drm_i915_private *dev_priv = guc_to_i915(guc); - struct drm_i915_gem_object *obj; - struct i915_vma *vma; - int ret; - - obj = i915_gem_object_create(dev_priv, size); - if (IS_ERR(obj)) - return ERR_CAST(obj); - - vma = i915_vma_instance(obj, &dev_priv->ggtt.base, NULL); - if (IS_ERR(vma)) - goto err; - - ret = i915_vma_pin(vma, 0, PAGE_SIZE, - PIN_GLOBAL | PIN_OFFSET_BIAS | GUC_WOPCM_TOP); - if (ret) { - vma = ERR_PTR(ret); - goto err; - } - - return vma; - -err: - i915_gem_object_put(obj); - return vma; -} - /* Check that a doorbell register is in the expected state */ static bool doorbell_ok(struct intel_guc *guc, u16 db_id) { @@ -894,8 +758,8 @@ static int guc_init_doorbell_hw(struct intel_guc *guc) */ static struct i915_guc_client * guc_client_alloc(struct drm_i915_private *dev_priv, - uint32_t engines, - uint32_t priority, + u32 engines, + u32 priority, struct i915_gem_context *ctx) { struct i915_guc_client *client; @@ -913,8 +777,6 @@ guc_client_alloc(struct drm_i915_private *dev_priv, client->engines = engines; client->priority = priority; client->doorbell_id = GUC_DOORBELL_INVALID; - client->wq_offset = GUC_DB_SIZE; - client->wq_size = GUC_WQ_SIZE; spin_lock_init(&client->wq_lock); ret = ida_simple_get(&guc->stage_ids, 0, GUC_MAX_STAGE_DESCRIPTORS, @@ -996,28 +858,39 @@ static void guc_client_free(struct i915_guc_client *client) kfree(client); } +static void guc_policy_init(struct guc_policy *policy) +{ + policy->execution_quantum = POLICY_DEFAULT_EXECUTION_QUANTUM_US; + policy->preemption_time = POLICY_DEFAULT_PREEMPTION_TIME_US; + policy->fault_time = POLICY_DEFAULT_FAULT_TIME_US; + policy->policy_flags = 0; +} + static void guc_policies_init(struct guc_policies *policies) { struct guc_policy *policy; u32 p, i; - policies->dpc_promote_time = 500000; + policies->dpc_promote_time = POLICY_DEFAULT_DPC_PROMOTE_TIME_US; policies->max_num_work_items = POLICY_MAX_NUM_WI; for (p = 0; p < GUC_CLIENT_PRIORITY_NUM; p++) { for (i = GUC_RENDER_ENGINE; i < GUC_MAX_ENGINES_NUM; i++) { policy = &policies->policy[p][i]; - policy->execution_quantum = 1000000; - policy->preemption_time = 500000; - policy->fault_time = 250000; - policy->policy_flags = 0; + guc_policy_init(policy); } } policies->is_valid = 1; } +/* + * The first 80 dwords of the register state context, containing the + * execlists and ppgtt registers. + */ +#define LR_HW_CONTEXT_SIZE (80 * sizeof(u32)) + static int guc_ads_create(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); @@ -1032,6 +905,8 @@ static int guc_ads_create(struct intel_guc *guc) } __packed *blob; struct intel_engine_cs *engine; enum intel_engine_id id; + const u32 skipped_offset = LRC_HEADER_PAGES * PAGE_SIZE; + const u32 skipped_size = LRC_PPHWSP_SZ * PAGE_SIZE + LR_HW_CONTEXT_SIZE; u32 base; GEM_BUG_ON(guc->ads_vma); @@ -1062,13 +937,20 @@ static int guc_ads_create(struct intel_guc *guc) * engines after a reset. Here we use the Render ring default * context, which must already exist and be pinned in the GGTT, * so its address won't change after we've told the GuC where - * to find it. + * to find it. Note that we have to skip our header (1 page), + * because our GuC shared data is there. */ blob->ads.golden_context_lrca = - dev_priv->engine[RCS]->status_page.ggtt_offset; + guc_ggtt_offset(dev_priv->kernel_context->engine[RCS].state) + skipped_offset; + /* + * The GuC expects us to exclude the portion of the context image that + * it skips from the size it is to read. It starts reading from after + * the execlist context (so skipping the first page [PPHWSP] and 80 + * dwords). Weird guc is weird. + */ for_each_engine(engine, dev_priv, id) - blob->ads.eng_state_size[engine->guc_id] = engine->context_size; + blob->ads.eng_state_size[engine->guc_id] = engine->context_size - skipped_size; base = guc_ggtt_offset(vma); blob->ads.scheduler_policies = base + ptr_offset(blob, policies); @@ -1149,6 +1031,7 @@ void i915_guc_submission_fini(struct drm_i915_private *dev_priv) static void guc_interrupts_capture(struct drm_i915_private *dev_priv) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; struct intel_engine_cs *engine; enum intel_engine_id id; int irqs; @@ -1185,12 +1068,13 @@ static void guc_interrupts_capture(struct drm_i915_private *dev_priv) * Here we CLEAR REDIRECT_TO_GUC bit in pm_intrmsk_mbz, which will * result in the register bit being left SET! */ - dev_priv->rps.pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK; - dev_priv->rps.pm_intrmsk_mbz &= ~GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; + rps->pm_intrmsk_mbz |= ARAT_EXPIRED_INTRMSK; + rps->pm_intrmsk_mbz &= ~GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; } static void guc_interrupts_release(struct drm_i915_private *dev_priv) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; struct intel_engine_cs *engine; enum intel_engine_id id; int irqs; @@ -1209,8 +1093,8 @@ static void guc_interrupts_release(struct drm_i915_private *dev_priv) I915_WRITE(GUC_VCS2_VCS1_IER, 0); I915_WRITE(GUC_WD_VECS_IER, 0); - dev_priv->rps.pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; - dev_priv->rps.pm_intrmsk_mbz &= ~ARAT_EXPIRED_INTRMSK; + rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; + rps->pm_intrmsk_mbz &= ~ARAT_EXPIRED_INTRMSK; } int i915_guc_submission_enable(struct drm_i915_private *dev_priv) @@ -1221,6 +1105,19 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) enum intel_engine_id id; int err; + /* + * We're using GuC work items for submitting work through GuC. Since + * we're coalescing multiple requests from a single context into a + * single work item prior to assigning it to execlist_port, we can + * never have more work items than the total number of ports (for all + * engines). The GuC firmware is controlling the HEAD of work queue, + * and it is guaranteed that it will remove the work item from the + * queue before our request is completed. + */ + BUILD_BUG_ON(ARRAY_SIZE(engine->execlists.port) * + sizeof(struct guc_wq_item) * + I915_NUM_ENGINES > GUC_WQ_SIZE); + if (!client) { client = guc_client_alloc(dev_priv, INTEL_INFO(dev_priv)->ring_mask, @@ -1248,24 +1145,15 @@ int i915_guc_submission_enable(struct drm_i915_private *dev_priv) guc_interrupts_capture(dev_priv); for_each_engine(engine, dev_priv, id) { - const int wqi_size = sizeof(struct guc_wq_item); - struct drm_i915_gem_request *rq; - + struct intel_engine_execlists * const execlists = &engine->execlists; /* The tasklet was initialised by execlists, and may be in * a state of flux (across a reset) and so we just want to * take over the callback without changing any other state * in the tasklet. */ - engine->irq_tasklet.func = i915_guc_irq_handler; + execlists->irq_tasklet.func = i915_guc_irq_handler; clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); - - /* Replay the current set of previously submitted requests */ - spin_lock_irq(&engine->timeline->lock); - list_for_each_entry(rq, &engine->timeline->requests, link) { - guc_client_update_wq_rsvd(client, wqi_size); - __i915_guc_submit(rq); - } - spin_unlock_irq(&engine->timeline->lock); + tasklet_schedule(&execlists->irq_tasklet); } return 0; @@ -1288,55 +1176,3 @@ void i915_guc_submission_disable(struct drm_i915_private *dev_priv) guc_client_free(guc->execbuf_client); guc->execbuf_client = NULL; } - -/** - * intel_guc_suspend() - notify GuC entering suspend state - * @dev_priv: i915 device private - */ -int intel_guc_suspend(struct drm_i915_private *dev_priv) -{ - struct intel_guc *guc = &dev_priv->guc; - struct i915_gem_context *ctx; - u32 data[3]; - - if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) - return 0; - - gen9_disable_guc_interrupts(dev_priv); - - ctx = dev_priv->kernel_context; - - data[0] = INTEL_GUC_ACTION_ENTER_S_STATE; - /* any value greater than GUC_POWER_D0 */ - data[1] = GUC_POWER_D1; - /* first page is shared data with GuC */ - data[2] = guc_ggtt_offset(ctx->engine[RCS].state); - - return intel_guc_send(guc, data, ARRAY_SIZE(data)); -} - -/** - * intel_guc_resume() - notify GuC resuming from suspend state - * @dev_priv: i915 device private - */ -int intel_guc_resume(struct drm_i915_private *dev_priv) -{ - struct intel_guc *guc = &dev_priv->guc; - struct i915_gem_context *ctx; - u32 data[3]; - - if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) - return 0; - - if (i915.guc_log_level >= 0) - gen9_enable_guc_interrupts(dev_priv); - - ctx = dev_priv->kernel_context; - - data[0] = INTEL_GUC_ACTION_EXIT_S_STATE; - data[1] = GUC_POWER_D0; - /* first page is shared data with GuC */ - data[2] = guc_ggtt_offset(ctx->engine[RCS].state); - - return intel_guc_send(guc, data, ARRAY_SIZE(data)); -} diff --git a/drivers/gpu/drm/i915/i915_guc_submission.h b/drivers/gpu/drm/i915/i915_guc_submission.h new file mode 100644 index 000000000000..cb4353b59059 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_guc_submission.h @@ -0,0 +1,80 @@ +/* + * Copyright © 2014-2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _I915_GUC_SUBMISSION_H_ +#define _I915_GUC_SUBMISSION_H_ + +#include <linux/spinlock.h> + +#include "i915_gem.h" + +struct drm_i915_private; + +/* + * This structure primarily describes the GEM object shared with the GuC. + * The specs sometimes refer to this object as a "GuC context", but we use + * the term "client" to avoid confusion with hardware contexts. This + * GEM object is held for the entire lifetime of our interaction with + * the GuC, being allocated before the GuC is loaded with its firmware. + * Because there's no way to update the address used by the GuC after + * initialisation, the shared object must stay pinned into the GGTT as + * long as the GuC is in use. We also keep the first page (only) mapped + * into kernel address space, as it includes shared data that must be + * updated on every request submission. + * + * The single GEM object described here is actually made up of several + * separate areas, as far as the GuC is concerned. The first page (kept + * kmap'd) includes the "process descriptor" which holds sequence data for + * the doorbell, and one cacheline which actually *is* the doorbell; a + * write to this will "ring the doorbell" (i.e. send an interrupt to the + * GuC). The subsequent pages of the client object constitute the work + * queue (a circular array of work items), again described in the process + * descriptor. Work queue pages are mapped momentarily as required. + */ +struct i915_guc_client { + struct i915_vma *vma; + void *vaddr; + struct i915_gem_context *owner; + struct intel_guc *guc; + + /* bitmap of (host) engine ids */ + u32 engines; + u32 priority; + u32 stage_id; + u32 proc_desc_offset; + + u16 doorbell_id; + unsigned long doorbell_offset; + + spinlock_t wq_lock; + /* Per-engine counts of GuC submissions */ + u64 submissions[I915_NUM_ENGINES]; +}; + +int i915_guc_submission_init(struct drm_i915_private *dev_priv); +int i915_guc_submission_enable(struct drm_i915_private *dev_priv); +void i915_guc_submission_disable(struct drm_i915_private *dev_priv); +void i915_guc_submission_fini(struct drm_i915_private *dev_priv); + +#endif diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2fe92d2e0f62..f8205841868b 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -126,7 +126,7 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { POSTING_READ(GEN8_##type##_IIR(which)); \ } while (0) -#define GEN5_IRQ_RESET(type) do { \ +#define GEN3_IRQ_RESET(type) do { \ I915_WRITE(type##IMR, 0xffffffff); \ POSTING_READ(type##IMR); \ I915_WRITE(type##IER, 0); \ @@ -136,10 +136,20 @@ static const u32 hpd_bxt[HPD_NUM_PINS] = { POSTING_READ(type##IIR); \ } while (0) +#define GEN2_IRQ_RESET(type) do { \ + I915_WRITE16(type##IMR, 0xffff); \ + POSTING_READ16(type##IMR); \ + I915_WRITE16(type##IER, 0); \ + I915_WRITE16(type##IIR, 0xffff); \ + POSTING_READ16(type##IIR); \ + I915_WRITE16(type##IIR, 0xffff); \ + POSTING_READ16(type##IIR); \ +} while (0) + /* * We should clear IMR at preinstall/uninstall, and just check at postinstall. */ -static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, +static void gen3_assert_iir_is_zero(struct drm_i915_private *dev_priv, i915_reg_t reg) { u32 val = I915_READ(reg); @@ -155,20 +165,43 @@ static void gen5_assert_iir_is_zero(struct drm_i915_private *dev_priv, POSTING_READ(reg); } +static void gen2_assert_iir_is_zero(struct drm_i915_private *dev_priv, + i915_reg_t reg) +{ + u16 val = I915_READ16(reg); + + if (val == 0) + return; + + WARN(1, "Interrupt register 0x%x is not zero: 0x%08x\n", + i915_mmio_reg_offset(reg), val); + I915_WRITE16(reg, 0xffff); + POSTING_READ16(reg); + I915_WRITE16(reg, 0xffff); + POSTING_READ16(reg); +} + #define GEN8_IRQ_INIT_NDX(type, which, imr_val, ier_val) do { \ - gen5_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \ + gen3_assert_iir_is_zero(dev_priv, GEN8_##type##_IIR(which)); \ I915_WRITE(GEN8_##type##_IER(which), (ier_val)); \ I915_WRITE(GEN8_##type##_IMR(which), (imr_val)); \ POSTING_READ(GEN8_##type##_IMR(which)); \ } while (0) -#define GEN5_IRQ_INIT(type, imr_val, ier_val) do { \ - gen5_assert_iir_is_zero(dev_priv, type##IIR); \ +#define GEN3_IRQ_INIT(type, imr_val, ier_val) do { \ + gen3_assert_iir_is_zero(dev_priv, type##IIR); \ I915_WRITE(type##IER, (ier_val)); \ I915_WRITE(type##IMR, (imr_val)); \ POSTING_READ(type##IMR); \ } while (0) +#define GEN2_IRQ_INIT(type, imr_val, ier_val) do { \ + gen2_assert_iir_is_zero(dev_priv, type##IIR); \ + I915_WRITE16(type##IER, (ier_val)); \ + I915_WRITE16(type##IMR, (imr_val)); \ + POSTING_READ16(type##IMR); \ +} while (0) + static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir); @@ -371,19 +404,21 @@ void gen6_reset_rps_interrupts(struct drm_i915_private *dev_priv) { spin_lock_irq(&dev_priv->irq_lock); gen6_reset_pm_iir(dev_priv, dev_priv->pm_rps_events); - dev_priv->rps.pm_iir = 0; + dev_priv->gt_pm.rps.pm_iir = 0; spin_unlock_irq(&dev_priv->irq_lock); } void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) { - if (READ_ONCE(dev_priv->rps.interrupts_enabled)) + struct intel_rps *rps = &dev_priv->gt_pm.rps; + + if (READ_ONCE(rps->interrupts_enabled)) return; spin_lock_irq(&dev_priv->irq_lock); - WARN_ON_ONCE(dev_priv->rps.pm_iir); + WARN_ON_ONCE(rps->pm_iir); WARN_ON_ONCE(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); - dev_priv->rps.interrupts_enabled = true; + rps->interrupts_enabled = true; gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); spin_unlock_irq(&dev_priv->irq_lock); @@ -391,11 +426,13 @@ void gen6_enable_rps_interrupts(struct drm_i915_private *dev_priv) void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) { - if (!READ_ONCE(dev_priv->rps.interrupts_enabled)) + struct intel_rps *rps = &dev_priv->gt_pm.rps; + + if (!READ_ONCE(rps->interrupts_enabled)) return; spin_lock_irq(&dev_priv->irq_lock); - dev_priv->rps.interrupts_enabled = false; + rps->interrupts_enabled = false; I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0u)); @@ -409,7 +446,7 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv) * we will reset the GPU to minimum frequencies, so the current * state of the worker can be discarded. */ - cancel_work_sync(&dev_priv->rps.work); + cancel_work_sync(&rps->work); gen6_reset_rps_interrupts(dev_priv); } @@ -534,62 +571,16 @@ void ibx_display_interrupt_update(struct drm_i915_private *dev_priv, POSTING_READ(SDEIMR); } -static void -__i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, - u32 enable_mask, u32 status_mask) -{ - i915_reg_t reg = PIPESTAT(pipe); - u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK; - - lockdep_assert_held(&dev_priv->irq_lock); - WARN_ON(!intel_irqs_enabled(dev_priv)); - - if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || - status_mask & ~PIPESTAT_INT_STATUS_MASK, - "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", - pipe_name(pipe), enable_mask, status_mask)) - return; - - if ((pipestat & enable_mask) == enable_mask) - return; - - dev_priv->pipestat_irq_mask[pipe] |= status_mask; - - /* Enable the interrupt, clear any pending status */ - pipestat |= enable_mask | status_mask; - I915_WRITE(reg, pipestat); - POSTING_READ(reg); -} - -static void -__i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, - u32 enable_mask, u32 status_mask) +u32 i915_pipestat_enable_mask(struct drm_i915_private *dev_priv, + enum pipe pipe) { - i915_reg_t reg = PIPESTAT(pipe); - u32 pipestat = I915_READ(reg) & PIPESTAT_INT_ENABLE_MASK; + u32 status_mask = dev_priv->pipestat_irq_mask[pipe]; + u32 enable_mask = status_mask << 16; lockdep_assert_held(&dev_priv->irq_lock); - WARN_ON(!intel_irqs_enabled(dev_priv)); - - if (WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || - status_mask & ~PIPESTAT_INT_STATUS_MASK, - "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", - pipe_name(pipe), enable_mask, status_mask)) - return; - - if ((pipestat & enable_mask) == 0) - return; - - dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; - pipestat &= ~enable_mask; - I915_WRITE(reg, pipestat); - POSTING_READ(reg); -} - -static u32 vlv_get_pipestat_enable_mask(struct drm_device *dev, u32 status_mask) -{ - u32 enable_mask = status_mask << 16; + if (INTEL_GEN(dev_priv) < 5) + goto out; /* * On pipe A we don't support the PSR interrupt yet, @@ -612,35 +603,59 @@ static u32 vlv_get_pipestat_enable_mask(struct drm_device *dev, u32 status_mask) if (status_mask & SPRITE1_FLIP_DONE_INT_STATUS_VLV) enable_mask |= SPRITE1_FLIP_DONE_INT_EN_VLV; +out: + WARN_ONCE(enable_mask & ~PIPESTAT_INT_ENABLE_MASK || + status_mask & ~PIPESTAT_INT_STATUS_MASK, + "pipe %c: enable_mask=0x%x, status_mask=0x%x\n", + pipe_name(pipe), enable_mask, status_mask); + return enable_mask; } -void -i915_enable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, - u32 status_mask) +void i915_enable_pipestat(struct drm_i915_private *dev_priv, + enum pipe pipe, u32 status_mask) { + i915_reg_t reg = PIPESTAT(pipe); u32 enable_mask; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - enable_mask = vlv_get_pipestat_enable_mask(&dev_priv->drm, - status_mask); - else - enable_mask = status_mask << 16; - __i915_enable_pipestat(dev_priv, pipe, enable_mask, status_mask); + WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, + "pipe %c: status_mask=0x%x\n", + pipe_name(pipe), status_mask); + + lockdep_assert_held(&dev_priv->irq_lock); + WARN_ON(!intel_irqs_enabled(dev_priv)); + + if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == status_mask) + return; + + dev_priv->pipestat_irq_mask[pipe] |= status_mask; + enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + + I915_WRITE(reg, enable_mask | status_mask); + POSTING_READ(reg); } -void -i915_disable_pipestat(struct drm_i915_private *dev_priv, enum pipe pipe, - u32 status_mask) +void i915_disable_pipestat(struct drm_i915_private *dev_priv, + enum pipe pipe, u32 status_mask) { + i915_reg_t reg = PIPESTAT(pipe); u32 enable_mask; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - enable_mask = vlv_get_pipestat_enable_mask(&dev_priv->drm, - status_mask); - else - enable_mask = status_mask << 16; - __i915_disable_pipestat(dev_priv, pipe, enable_mask, status_mask); + WARN_ONCE(status_mask & ~PIPESTAT_INT_STATUS_MASK, + "pipe %c: status_mask=0x%x\n", + pipe_name(pipe), status_mask); + + lockdep_assert_held(&dev_priv->irq_lock); + WARN_ON(!intel_irqs_enabled(dev_priv)); + + if ((dev_priv->pipestat_irq_mask[pipe] & status_mask) == 0) + return; + + dev_priv->pipestat_irq_mask[pipe] &= ~status_mask; + enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + + I915_WRITE(reg, enable_mask | status_mask); + POSTING_READ(reg); } /** @@ -772,6 +787,57 @@ static u32 g4x_get_vblank_counter(struct drm_device *dev, unsigned int pipe) return I915_READ(PIPE_FRMCOUNT_G4X(pipe)); } +/* + * On certain encoders on certain platforms, pipe + * scanline register will not work to get the scanline, + * since the timings are driven from the PORT or issues + * with scanline register updates. + * This function will use Framestamp and current + * timestamp registers to calculate the scanline. + */ +static u32 __intel_get_crtc_scanline_from_timestamp(struct intel_crtc *crtc) +{ + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + struct drm_vblank_crtc *vblank = + &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; + const struct drm_display_mode *mode = &vblank->hwmode; + u32 vblank_start = mode->crtc_vblank_start; + u32 vtotal = mode->crtc_vtotal; + u32 htotal = mode->crtc_htotal; + u32 clock = mode->crtc_clock; + u32 scanline, scan_prev_time, scan_curr_time, scan_post_time; + + /* + * To avoid the race condition where we might cross into the + * next vblank just between the PIPE_FRMTMSTMP and TIMESTAMP_CTR + * reads. We make sure we read PIPE_FRMTMSTMP and TIMESTAMP_CTR + * during the same frame. + */ + do { + /* + * This field provides read back of the display + * pipe frame time stamp. The time stamp value + * is sampled at every start of vertical blank. + */ + scan_prev_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); + + /* + * The TIMESTAMP_CTR register has the current + * time stamp value. + */ + scan_curr_time = I915_READ_FW(IVB_TIMESTAMP_CTR); + + scan_post_time = I915_READ_FW(PIPE_FRMTMSTMP(crtc->pipe)); + } while (scan_post_time != scan_prev_time); + + scanline = div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, + clock), 1000 * htotal); + scanline = min(scanline, vtotal - 1); + scanline = (scanline + vblank_start) % vtotal; + + return scanline; +} + /* I915_READ_FW, only for fast reads of display block, no need for forcewake etc. */ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) { @@ -788,6 +854,9 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc) vblank = &crtc->base.dev->vblank[drm_crtc_index(&crtc->base)]; mode = &vblank->hwmode; + if (mode->private_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) + return __intel_get_crtc_scanline_from_timestamp(crtc); + vtotal = mode->crtc_vtotal; if (mode->flags & DRM_MODE_FLAG_INTERLACE) vtotal /= 2; @@ -1005,6 +1074,8 @@ static void notify_ring(struct intel_engine_cs *engine) spin_lock(&engine->breadcrumbs.irq_lock); wait = engine->breadcrumbs.irq_wait; if (wait) { + bool wakeup = engine->irq_seqno_barrier; + /* We use a callback from the dma-fence to submit * requests after waiting on our own requests. To * ensure minimum delay in queuing the next request to @@ -1017,12 +1088,18 @@ static void notify_ring(struct intel_engine_cs *engine) * and many waiters. */ if (i915_seqno_passed(intel_engine_get_seqno(engine), - wait->seqno) && - !test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, - &wait->request->fence.flags)) - rq = i915_gem_request_get(wait->request); + wait->seqno)) { + struct drm_i915_gem_request *waiter = wait->request; + + wakeup = true; + if (!test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, + &waiter->fence.flags) && + intel_wait_check_request(wait, waiter)) + rq = i915_gem_request_get(waiter); + } - wake_up_process(wait->tsk); + if (wakeup) + wake_up_process(wait->tsk); } else { __intel_engine_disarm_breadcrumbs(engine); } @@ -1046,12 +1123,13 @@ static void vlv_c0_read(struct drm_i915_private *dev_priv, void gen6_rps_reset_ei(struct drm_i915_private *dev_priv) { - memset(&dev_priv->rps.ei, 0, sizeof(dev_priv->rps.ei)); + memset(&dev_priv->gt_pm.rps.ei, 0, sizeof(dev_priv->gt_pm.rps.ei)); } static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) { - const struct intel_rps_ei *prev = &dev_priv->rps.ei; + struct intel_rps *rps = &dev_priv->gt_pm.rps; + const struct intel_rps_ei *prev = &rps->ei; struct intel_rps_ei now; u32 events = 0; @@ -1078,28 +1156,29 @@ static u32 vlv_wa_c0_ei(struct drm_i915_private *dev_priv, u32 pm_iir) c0 = max(render, media); c0 *= 1000 * 100 << 8; /* to usecs and scale to threshold% */ - if (c0 > time * dev_priv->rps.up_threshold) + if (c0 > time * rps->up_threshold) events = GEN6_PM_RP_UP_THRESHOLD; - else if (c0 < time * dev_priv->rps.down_threshold) + else if (c0 < time * rps->down_threshold) events = GEN6_PM_RP_DOWN_THRESHOLD; } - dev_priv->rps.ei = now; + rps->ei = now; return events; } static void gen6_pm_rps_work(struct work_struct *work) { struct drm_i915_private *dev_priv = - container_of(work, struct drm_i915_private, rps.work); + container_of(work, struct drm_i915_private, gt_pm.rps.work); + struct intel_rps *rps = &dev_priv->gt_pm.rps; bool client_boost = false; int new_delay, adj, min, max; u32 pm_iir = 0; spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->rps.interrupts_enabled) { - pm_iir = fetch_and_zero(&dev_priv->rps.pm_iir); - client_boost = atomic_read(&dev_priv->rps.num_waiters); + if (rps->interrupts_enabled) { + pm_iir = fetch_and_zero(&rps->pm_iir); + client_boost = atomic_read(&rps->num_waiters); } spin_unlock_irq(&dev_priv->irq_lock); @@ -1108,18 +1187,18 @@ static void gen6_pm_rps_work(struct work_struct *work) if ((pm_iir & dev_priv->pm_rps_events) == 0 && !client_boost) goto out; - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); pm_iir |= vlv_wa_c0_ei(dev_priv, pm_iir); - adj = dev_priv->rps.last_adj; - new_delay = dev_priv->rps.cur_freq; - min = dev_priv->rps.min_freq_softlimit; - max = dev_priv->rps.max_freq_softlimit; + adj = rps->last_adj; + new_delay = rps->cur_freq; + min = rps->min_freq_softlimit; + max = rps->max_freq_softlimit; if (client_boost) - max = dev_priv->rps.max_freq; - if (client_boost && new_delay < dev_priv->rps.boost_freq) { - new_delay = dev_priv->rps.boost_freq; + max = rps->max_freq; + if (client_boost && new_delay < rps->boost_freq) { + new_delay = rps->boost_freq; adj = 0; } else if (pm_iir & GEN6_PM_RP_UP_THRESHOLD) { if (adj > 0) @@ -1127,15 +1206,15 @@ static void gen6_pm_rps_work(struct work_struct *work) else /* CHV needs even encode values */ adj = IS_CHERRYVIEW(dev_priv) ? 2 : 1; - if (new_delay >= dev_priv->rps.max_freq_softlimit) + if (new_delay >= rps->max_freq_softlimit) adj = 0; } else if (client_boost) { adj = 0; } else if (pm_iir & GEN6_PM_RP_DOWN_TIMEOUT) { - if (dev_priv->rps.cur_freq > dev_priv->rps.efficient_freq) - new_delay = dev_priv->rps.efficient_freq; - else if (dev_priv->rps.cur_freq > dev_priv->rps.min_freq_softlimit) - new_delay = dev_priv->rps.min_freq_softlimit; + if (rps->cur_freq > rps->efficient_freq) + new_delay = rps->efficient_freq; + else if (rps->cur_freq > rps->min_freq_softlimit) + new_delay = rps->min_freq_softlimit; adj = 0; } else if (pm_iir & GEN6_PM_RP_DOWN_THRESHOLD) { if (adj < 0) @@ -1143,13 +1222,13 @@ static void gen6_pm_rps_work(struct work_struct *work) else /* CHV needs even encode values */ adj = IS_CHERRYVIEW(dev_priv) ? -2 : -1; - if (new_delay <= dev_priv->rps.min_freq_softlimit) + if (new_delay <= rps->min_freq_softlimit) adj = 0; } else { /* unknown event */ adj = 0; } - dev_priv->rps.last_adj = adj; + rps->last_adj = adj; /* sysfs frequency interfaces may have snuck in while servicing the * interrupt @@ -1159,15 +1238,15 @@ static void gen6_pm_rps_work(struct work_struct *work) if (intel_set_rps(dev_priv, new_delay)) { DRM_DEBUG_DRIVER("Failed to set new GPU frequency\n"); - dev_priv->rps.last_adj = 0; + rps->last_adj = 0; } - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); out: /* Make sure not to corrupt PMIMR state used by ringbuffer on GEN6 */ spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->rps.interrupts_enabled) + if (rps->interrupts_enabled) gen6_unmask_pm_irq(dev_priv, dev_priv->pm_rps_events); spin_unlock_irq(&dev_priv->irq_lock); } @@ -1305,10 +1384,11 @@ static void snb_gt_irq_handler(struct drm_i915_private *dev_priv, static void gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) { + struct intel_engine_execlists * const execlists = &engine->execlists; bool tasklet = false; if (iir & (GT_CONTEXT_SWITCH_INTERRUPT << test_shift)) { - if (port_count(&engine->execlist_port[0])) { + if (READ_ONCE(engine->execlists.active)) { __set_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); tasklet = true; } @@ -1316,11 +1396,11 @@ gen8_cs_irq_handler(struct intel_engine_cs *engine, u32 iir, int test_shift) if (iir & (GT_RENDER_USER_INTERRUPT << test_shift)) { notify_ring(engine); - tasklet |= i915.enable_guc_submission; + tasklet |= i915_modparams.enable_guc_submission; } if (tasklet) - tasklet_hi_schedule(&engine->irq_tasklet); + tasklet_hi_schedule(&execlists->irq_tasklet); } static irqreturn_t gen8_gt_irq_ack(struct drm_i915_private *dev_priv, @@ -1573,11 +1653,11 @@ static void display_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, * bonkers. So let's just wait for the next vblank and read * out the buggy result. * - * On CHV sometimes the second CRC is bonkers as well, so + * On GEN8+ sometimes the second CRC is bonkers as well, so * don't trust that one either. */ if (pipe_crc->skipped == 0 || - (IS_CHERRYVIEW(dev_priv) && pipe_crc->skipped == 1)) { + (INTEL_GEN(dev_priv) >= 8 && pipe_crc->skipped == 1)) { pipe_crc->skipped++; spin_unlock(&pipe_crc->lock); return; @@ -1649,12 +1729,14 @@ static void i9xx_pipe_crc_irq_handler(struct drm_i915_private *dev_priv, * the work queue. */ static void gen6_rps_irq_handler(struct drm_i915_private *dev_priv, u32 pm_iir) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + if (pm_iir & dev_priv->pm_rps_events) { spin_lock(&dev_priv->irq_lock); gen6_mask_pm_irq(dev_priv, pm_iir & dev_priv->pm_rps_events); - if (dev_priv->rps.interrupts_enabled) { - dev_priv->rps.pm_iir |= pm_iir & dev_priv->pm_rps_events; - schedule_work(&dev_priv->rps.work); + if (rps->interrupts_enabled) { + rps->pm_iir |= pm_iir & dev_priv->pm_rps_events; + schedule_work(&rps->work); } spin_unlock(&dev_priv->irq_lock); } @@ -1706,8 +1788,21 @@ static void gen9_guc_irq_handler(struct drm_i915_private *dev_priv, u32 gt_iir) } } -static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv, - u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +static void i9xx_pipestat_irq_reset(struct drm_i915_private *dev_priv) +{ + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + I915_WRITE(PIPESTAT(pipe), + PIPESTAT_INT_STATUS_MASK | + PIPE_FIFO_UNDERRUN_STATUS); + + dev_priv->pipestat_irq_mask[pipe] = 0; + } +} + +static void i9xx_pipestat_irq_ack(struct drm_i915_private *dev_priv, + u32 iir, u32 pipe_stats[I915_MAX_PIPES]) { int pipe; @@ -1720,7 +1815,7 @@ static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv, for_each_pipe(dev_priv, pipe) { i915_reg_t reg; - u32 mask, iir_bit = 0; + u32 status_mask, enable_mask, iir_bit = 0; /* * PIPESTAT bits get signalled even when the interrupt is @@ -1731,7 +1826,7 @@ static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv, */ /* fifo underruns are filterered in the underrun handler. */ - mask = PIPE_FIFO_UNDERRUN_STATUS; + status_mask = PIPE_FIFO_UNDERRUN_STATUS; switch (pipe) { case PIPE_A: @@ -1745,25 +1840,92 @@ static void valleyview_pipestat_irq_ack(struct drm_i915_private *dev_priv, break; } if (iir & iir_bit) - mask |= dev_priv->pipestat_irq_mask[pipe]; + status_mask |= dev_priv->pipestat_irq_mask[pipe]; - if (!mask) + if (!status_mask) continue; reg = PIPESTAT(pipe); - mask |= PIPESTAT_INT_ENABLE_MASK; - pipe_stats[pipe] = I915_READ(reg) & mask; + pipe_stats[pipe] = I915_READ(reg) & status_mask; + enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); /* * Clear the PIPE*STAT regs before the IIR */ - if (pipe_stats[pipe] & (PIPE_FIFO_UNDERRUN_STATUS | - PIPESTAT_INT_STATUS_MASK)) - I915_WRITE(reg, pipe_stats[pipe]); + if (pipe_stats[pipe]) + I915_WRITE(reg, enable_mask | pipe_stats[pipe]); } spin_unlock(&dev_priv->irq_lock); } +static void i8xx_pipestat_irq_handler(struct drm_i915_private *dev_priv, + u16 iir, u32 pipe_stats[I915_MAX_PIPES]) +{ + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) + drm_handle_vblank(&dev_priv->drm, pipe); + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_irq_handler(dev_priv, pipe); + + if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) + intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + } +} + +static void i915_pipestat_irq_handler(struct drm_i915_private *dev_priv, + u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +{ + bool blc_event = false; + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) + drm_handle_vblank(&dev_priv->drm, pipe); + + if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) + blc_event = true; + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_irq_handler(dev_priv, pipe); + + if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) + intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + } + + if (blc_event || (iir & I915_ASLE_INTERRUPT)) + intel_opregion_asle_intr(dev_priv); +} + +static void i965_pipestat_irq_handler(struct drm_i915_private *dev_priv, + u32 iir, u32 pipe_stats[I915_MAX_PIPES]) +{ + bool blc_event = false; + enum pipe pipe; + + for_each_pipe(dev_priv, pipe) { + if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) + drm_handle_vblank(&dev_priv->drm, pipe); + + if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) + blc_event = true; + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_irq_handler(dev_priv, pipe); + + if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) + intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); + } + + if (blc_event || (iir & I915_ASLE_INTERRUPT)) + intel_opregion_asle_intr(dev_priv); + + if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) + gmbus_irq_handler(dev_priv); +} + static void valleyview_pipestat_irq_handler(struct drm_i915_private *dev_priv, u32 pipe_stats[I915_MAX_PIPES]) { @@ -1879,7 +2041,7 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) /* Call regardless, as some status bits might not be * signalled in iir */ - valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats); + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); if (iir & (I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT)) @@ -1963,7 +2125,7 @@ static irqreturn_t cherryview_irq_handler(int irq, void *arg) /* Call regardless, as some status bits might not be * signalled in iir */ - valleyview_pipestat_irq_ack(dev_priv, iir, pipe_stats); + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); if (iir & (I915_LPE_PIPE_A_INTERRUPT | I915_LPE_PIPE_B_INTERRUPT | @@ -2100,18 +2262,14 @@ static void ivb_err_int_handler(struct drm_i915_private *dev_priv) static void cpt_serr_int_handler(struct drm_i915_private *dev_priv) { u32 serr_int = I915_READ(SERR_INT); + enum pipe pipe; if (serr_int & SERR_INT_POISON) DRM_ERROR("PCH poison interrupt\n"); - if (serr_int & SERR_INT_TRANS_A_FIFO_UNDERRUN) - intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_A); - - if (serr_int & SERR_INT_TRANS_B_FIFO_UNDERRUN) - intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_B); - - if (serr_int & SERR_INT_TRANS_C_FIFO_UNDERRUN) - intel_pch_fifo_underrun_irq_handler(dev_priv, PIPE_C); + for_each_pipe(dev_priv, pipe) + if (serr_int & SERR_INT_TRANS_FIFO_UNDERRUN(pipe)) + intel_pch_fifo_underrun_irq_handler(dev_priv, pipe); I915_WRITE(SERR_INT, serr_int); } @@ -2860,7 +3018,7 @@ static void ibx_irq_reset(struct drm_i915_private *dev_priv) if (HAS_PCH_NOP(dev_priv)) return; - GEN5_IRQ_RESET(SDE); + GEN3_IRQ_RESET(SDE); if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) I915_WRITE(SERR_INT, 0xffffffff); @@ -2888,15 +3046,13 @@ static void ibx_irq_pre_postinstall(struct drm_device *dev) static void gen5_gt_irq_reset(struct drm_i915_private *dev_priv) { - GEN5_IRQ_RESET(GT); + GEN3_IRQ_RESET(GT); if (INTEL_GEN(dev_priv) >= 6) - GEN5_IRQ_RESET(GEN6_PM); + GEN3_IRQ_RESET(GEN6_PM); } static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) { - enum pipe pipe; - if (IS_CHERRYVIEW(dev_priv)) I915_WRITE(DPINVGTT, DPINVGTT_STATUS_MASK_CHV); else @@ -2905,14 +3061,9 @@ static void vlv_display_irq_reset(struct drm_i915_private *dev_priv) i915_hotplug_interrupt_update_locked(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - for_each_pipe(dev_priv, pipe) { - I915_WRITE(PIPESTAT(pipe), - PIPE_FIFO_UNDERRUN_STATUS | - PIPESTAT_INT_STATUS_MASK); - dev_priv->pipestat_irq_mask[pipe] = 0; - } + i9xx_pipestat_irq_reset(dev_priv); - GEN5_IRQ_RESET(VLV_); + GEN3_IRQ_RESET(VLV_); dev_priv->irq_mask = ~0; } @@ -2922,8 +3073,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) u32 enable_mask; enum pipe pipe; - pipestat_mask = PLANE_FLIP_DONE_INT_STATUS_VLV | - PIPE_CRC_DONE_INTERRUPT_STATUS; + pipestat_mask = PIPE_CRC_DONE_INTERRUPT_STATUS; i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); for_each_pipe(dev_priv, pipe) @@ -2943,7 +3093,7 @@ static void vlv_display_irq_postinstall(struct drm_i915_private *dev_priv) dev_priv->irq_mask = ~enable_mask; - GEN5_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); + GEN3_IRQ_INIT(VLV_, dev_priv->irq_mask, enable_mask); } /* drm_dma.h hooks @@ -2952,9 +3102,10 @@ static void ironlake_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - I915_WRITE(HWSTAM, 0xffffffff); + if (IS_GEN5(dev_priv)) + I915_WRITE(HWSTAM, 0xffffffff); - GEN5_IRQ_RESET(DE); + GEN3_IRQ_RESET(DE); if (IS_GEN7(dev_priv)) I915_WRITE(GEN7_ERR_INT, 0xffffffff); @@ -2963,7 +3114,7 @@ static void ironlake_irq_reset(struct drm_device *dev) ibx_irq_reset(dev_priv); } -static void valleyview_irq_preinstall(struct drm_device *dev) +static void valleyview_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -3001,9 +3152,9 @@ static void gen8_irq_reset(struct drm_device *dev) POWER_DOMAIN_PIPE(pipe))) GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); - GEN5_IRQ_RESET(GEN8_DE_PORT_); - GEN5_IRQ_RESET(GEN8_DE_MISC_); - GEN5_IRQ_RESET(GEN8_PCU_); + GEN3_IRQ_RESET(GEN8_DE_PORT_); + GEN3_IRQ_RESET(GEN8_DE_MISC_); + GEN3_IRQ_RESET(GEN8_PCU_); if (HAS_PCH_SPLIT(dev_priv)) ibx_irq_reset(dev_priv); @@ -3016,10 +3167,17 @@ void gen8_irq_power_well_post_enable(struct drm_i915_private *dev_priv, enum pipe pipe; spin_lock_irq(&dev_priv->irq_lock); + + if (!intel_irqs_enabled(dev_priv)) { + spin_unlock_irq(&dev_priv->irq_lock); + return; + } + for_each_pipe_masked(dev_priv, pipe, pipe_mask) GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, dev_priv->de_irq_mask[pipe], ~dev_priv->de_irq_mask[pipe] | extra_ier); + spin_unlock_irq(&dev_priv->irq_lock); } @@ -3029,15 +3187,22 @@ void gen8_irq_power_well_pre_disable(struct drm_i915_private *dev_priv, enum pipe pipe; spin_lock_irq(&dev_priv->irq_lock); + + if (!intel_irqs_enabled(dev_priv)) { + spin_unlock_irq(&dev_priv->irq_lock); + return; + } + for_each_pipe_masked(dev_priv, pipe, pipe_mask) GEN8_IRQ_RESET_NDX(DE_PIPE, pipe); + spin_unlock_irq(&dev_priv->irq_lock); /* make sure we're done processing display irqs */ synchronize_irq(dev_priv->drm.irq); } -static void cherryview_irq_preinstall(struct drm_device *dev) +static void cherryview_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); @@ -3046,7 +3211,7 @@ static void cherryview_irq_preinstall(struct drm_device *dev) gen8_gt_irq_reset(dev_priv); - GEN5_IRQ_RESET(GEN8_PCU_); + GEN3_IRQ_RESET(GEN8_PCU_); spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->display_irqs_enabled) @@ -3111,7 +3276,15 @@ static void ibx_hpd_irq_setup(struct drm_i915_private *dev_priv) static void spt_hpd_detection_setup(struct drm_i915_private *dev_priv) { - u32 hotplug; + u32 val, hotplug; + + /* Display WA #1179 WaHardHangonHotPlug: cnp */ + if (HAS_PCH_CNP(dev_priv)) { + val = I915_READ(SOUTH_CHICKEN1); + val &= ~CHASSIS_CLK_REQ_DURATION_MASK; + val |= CHASSIS_CLK_REQ_DURATION(0xf); + I915_WRITE(SOUTH_CHICKEN1, val); + } /* Enable digital hotplug on the PCH */ hotplug = I915_READ(PCH_PORT_HOTPLUG); @@ -3238,10 +3411,12 @@ static void ibx_irq_postinstall(struct drm_device *dev) if (HAS_PCH_IBX(dev_priv)) mask = SDE_GMBUS | SDE_AUX_MASK | SDE_POISON; - else + else if (HAS_PCH_CPT(dev_priv) || HAS_PCH_LPT(dev_priv)) mask = SDE_GMBUS_CPT | SDE_AUX_MASK_CPT; + else + mask = SDE_GMBUS_CPT; - gen5_assert_iir_is_zero(dev_priv, SDEIIR); + gen3_assert_iir_is_zero(dev_priv, SDEIIR); I915_WRITE(SDEIMR, ~mask); if (HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || @@ -3272,7 +3447,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) gt_irqs |= GT_BLT_USER_INTERRUPT | GT_BSD_USER_INTERRUPT; } - GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); + GEN3_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); if (INTEL_GEN(dev_priv) >= 6) { /* @@ -3285,7 +3460,7 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) } dev_priv->pm_imr = 0xffffffff; - GEN5_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs); + GEN3_IRQ_INIT(GEN6_PM, dev_priv->pm_imr, pm_irqs); } } @@ -3296,18 +3471,14 @@ static int ironlake_irq_postinstall(struct drm_device *dev) if (INTEL_GEN(dev_priv) >= 7) { display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE_IVB | - DE_PCH_EVENT_IVB | DE_PLANEC_FLIP_DONE_IVB | - DE_PLANEB_FLIP_DONE_IVB | - DE_PLANEA_FLIP_DONE_IVB | DE_AUX_CHANNEL_A_IVB); + DE_PCH_EVENT_IVB | DE_AUX_CHANNEL_A_IVB); extra_mask = (DE_PIPEC_VBLANK_IVB | DE_PIPEB_VBLANK_IVB | DE_PIPEA_VBLANK_IVB | DE_ERR_INT_IVB | DE_DP_A_HOTPLUG_IVB); } else { display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | - DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE | - DE_AUX_CHANNEL_A | - DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE | - DE_POISON); + DE_AUX_CHANNEL_A | DE_PIPEB_CRC_DONE | + DE_PIPEA_CRC_DONE | DE_POISON); extra_mask = (DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT | DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | DE_DP_A_HOTPLUG); @@ -3315,11 +3486,9 @@ static int ironlake_irq_postinstall(struct drm_device *dev) dev_priv->irq_mask = ~display_mask; - I915_WRITE(HWSTAM, 0xeffe); - ibx_irq_pre_postinstall(dev); - GEN5_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask); + GEN3_IRQ_INIT(DE, dev_priv->irq_mask, display_mask | extra_mask); gen5_gt_irq_postinstall(dev); @@ -3429,15 +3598,13 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) enum pipe pipe; if (INTEL_GEN(dev_priv) >= 9) { - de_pipe_masked |= GEN9_PIPE_PLANE1_FLIP_DONE | - GEN9_DE_PIPE_IRQ_FAULT_ERRORS; + de_pipe_masked |= GEN9_DE_PIPE_IRQ_FAULT_ERRORS; de_port_masked |= GEN9_AUX_CHANNEL_B | GEN9_AUX_CHANNEL_C | GEN9_AUX_CHANNEL_D; if (IS_GEN9_LP(dev_priv)) de_port_masked |= BXT_DE_PORT_GMBUS; } else { - de_pipe_masked |= GEN8_PIPE_PRIMARY_FLIP_DONE | - GEN8_DE_PIPE_IRQ_FAULT_ERRORS; + de_pipe_masked |= GEN8_DE_PIPE_IRQ_FAULT_ERRORS; } de_pipe_enables = de_pipe_masked | GEN8_PIPE_VBLANK | @@ -3449,19 +3616,18 @@ static void gen8_de_irq_postinstall(struct drm_i915_private *dev_priv) else if (IS_BROADWELL(dev_priv)) de_port_enables |= GEN8_PORT_DP_A_HOTPLUG; - dev_priv->de_irq_mask[PIPE_A] = ~de_pipe_masked; - dev_priv->de_irq_mask[PIPE_B] = ~de_pipe_masked; - dev_priv->de_irq_mask[PIPE_C] = ~de_pipe_masked; + for_each_pipe(dev_priv, pipe) { + dev_priv->de_irq_mask[pipe] = ~de_pipe_masked; - for_each_pipe(dev_priv, pipe) if (intel_display_power_is_enabled(dev_priv, POWER_DOMAIN_PIPE(pipe))) GEN8_IRQ_INIT_NDX(DE_PIPE, pipe, dev_priv->de_irq_mask[pipe], de_pipe_enables); + } - GEN5_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables); - GEN5_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); + GEN3_IRQ_INIT(GEN8_DE_PORT_, ~de_port_masked, de_port_enables); + GEN3_IRQ_INIT(GEN8_DE_MISC_, ~de_misc_masked, de_misc_masked); if (IS_GEN9_LP(dev_priv)) bxt_hpd_detection_setup(dev_priv); @@ -3505,98 +3671,36 @@ static int cherryview_irq_postinstall(struct drm_device *dev) return 0; } -static void gen8_irq_uninstall(struct drm_device *dev) +static void i8xx_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - if (!dev_priv) - return; - - gen8_irq_reset(dev); -} - -static void valleyview_irq_uninstall(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - if (!dev_priv) - return; - - I915_WRITE(VLV_MASTER_IER, 0); - POSTING_READ(VLV_MASTER_IER); - - gen5_gt_irq_reset(dev_priv); - - I915_WRITE(HWSTAM, 0xffffffff); - - spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) - vlv_display_irq_reset(dev_priv); - spin_unlock_irq(&dev_priv->irq_lock); -} - -static void cherryview_irq_uninstall(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - if (!dev_priv) - return; - - I915_WRITE(GEN8_MASTER_IRQ, 0); - POSTING_READ(GEN8_MASTER_IRQ); + i9xx_pipestat_irq_reset(dev_priv); - gen8_gt_irq_reset(dev_priv); - - GEN5_IRQ_RESET(GEN8_PCU_); - - spin_lock_irq(&dev_priv->irq_lock); - if (dev_priv->display_irqs_enabled) - vlv_display_irq_reset(dev_priv); - spin_unlock_irq(&dev_priv->irq_lock); -} - -static void ironlake_irq_uninstall(struct drm_device *dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - - if (!dev_priv) - return; - - ironlake_irq_reset(dev); -} - -static void i8xx_irq_preinstall(struct drm_device * dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; + I915_WRITE16(HWSTAM, 0xffff); - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), 0); - I915_WRITE16(IMR, 0xffff); - I915_WRITE16(IER, 0x0); - POSTING_READ16(IER); + GEN2_IRQ_RESET(); } static int i8xx_irq_postinstall(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); + u16 enable_mask; - I915_WRITE16(EMR, - ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); + I915_WRITE16(EMR, ~(I915_ERROR_PAGE_TABLE | + I915_ERROR_MEMORY_REFRESH)); /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = ~(I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | - I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT); - I915_WRITE16(IMR, dev_priv->irq_mask); + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); - I915_WRITE16(IER, - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_USER_INTERRUPT); - POSTING_READ16(IER); + enable_mask = + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | + I915_USER_INTERRUPT; + + GEN2_IRQ_INIT(, dev_priv->irq_mask, enable_mask); /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ @@ -3608,17 +3712,11 @@ static int i8xx_irq_postinstall(struct drm_device *dev) return 0; } -/* - * Returns true when a page flip has completed. - */ static irqreturn_t i8xx_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); - u16 iir, new_iir; - u32 pipe_stats[2]; - int pipe; - irqreturn_t ret; + irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -3626,96 +3724,50 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - ret = IRQ_NONE; - iir = I915_READ16(IIR); - if (iir == 0) - goto out; + do { + u32 pipe_stats[I915_MAX_PIPES] = {}; + u16 iir; - while (iir) { - /* Can't rely on pipestat interrupt bit in iir as it might - * have been cleared after the pipestat interrupt was received. - * It doesn't set the bit in iir again, but it still produces - * interrupts (for non-MSI). - */ - spin_lock(&dev_priv->irq_lock); - if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) - DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); + iir = I915_READ16(IIR); + if (iir == 0) + break; - for_each_pipe(dev_priv, pipe) { - i915_reg_t reg = PIPESTAT(pipe); - pipe_stats[pipe] = I915_READ(reg); + ret = IRQ_HANDLED; - /* - * Clear the PIPE*STAT regs before the IIR - */ - if (pipe_stats[pipe] & 0x8000ffff) - I915_WRITE(reg, pipe_stats[pipe]); - } - spin_unlock(&dev_priv->irq_lock); + /* Call regardless, as some status bits might not be + * signalled in iir */ + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); I915_WRITE16(IIR, iir); - new_iir = I915_READ16(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) notify_ring(dev_priv->engine[RCS]); - for_each_pipe(dev_priv, pipe) { - int plane = pipe; - if (HAS_FBC(dev_priv)) - plane = !plane; - - if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) - drm_handle_vblank(&dev_priv->drm, pipe); - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev_priv, pipe); - - if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, - pipe); - } + if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) + DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - iir = new_iir; - } - ret = IRQ_HANDLED; + i8xx_pipestat_irq_handler(dev_priv, iir, pipe_stats); + } while (0); -out: enable_rpm_wakeref_asserts(dev_priv); return ret; } -static void i8xx_irq_uninstall(struct drm_device * dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; - - for_each_pipe(dev_priv, pipe) { - /* Clear enable bits; then clear status bits */ - I915_WRITE(PIPESTAT(pipe), 0); - I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); - } - I915_WRITE16(IMR, 0xffff); - I915_WRITE16(IER, 0x0); - I915_WRITE16(IIR, I915_READ16(IIR)); -} - -static void i915_irq_preinstall(struct drm_device * dev) +static void i915_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; if (I915_HAS_HOTPLUG(dev_priv)) { i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); } - I915_WRITE16(HWSTAM, 0xeffe); - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), 0); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - POSTING_READ(IER); + i9xx_pipestat_irq_reset(dev_priv); + + I915_WRITE(HWSTAM, 0xffffffff); + + GEN3_IRQ_RESET(); } static int i915_irq_postinstall(struct drm_device *dev) @@ -3723,15 +3775,14 @@ static int i915_irq_postinstall(struct drm_device *dev) struct drm_i915_private *dev_priv = to_i915(dev); u32 enable_mask; - I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | I915_ERROR_MEMORY_REFRESH)); + I915_WRITE(EMR, ~(I915_ERROR_PAGE_TABLE | + I915_ERROR_MEMORY_REFRESH)); /* Unmask the interrupts that we always want on. */ dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | - I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT); + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT); enable_mask = I915_ASLE_INTERRUPT | @@ -3740,20 +3791,13 @@ static int i915_irq_postinstall(struct drm_device *dev) I915_USER_INTERRUPT; if (I915_HAS_HOTPLUG(dev_priv)) { - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - POSTING_READ(PORT_HOTPLUG_EN); - /* Enable in IER... */ enable_mask |= I915_DISPLAY_PORT_INTERRUPT; /* and unmask in IMR */ dev_priv->irq_mask &= ~I915_DISPLAY_PORT_INTERRUPT; } - I915_WRITE(IMR, dev_priv->irq_mask); - I915_WRITE(IER, enable_mask); - POSTING_READ(IER); - - i915_enable_asle_pipestat(dev_priv); + GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); /* Interrupt setup is already guaranteed to be single-threaded, this is * just to make the assert_spin_locked check happy. */ @@ -3762,6 +3806,8 @@ static int i915_irq_postinstall(struct drm_device *dev) i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); spin_unlock_irq(&dev_priv->irq_lock); + i915_enable_asle_pipestat(dev_priv); + return 0; } @@ -3769,8 +3815,7 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); - u32 iir, new_iir, pipe_stats[I915_MAX_PIPES]; - int pipe, ret = IRQ_NONE; + irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -3778,131 +3823,56 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - iir = I915_READ(IIR); do { - bool irq_received = (iir) != 0; - bool blc_event = false; - - /* Can't rely on pipestat interrupt bit in iir as it might - * have been cleared after the pipestat interrupt was received. - * It doesn't set the bit in iir again, but it still produces - * interrupts (for non-MSI). - */ - spin_lock(&dev_priv->irq_lock); - if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) - DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - - for_each_pipe(dev_priv, pipe) { - i915_reg_t reg = PIPESTAT(pipe); - pipe_stats[pipe] = I915_READ(reg); - - /* Clear the PIPE*STAT regs before the IIR */ - if (pipe_stats[pipe] & 0x8000ffff) { - I915_WRITE(reg, pipe_stats[pipe]); - irq_received = true; - } - } - spin_unlock(&dev_priv->irq_lock); + u32 pipe_stats[I915_MAX_PIPES] = {}; + u32 hotplug_status = 0; + u32 iir; - if (!irq_received) + iir = I915_READ(IIR); + if (iir == 0) break; - /* Consume port. Then clear IIR or we'll miss events */ + ret = IRQ_HANDLED; + if (I915_HAS_HOTPLUG(dev_priv) && - iir & I915_DISPLAY_PORT_INTERRUPT) { - u32 hotplug_status = i9xx_hpd_irq_ack(dev_priv); - if (hotplug_status) - i9xx_hpd_irq_handler(dev_priv, hotplug_status); - } + iir & I915_DISPLAY_PORT_INTERRUPT) + hotplug_status = i9xx_hpd_irq_ack(dev_priv); + + /* Call regardless, as some status bits might not be + * signalled in iir */ + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); I915_WRITE(IIR, iir); - new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) notify_ring(dev_priv->engine[RCS]); - for_each_pipe(dev_priv, pipe) { - int plane = pipe; - if (HAS_FBC(dev_priv)) - plane = !plane; - - if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS) - drm_handle_vblank(&dev_priv->drm, pipe); - - if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) - blc_event = true; - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev_priv, pipe); - - if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, - pipe); - } + if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) + DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - if (blc_event || (iir & I915_ASLE_INTERRUPT)) - intel_opregion_asle_intr(dev_priv); + if (hotplug_status) + i9xx_hpd_irq_handler(dev_priv, hotplug_status); - /* With MSI, interrupts are only generated when iir - * transitions from zero to nonzero. If another bit got - * set while we were handling the existing iir bits, then - * we would never get another interrupt. - * - * This is fine on non-MSI as well, as if we hit this path - * we avoid exiting the interrupt handler only to generate - * another one. - * - * Note that for MSI this could cause a stray interrupt report - * if an interrupt landed in the time between writing IIR and - * the posting read. This should be rare enough to never - * trigger the 99% of 100,000 interrupts test for disabling - * stray interrupts. - */ - ret = IRQ_HANDLED; - iir = new_iir; - } while (iir); + i915_pipestat_irq_handler(dev_priv, iir, pipe_stats); + } while (0); enable_rpm_wakeref_asserts(dev_priv); return ret; } -static void i915_irq_uninstall(struct drm_device * dev) +static void i965_irq_reset(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; - - if (I915_HAS_HOTPLUG(dev_priv)) { - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - } - - I915_WRITE16(HWSTAM, 0xffff); - for_each_pipe(dev_priv, pipe) { - /* Clear enable bits; then clear status bits */ - I915_WRITE(PIPESTAT(pipe), 0); - I915_WRITE(PIPESTAT(pipe), I915_READ(PIPESTAT(pipe))); - } - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - - I915_WRITE(IIR, I915_READ(IIR)); -} - -static void i965_irq_preinstall(struct drm_device * dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - I915_WRITE(HWSTAM, 0xeffe); - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), 0); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - POSTING_READ(IER); + i9xx_pipestat_irq_reset(dev_priv); + + I915_WRITE(HWSTAM, 0xffffffff); + + GEN3_IRQ_RESET(); } static int i965_irq_postinstall(struct drm_device *dev) @@ -3911,31 +3881,6 @@ static int i965_irq_postinstall(struct drm_device *dev) u32 enable_mask; u32 error_mask; - /* Unmask the interrupts that we always want on. */ - dev_priv->irq_mask = ~(I915_ASLE_INTERRUPT | - I915_DISPLAY_PORT_INTERRUPT | - I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | - I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | - I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | - I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT | - I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); - - enable_mask = ~dev_priv->irq_mask; - enable_mask &= ~(I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT | - I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT); - enable_mask |= I915_USER_INTERRUPT; - - if (IS_G4X(dev_priv)) - enable_mask |= I915_BSD_USER_INTERRUPT; - - /* Interrupt setup is already guaranteed to be single-threaded, this is - * just to make the assert_spin_locked check happy. */ - spin_lock_irq(&dev_priv->irq_lock); - i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); - i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); - i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); - spin_unlock_irq(&dev_priv->irq_lock); - /* * Enable some error detection, note the instruction error mask * bit is reserved, so we leave it masked. @@ -3951,12 +3896,34 @@ static int i965_irq_postinstall(struct drm_device *dev) } I915_WRITE(EMR, error_mask); - I915_WRITE(IMR, dev_priv->irq_mask); - I915_WRITE(IER, enable_mask); - POSTING_READ(IER); + /* Unmask the interrupts that we always want on. */ + dev_priv->irq_mask = + ~(I915_ASLE_INTERRUPT | + I915_DISPLAY_PORT_INTERRUPT | + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | + I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT); - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - POSTING_READ(PORT_HOTPLUG_EN); + enable_mask = + I915_ASLE_INTERRUPT | + I915_DISPLAY_PORT_INTERRUPT | + I915_DISPLAY_PIPE_A_EVENT_INTERRUPT | + I915_DISPLAY_PIPE_B_EVENT_INTERRUPT | + I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT | + I915_USER_INTERRUPT; + + if (IS_G4X(dev_priv)) + enable_mask |= I915_BSD_USER_INTERRUPT; + + GEN3_IRQ_INIT(, dev_priv->irq_mask, enable_mask); + + /* Interrupt setup is already guaranteed to be single-threaded, this is + * just to make the assert_spin_locked check happy. */ + spin_lock_irq(&dev_priv->irq_lock); + i915_enable_pipestat(dev_priv, PIPE_A, PIPE_GMBUS_INTERRUPT_STATUS); + i915_enable_pipestat(dev_priv, PIPE_A, PIPE_CRC_DONE_INTERRUPT_STATUS); + i915_enable_pipestat(dev_priv, PIPE_B, PIPE_CRC_DONE_INTERRUPT_STATUS); + spin_unlock_irq(&dev_priv->irq_lock); i915_enable_asle_pipestat(dev_priv); @@ -3992,9 +3959,7 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_i915_private *dev_priv = to_i915(dev); - u32 iir, new_iir; - u32 pipe_stats[I915_MAX_PIPES]; - int ret = IRQ_NONE, pipe; + irqreturn_t ret = IRQ_NONE; if (!intel_irqs_enabled(dev_priv)) return IRQ_NONE; @@ -4002,121 +3967,46 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) /* IRQs are synced during runtime_suspend, we don't require a wakeref */ disable_rpm_wakeref_asserts(dev_priv); - iir = I915_READ(IIR); - - for (;;) { - bool irq_received = (iir) != 0; - bool blc_event = false; - - /* Can't rely on pipestat interrupt bit in iir as it might - * have been cleared after the pipestat interrupt was received. - * It doesn't set the bit in iir again, but it still produces - * interrupts (for non-MSI). - */ - spin_lock(&dev_priv->irq_lock); - if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) - DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - - for_each_pipe(dev_priv, pipe) { - i915_reg_t reg = PIPESTAT(pipe); - pipe_stats[pipe] = I915_READ(reg); - - /* - * Clear the PIPE*STAT regs before the IIR - */ - if (pipe_stats[pipe] & 0x8000ffff) { - I915_WRITE(reg, pipe_stats[pipe]); - irq_received = true; - } - } - spin_unlock(&dev_priv->irq_lock); + do { + u32 pipe_stats[I915_MAX_PIPES] = {}; + u32 hotplug_status = 0; + u32 iir; - if (!irq_received) + iir = I915_READ(IIR); + if (iir == 0) break; ret = IRQ_HANDLED; - /* Consume port. Then clear IIR or we'll miss events */ - if (iir & I915_DISPLAY_PORT_INTERRUPT) { - u32 hotplug_status = i9xx_hpd_irq_ack(dev_priv); - if (hotplug_status) - i9xx_hpd_irq_handler(dev_priv, hotplug_status); - } + if (iir & I915_DISPLAY_PORT_INTERRUPT) + hotplug_status = i9xx_hpd_irq_ack(dev_priv); + + /* Call regardless, as some status bits might not be + * signalled in iir */ + i9xx_pipestat_irq_ack(dev_priv, iir, pipe_stats); I915_WRITE(IIR, iir); - new_iir = I915_READ(IIR); /* Flush posted writes */ if (iir & I915_USER_INTERRUPT) notify_ring(dev_priv->engine[RCS]); + if (iir & I915_BSD_USER_INTERRUPT) notify_ring(dev_priv->engine[VCS]); - for_each_pipe(dev_priv, pipe) { - if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS) - drm_handle_vblank(&dev_priv->drm, pipe); - - if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) - blc_event = true; - - if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) - i9xx_pipe_crc_irq_handler(dev_priv, pipe); - - if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS) - intel_cpu_fifo_underrun_irq_handler(dev_priv, pipe); - } - - if (blc_event || (iir & I915_ASLE_INTERRUPT)) - intel_opregion_asle_intr(dev_priv); + if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT) + DRM_DEBUG("Command parser error, iir 0x%08x\n", iir); - if (pipe_stats[0] & PIPE_GMBUS_INTERRUPT_STATUS) - gmbus_irq_handler(dev_priv); + if (hotplug_status) + i9xx_hpd_irq_handler(dev_priv, hotplug_status); - /* With MSI, interrupts are only generated when iir - * transitions from zero to nonzero. If another bit got - * set while we were handling the existing iir bits, then - * we would never get another interrupt. - * - * This is fine on non-MSI as well, as if we hit this path - * we avoid exiting the interrupt handler only to generate - * another one. - * - * Note that for MSI this could cause a stray interrupt report - * if an interrupt landed in the time between writing IIR and - * the posting read. This should be rare enough to never - * trigger the 99% of 100,000 interrupts test for disabling - * stray interrupts. - */ - iir = new_iir; - } + i965_pipestat_irq_handler(dev_priv, iir, pipe_stats); + } while (0); enable_rpm_wakeref_asserts(dev_priv); return ret; } -static void i965_irq_uninstall(struct drm_device * dev) -{ - struct drm_i915_private *dev_priv = to_i915(dev); - int pipe; - - if (!dev_priv) - return; - - i915_hotplug_interrupt_update(dev_priv, 0xffffffff, 0); - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); - - I915_WRITE(HWSTAM, 0xffffffff); - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), 0); - I915_WRITE(IMR, 0xffffffff); - I915_WRITE(IER, 0x0); - - for_each_pipe(dev_priv, pipe) - I915_WRITE(PIPESTAT(pipe), - I915_READ(PIPESTAT(pipe)) & 0x8000ffff); - I915_WRITE(IIR, I915_READ(IIR)); -} - /** * intel_irq_init - initializes irq support * @dev_priv: i915 device instance @@ -4127,11 +4017,12 @@ static void i965_irq_uninstall(struct drm_device * dev) void intel_irq_init(struct drm_i915_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; + struct intel_rps *rps = &dev_priv->gt_pm.rps; int i; intel_hpd_init_work(dev_priv); - INIT_WORK(&dev_priv->rps.work, gen6_pm_rps_work); + INIT_WORK(&rps->work, gen6_pm_rps_work); INIT_WORK(&dev_priv->l3_parity.error_work, ivybridge_parity_work); for (i = 0; i < MAX_L3_SLICES; ++i) @@ -4147,7 +4038,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) else dev_priv->pm_rps_events = GEN6_PM_RPS_EVENTS; - dev_priv->rps.pm_intrmsk_mbz = 0; + rps->pm_intrmsk_mbz = 0; /* * SNB,IVB,HSW can while VLV,CHV may hard hang on looping batchbuffer @@ -4156,10 +4047,10 @@ void intel_irq_init(struct drm_i915_private *dev_priv) * TODO: verify if this can be reproduced on VLV,CHV. */ if (INTEL_GEN(dev_priv) <= 7) - dev_priv->rps.pm_intrmsk_mbz |= GEN6_PM_RP_UP_EI_EXPIRED; + rps->pm_intrmsk_mbz |= GEN6_PM_RP_UP_EI_EXPIRED; if (INTEL_GEN(dev_priv) >= 8) - dev_priv->rps.pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; + rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; if (IS_GEN2(dev_priv)) { /* Gen2 doesn't have a hardware frame counter */ @@ -4197,17 +4088,17 @@ void intel_irq_init(struct drm_i915_private *dev_priv) if (IS_CHERRYVIEW(dev_priv)) { dev->driver->irq_handler = cherryview_irq_handler; - dev->driver->irq_preinstall = cherryview_irq_preinstall; + dev->driver->irq_preinstall = cherryview_irq_reset; dev->driver->irq_postinstall = cherryview_irq_postinstall; - dev->driver->irq_uninstall = cherryview_irq_uninstall; + dev->driver->irq_uninstall = cherryview_irq_reset; dev->driver->enable_vblank = i965_enable_vblank; dev->driver->disable_vblank = i965_disable_vblank; dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; } else if (IS_VALLEYVIEW(dev_priv)) { dev->driver->irq_handler = valleyview_irq_handler; - dev->driver->irq_preinstall = valleyview_irq_preinstall; + dev->driver->irq_preinstall = valleyview_irq_reset; dev->driver->irq_postinstall = valleyview_irq_postinstall; - dev->driver->irq_uninstall = valleyview_irq_uninstall; + dev->driver->irq_uninstall = valleyview_irq_reset; dev->driver->enable_vblank = i965_enable_vblank; dev->driver->disable_vblank = i965_disable_vblank; dev_priv->display.hpd_irq_setup = i915_hpd_irq_setup; @@ -4215,7 +4106,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_handler = gen8_irq_handler; dev->driver->irq_preinstall = gen8_irq_reset; dev->driver->irq_postinstall = gen8_irq_postinstall; - dev->driver->irq_uninstall = gen8_irq_uninstall; + dev->driver->irq_uninstall = gen8_irq_reset; dev->driver->enable_vblank = gen8_enable_vblank; dev->driver->disable_vblank = gen8_disable_vblank; if (IS_GEN9_LP(dev_priv)) @@ -4229,29 +4120,29 @@ void intel_irq_init(struct drm_i915_private *dev_priv) dev->driver->irq_handler = ironlake_irq_handler; dev->driver->irq_preinstall = ironlake_irq_reset; dev->driver->irq_postinstall = ironlake_irq_postinstall; - dev->driver->irq_uninstall = ironlake_irq_uninstall; + dev->driver->irq_uninstall = ironlake_irq_reset; dev->driver->enable_vblank = ironlake_enable_vblank; dev->driver->disable_vblank = ironlake_disable_vblank; dev_priv->display.hpd_irq_setup = ilk_hpd_irq_setup; } else { if (IS_GEN2(dev_priv)) { - dev->driver->irq_preinstall = i8xx_irq_preinstall; + dev->driver->irq_preinstall = i8xx_irq_reset; dev->driver->irq_postinstall = i8xx_irq_postinstall; dev->driver->irq_handler = i8xx_irq_handler; - dev->driver->irq_uninstall = i8xx_irq_uninstall; + dev->driver->irq_uninstall = i8xx_irq_reset; dev->driver->enable_vblank = i8xx_enable_vblank; dev->driver->disable_vblank = i8xx_disable_vblank; } else if (IS_GEN3(dev_priv)) { - dev->driver->irq_preinstall = i915_irq_preinstall; + dev->driver->irq_preinstall = i915_irq_reset; dev->driver->irq_postinstall = i915_irq_postinstall; - dev->driver->irq_uninstall = i915_irq_uninstall; + dev->driver->irq_uninstall = i915_irq_reset; dev->driver->irq_handler = i915_irq_handler; dev->driver->enable_vblank = i8xx_enable_vblank; dev->driver->disable_vblank = i8xx_disable_vblank; } else { - dev->driver->irq_preinstall = i965_irq_preinstall; + dev->driver->irq_preinstall = i965_irq_reset; dev->driver->irq_postinstall = i965_irq_postinstall; - dev->driver->irq_uninstall = i965_irq_uninstall; + dev->driver->irq_uninstall = i965_irq_reset; dev->driver->irq_handler = i965_irq_handler; dev->driver->enable_vblank = i965_enable_vblank; dev->driver->disable_vblank = i965_disable_vblank; @@ -4293,7 +4184,7 @@ int intel_irq_install(struct drm_i915_private *dev_priv) * interrupts as enabled _before_ actually enabling them to avoid * special cases in our ordering checks. */ - dev_priv->pm.irqs_enabled = true; + dev_priv->runtime_pm.irqs_enabled = true; return drm_irq_install(&dev_priv->drm, dev_priv->drm.pdev->irq); } @@ -4309,7 +4200,7 @@ void intel_irq_uninstall(struct drm_i915_private *dev_priv) { drm_irq_uninstall(&dev_priv->drm); intel_hpd_cancel_work(dev_priv); - dev_priv->pm.irqs_enabled = false; + dev_priv->runtime_pm.irqs_enabled = false; } /** @@ -4322,7 +4213,7 @@ void intel_irq_uninstall(struct drm_i915_private *dev_priv) void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) { dev_priv->drm.driver->irq_uninstall(&dev_priv->drm); - dev_priv->pm.irqs_enabled = false; + dev_priv->runtime_pm.irqs_enabled = false; synchronize_irq(dev_priv->drm.irq); } @@ -4335,7 +4226,7 @@ void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv) */ void intel_runtime_pm_enable_interrupts(struct drm_i915_private *dev_priv) { - dev_priv->pm.irqs_enabled = true; + dev_priv->runtime_pm.irqs_enabled = true; dev_priv->drm.driver->irq_preinstall(&dev_priv->drm); dev_priv->drm.driver->irq_postinstall(&dev_priv->drm); } diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt2.c b/drivers/gpu/drm/i915/i915_oa_cflgt2.c new file mode 100644 index 000000000000..368c87d7ee9a --- /dev/null +++ b/drivers/gpu/drm/i915/i915_oa_cflgt2.c @@ -0,0 +1,109 @@ +/* + * Autogenerated file by GPU Top : https://github.com/rib/gputop + * DO NOT EDIT manually! + * + * + * Copyright (c) 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION 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 <linux/sysfs.h> + +#include "i915_drv.h" +#include "i915_oa_cflgt2.h" + +static const struct i915_oa_reg b_counter_config_test_oa[] = { + { _MMIO(0x2740), 0x00000000 }, + { _MMIO(0x2744), 0x00800000 }, + { _MMIO(0x2714), 0xf0800000 }, + { _MMIO(0x2710), 0x00000000 }, + { _MMIO(0x2724), 0xf0800000 }, + { _MMIO(0x2720), 0x00000000 }, + { _MMIO(0x2770), 0x00000004 }, + { _MMIO(0x2774), 0x00000000 }, + { _MMIO(0x2778), 0x00000003 }, + { _MMIO(0x277c), 0x00000000 }, + { _MMIO(0x2780), 0x00000007 }, + { _MMIO(0x2784), 0x00000000 }, + { _MMIO(0x2788), 0x00100002 }, + { _MMIO(0x278c), 0x0000fff7 }, + { _MMIO(0x2790), 0x00100002 }, + { _MMIO(0x2794), 0x0000ffcf }, + { _MMIO(0x2798), 0x00100082 }, + { _MMIO(0x279c), 0x0000ffef }, + { _MMIO(0x27a0), 0x001000c2 }, + { _MMIO(0x27a4), 0x0000ffe7 }, + { _MMIO(0x27a8), 0x00100001 }, + { _MMIO(0x27ac), 0x0000ffe7 }, +}; + +static const struct i915_oa_reg flex_eu_config_test_oa[] = { +}; + +static const struct i915_oa_reg mux_config_test_oa[] = { + { _MMIO(0x9840), 0x00000080 }, + { _MMIO(0x9888), 0x11810000 }, + { _MMIO(0x9888), 0x07810013 }, + { _MMIO(0x9888), 0x1f810000 }, + { _MMIO(0x9888), 0x1d810000 }, + { _MMIO(0x9888), 0x1b930040 }, + { _MMIO(0x9888), 0x07e54000 }, + { _MMIO(0x9888), 0x1f908000 }, + { _MMIO(0x9888), 0x11900000 }, + { _MMIO(0x9888), 0x37900000 }, + { _MMIO(0x9888), 0x53900000 }, + { _MMIO(0x9888), 0x45900000 }, + { _MMIO(0x9888), 0x33900000 }, +}; + +static ssize_t +show_test_oa_id(struct device *kdev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "1\n"); +} + +void +i915_perf_load_test_config_cflgt2(struct drm_i915_private *dev_priv) +{ + strncpy(dev_priv->perf.oa.test_config.uuid, + "74fb4902-d3d3-4237-9e90-cbdc68d0a446", + UUID_STRING_LEN); + dev_priv->perf.oa.test_config.id = 1; + + dev_priv->perf.oa.test_config.mux_regs = mux_config_test_oa; + dev_priv->perf.oa.test_config.mux_regs_len = ARRAY_SIZE(mux_config_test_oa); + + dev_priv->perf.oa.test_config.b_counter_regs = b_counter_config_test_oa; + dev_priv->perf.oa.test_config.b_counter_regs_len = ARRAY_SIZE(b_counter_config_test_oa); + + dev_priv->perf.oa.test_config.flex_regs = flex_eu_config_test_oa; + dev_priv->perf.oa.test_config.flex_regs_len = ARRAY_SIZE(flex_eu_config_test_oa); + + dev_priv->perf.oa.test_config.sysfs_metric.name = "74fb4902-d3d3-4237-9e90-cbdc68d0a446"; + dev_priv->perf.oa.test_config.sysfs_metric.attrs = dev_priv->perf.oa.test_config.attrs; + + dev_priv->perf.oa.test_config.attrs[0] = &dev_priv->perf.oa.test_config.sysfs_metric_id.attr; + + dev_priv->perf.oa.test_config.sysfs_metric_id.attr.name = "id"; + dev_priv->perf.oa.test_config.sysfs_metric_id.attr.mode = 0444; + dev_priv->perf.oa.test_config.sysfs_metric_id.show = show_test_oa_id; +} diff --git a/drivers/gpu/drm/i915/i915_oa_cflgt2.h b/drivers/gpu/drm/i915/i915_oa_cflgt2.h new file mode 100644 index 000000000000..1f3268ef2ea2 --- /dev/null +++ b/drivers/gpu/drm/i915/i915_oa_cflgt2.h @@ -0,0 +1,34 @@ +/* + * Autogenerated file by GPU Top : https://github.com/rib/gputop + * DO NOT EDIT manually! + * + * + * Copyright (c) 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef __I915_OA_CFLGT2_H__ +#define __I915_OA_CFLGT2_H__ + +extern void i915_perf_load_test_config_cflgt2(struct drm_i915_private *dev_priv); + +#endif diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 8ab003dca113..b4faeb6aa2bd 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -25,235 +25,168 @@ #include "i915_params.h" #include "i915_drv.h" -struct i915_params i915 __read_mostly = { - .modeset = -1, - .panel_ignore_lid = 1, - .semaphores = -1, - .lvds_channel_mode = 0, - .panel_use_ssc = -1, - .vbt_sdvo_panel_type = -1, - .enable_rc6 = -1, - .enable_dc = -1, - .enable_fbc = -1, - .enable_execlists = -1, - .enable_hangcheck = true, - .enable_ppgtt = -1, - .enable_psr = -1, - .alpha_support = IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT), - .disable_power_well = -1, - .enable_ips = 1, - .fastboot = 0, - .prefault_disable = 0, - .load_detect_test = 0, - .force_reset_modeset_test = 0, - .reset = 2, - .error_capture = true, - .invert_brightness = 0, - .disable_display = 0, - .enable_cmd_parser = true, - .use_mmio_flip = 0, - .mmio_debug = 0, - .verbose_state_checks = 1, - .nuclear_pageflip = 0, - .edp_vswing = 0, - .enable_guc_loading = 0, - .enable_guc_submission = 0, - .guc_log_level = -1, - .guc_firmware_path = NULL, - .huc_firmware_path = NULL, - .enable_dp_mst = true, - .inject_load_failure = 0, - .enable_dpcd_backlight = false, - .enable_gvt = false, +#define i915_param_named(name, T, perm, desc) \ + module_param_named(name, i915_modparams.name, T, perm); \ + MODULE_PARM_DESC(name, desc) +#define i915_param_named_unsafe(name, T, perm, desc) \ + module_param_named_unsafe(name, i915_modparams.name, T, perm); \ + MODULE_PARM_DESC(name, desc) + +struct i915_params i915_modparams __read_mostly = { +#define MEMBER(T, member, value) .member = (value), + I915_PARAMS_FOR_EACH(MEMBER) +#undef MEMBER }; -module_param_named(modeset, i915.modeset, int, 0400); -MODULE_PARM_DESC(modeset, +i915_param_named(modeset, int, 0400, "Use kernel modesetting [KMS] (0=disable, " "1=on, -1=force vga console preference [default])"); -module_param_named_unsafe(panel_ignore_lid, i915.panel_ignore_lid, int, 0600); -MODULE_PARM_DESC(panel_ignore_lid, +i915_param_named_unsafe(panel_ignore_lid, int, 0600, "Override lid status (0=autodetect, 1=autodetect disabled [default], " "-1=force lid closed, -2=force lid open)"); -module_param_named_unsafe(semaphores, i915.semaphores, int, 0400); -MODULE_PARM_DESC(semaphores, +i915_param_named_unsafe(semaphores, int, 0400, "Use semaphores for inter-ring sync " "(default: -1 (use per-chip defaults))"); -module_param_named_unsafe(enable_rc6, i915.enable_rc6, int, 0400); -MODULE_PARM_DESC(enable_rc6, +i915_param_named_unsafe(enable_rc6, int, 0400, "Enable power-saving render C-state 6. " "Different stages can be selected via bitmask values " "(0 = disable; 1 = enable rc6; 2 = enable deep rc6; 4 = enable deepest rc6). " "For example, 3 would enable rc6 and deep rc6, and 7 would enable everything. " "default: -1 (use per-chip default)"); -module_param_named_unsafe(enable_dc, i915.enable_dc, int, 0400); -MODULE_PARM_DESC(enable_dc, +i915_param_named_unsafe(enable_dc, int, 0400, "Enable power-saving display C-states. " "(-1=auto [default]; 0=disable; 1=up to DC5; 2=up to DC6)"); -module_param_named_unsafe(enable_fbc, i915.enable_fbc, int, 0600); -MODULE_PARM_DESC(enable_fbc, +i915_param_named_unsafe(enable_fbc, int, 0600, "Enable frame buffer compression for power savings " "(default: -1 (use per-chip default))"); -module_param_named_unsafe(lvds_channel_mode, i915.lvds_channel_mode, int, 0400); -MODULE_PARM_DESC(lvds_channel_mode, +i915_param_named_unsafe(lvds_channel_mode, int, 0400, "Specify LVDS channel mode " "(0=probe BIOS [default], 1=single-channel, 2=dual-channel)"); -module_param_named_unsafe(lvds_use_ssc, i915.panel_use_ssc, int, 0600); -MODULE_PARM_DESC(lvds_use_ssc, +i915_param_named_unsafe(panel_use_ssc, int, 0600, "Use Spread Spectrum Clock with panels [LVDS/eDP] " "(default: auto from VBT)"); -module_param_named_unsafe(vbt_sdvo_panel_type, i915.vbt_sdvo_panel_type, int, 0400); -MODULE_PARM_DESC(vbt_sdvo_panel_type, +i915_param_named_unsafe(vbt_sdvo_panel_type, int, 0400, "Override/Ignore selection of SDVO panel mode in the VBT " "(-2=ignore, -1=auto [default], index in VBT BIOS table)"); -module_param_named_unsafe(reset, i915.reset, int, 0600); -MODULE_PARM_DESC(reset, "Attempt GPU resets (0=disabled, 1=full gpu reset, 2=engine reset [default])"); +i915_param_named_unsafe(reset, int, 0600, + "Attempt GPU resets (0=disabled, 1=full gpu reset, 2=engine reset [default])"); -module_param_named_unsafe(vbt_firmware, i915.vbt_firmware, charp, 0400); -MODULE_PARM_DESC(vbt_firmware, - "Load VBT from specified file under /lib/firmware"); +i915_param_named_unsafe(vbt_firmware, charp, 0400, + "Load VBT from specified file under /lib/firmware"); #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) -module_param_named(error_capture, i915.error_capture, bool, 0600); -MODULE_PARM_DESC(error_capture, +i915_param_named(error_capture, bool, 0600, "Record the GPU state following a hang. " "This information in /sys/class/drm/card<N>/error is vital for " "triaging and debugging hangs."); #endif -module_param_named_unsafe(enable_hangcheck, i915.enable_hangcheck, bool, 0644); -MODULE_PARM_DESC(enable_hangcheck, +i915_param_named_unsafe(enable_hangcheck, bool, 0644, "Periodically check GPU activity for detecting hangs. " "WARNING: Disabling this can cause system wide hangs. " "(default: true)"); -module_param_named_unsafe(enable_ppgtt, i915.enable_ppgtt, int, 0400); -MODULE_PARM_DESC(enable_ppgtt, +i915_param_named_unsafe(enable_ppgtt, int, 0400, "Override PPGTT usage. " "(-1=auto [default], 0=disabled, 1=aliasing, 2=full, 3=full with extended address space)"); -module_param_named_unsafe(enable_execlists, i915.enable_execlists, int, 0400); -MODULE_PARM_DESC(enable_execlists, +i915_param_named_unsafe(enable_execlists, int, 0400, "Override execlists usage. " "(-1=auto [default], 0=disabled, 1=enabled)"); -module_param_named_unsafe(enable_psr, i915.enable_psr, int, 0600); -MODULE_PARM_DESC(enable_psr, "Enable PSR " - "(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) " - "Default: -1 (use per-chip default)"); +i915_param_named_unsafe(enable_psr, int, 0600, + "Enable PSR " + "(0=disabled, 1=enabled - link mode chosen per-platform, 2=force link-standby mode, 3=force link-off mode) " + "Default: -1 (use per-chip default)"); -module_param_named_unsafe(alpha_support, i915.alpha_support, bool, 0400); -MODULE_PARM_DESC(alpha_support, +i915_param_named_unsafe(alpha_support, bool, 0400, "Enable alpha quality driver support for latest hardware. " "See also CONFIG_DRM_I915_ALPHA_SUPPORT."); -module_param_named_unsafe(disable_power_well, i915.disable_power_well, int, 0400); -MODULE_PARM_DESC(disable_power_well, +i915_param_named_unsafe(disable_power_well, int, 0400, "Disable display power wells when possible " "(-1=auto [default], 0=power wells always on, 1=power wells disabled when possible)"); -module_param_named_unsafe(enable_ips, i915.enable_ips, int, 0600); -MODULE_PARM_DESC(enable_ips, "Enable IPS (default: true)"); +i915_param_named_unsafe(enable_ips, int, 0600, "Enable IPS (default: true)"); -module_param_named(fastboot, i915.fastboot, bool, 0600); -MODULE_PARM_DESC(fastboot, +i915_param_named(fastboot, bool, 0600, "Try to skip unnecessary mode sets at boot time (default: false)"); -module_param_named_unsafe(prefault_disable, i915.prefault_disable, bool, 0600); -MODULE_PARM_DESC(prefault_disable, +i915_param_named_unsafe(prefault_disable, bool, 0600, "Disable page prefaulting for pread/pwrite/reloc (default:false). " "For developers only."); -module_param_named_unsafe(load_detect_test, i915.load_detect_test, bool, 0600); -MODULE_PARM_DESC(load_detect_test, +i915_param_named_unsafe(load_detect_test, bool, 0600, "Force-enable the VGA load detect code for testing (default:false). " "For developers only."); -module_param_named_unsafe(force_reset_modeset_test, i915.force_reset_modeset_test, bool, 0600); -MODULE_PARM_DESC(force_reset_modeset_test, +i915_param_named_unsafe(force_reset_modeset_test, bool, 0600, "Force a modeset during gpu reset for testing (default:false). " "For developers only."); -module_param_named_unsafe(invert_brightness, i915.invert_brightness, int, 0600); -MODULE_PARM_DESC(invert_brightness, +i915_param_named_unsafe(invert_brightness, int, 0600, "Invert backlight brightness " "(-1 force normal, 0 machine defaults, 1 force inversion), please " "report PCI device ID, subsystem vendor and subsystem device ID " "to dri-devel@lists.freedesktop.org, if your machine needs it. " "It will then be included in an upcoming module version."); -module_param_named(disable_display, i915.disable_display, bool, 0400); -MODULE_PARM_DESC(disable_display, "Disable display (default: false)"); +i915_param_named(disable_display, bool, 0400, + "Disable display (default: false)"); -module_param_named_unsafe(enable_cmd_parser, i915.enable_cmd_parser, bool, 0400); -MODULE_PARM_DESC(enable_cmd_parser, - "Enable command parsing (true=enabled [default], false=disabled)"); +i915_param_named_unsafe(enable_cmd_parser, bool, 0400, + "Enable command parsing (true=enabled [default], false=disabled)"); -module_param_named_unsafe(use_mmio_flip, i915.use_mmio_flip, int, 0600); -MODULE_PARM_DESC(use_mmio_flip, - "use MMIO flips (-1=never, 0=driver discretion [default], 1=always)"); - -module_param_named(mmio_debug, i915.mmio_debug, int, 0600); -MODULE_PARM_DESC(mmio_debug, +i915_param_named(mmio_debug, int, 0600, "Enable the MMIO debug code for the first N failures (default: off). " "This may negatively affect performance."); -module_param_named(verbose_state_checks, i915.verbose_state_checks, bool, 0600); -MODULE_PARM_DESC(verbose_state_checks, +i915_param_named(verbose_state_checks, bool, 0600, "Enable verbose logs (ie. WARN_ON()) in case of unexpected hw state conditions."); -module_param_named_unsafe(nuclear_pageflip, i915.nuclear_pageflip, bool, 0400); -MODULE_PARM_DESC(nuclear_pageflip, - "Force enable atomic functionality on platforms that don't have full support yet."); +i915_param_named_unsafe(nuclear_pageflip, bool, 0400, + "Force enable atomic functionality on platforms that don't have full support yet."); /* WA to get away with the default setting in VBT for early platforms.Will be removed */ -module_param_named_unsafe(edp_vswing, i915.edp_vswing, int, 0400); -MODULE_PARM_DESC(edp_vswing, - "Ignore/Override vswing pre-emph table selection from VBT " - "(0=use value from vbt [default], 1=low power swing(200mV)," - "2=default swing(400mV))"); - -module_param_named_unsafe(enable_guc_loading, i915.enable_guc_loading, int, 0400); -MODULE_PARM_DESC(enable_guc_loading, - "Enable GuC firmware loading " - "(-1=auto, 0=never [default], 1=if available, 2=required)"); - -module_param_named_unsafe(enable_guc_submission, i915.enable_guc_submission, int, 0400); -MODULE_PARM_DESC(enable_guc_submission, - "Enable GuC submission " - "(-1=auto, 0=never [default], 1=if available, 2=required)"); - -module_param_named(guc_log_level, i915.guc_log_level, int, 0400); -MODULE_PARM_DESC(guc_log_level, +i915_param_named_unsafe(edp_vswing, int, 0400, + "Ignore/Override vswing pre-emph table selection from VBT " + "(0=use value from vbt [default], 1=low power swing(200mV)," + "2=default swing(400mV))"); + +i915_param_named_unsafe(enable_guc_loading, int, 0400, + "Enable GuC firmware loading " + "(-1=auto, 0=never [default], 1=if available, 2=required)"); + +i915_param_named_unsafe(enable_guc_submission, int, 0400, + "Enable GuC submission " + "(-1=auto, 0=never [default], 1=if available, 2=required)"); + +i915_param_named(guc_log_level, int, 0400, "GuC firmware logging level (-1:disabled (default), 0-3:enabled)"); -module_param_named_unsafe(guc_firmware_path, i915.guc_firmware_path, charp, 0400); -MODULE_PARM_DESC(guc_firmware_path, +i915_param_named_unsafe(guc_firmware_path, charp, 0400, "GuC firmware path to use instead of the default one"); -module_param_named_unsafe(huc_firmware_path, i915.huc_firmware_path, charp, 0400); -MODULE_PARM_DESC(huc_firmware_path, +i915_param_named_unsafe(huc_firmware_path, charp, 0400, "HuC firmware path to use instead of the default one"); -module_param_named_unsafe(enable_dp_mst, i915.enable_dp_mst, bool, 0600); -MODULE_PARM_DESC(enable_dp_mst, +i915_param_named_unsafe(enable_dp_mst, bool, 0600, "Enable multi-stream transport (MST) for new DisplayPort sinks. (default: true)"); -module_param_named_unsafe(inject_load_failure, i915.inject_load_failure, uint, 0400); -MODULE_PARM_DESC(inject_load_failure, + +i915_param_named_unsafe(inject_load_failure, uint, 0400, "Force an error after a number of failure check points (0:disabled (default), N:force failure at the Nth failure check point)"); -module_param_named(enable_dpcd_backlight, i915.enable_dpcd_backlight, bool, 0600); -MODULE_PARM_DESC(enable_dpcd_backlight, + +i915_param_named(enable_dpcd_backlight, bool, 0600, "Enable support for DPCD backlight control (default:false)"); -module_param_named(enable_gvt, i915.enable_gvt, bool, 0400); -MODULE_PARM_DESC(enable_gvt, +i915_param_named(enable_gvt, bool, 0400, "Enable support for Intel GVT-g graphics virtualization host support(default:false)"); diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index ac844709c97e..c7292268ed43 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -27,56 +27,55 @@ #include <linux/cache.h> /* for __read_mostly */ -#define I915_PARAMS_FOR_EACH(func) \ - func(char *, vbt_firmware); \ - func(int, modeset); \ - func(int, panel_ignore_lid); \ - func(int, semaphores); \ - func(int, lvds_channel_mode); \ - func(int, panel_use_ssc); \ - func(int, vbt_sdvo_panel_type); \ - func(int, enable_rc6); \ - func(int, enable_dc); \ - func(int, enable_fbc); \ - func(int, enable_ppgtt); \ - func(int, enable_execlists); \ - func(int, enable_psr); \ - func(int, disable_power_well); \ - func(int, enable_ips); \ - func(int, invert_brightness); \ - func(int, enable_guc_loading); \ - func(int, enable_guc_submission); \ - func(int, guc_log_level); \ - func(char *, guc_firmware_path); \ - func(char *, huc_firmware_path); \ - func(int, use_mmio_flip); \ - func(int, mmio_debug); \ - func(int, edp_vswing); \ - func(int, reset); \ - func(unsigned int, inject_load_failure); \ +#define I915_PARAMS_FOR_EACH(param) \ + param(char *, vbt_firmware, NULL) \ + param(int, modeset, -1) \ + param(int, panel_ignore_lid, 1) \ + param(int, semaphores, -1) \ + param(int, lvds_channel_mode, 0) \ + param(int, panel_use_ssc, -1) \ + param(int, vbt_sdvo_panel_type, -1) \ + param(int, enable_rc6, -1) \ + param(int, enable_dc, -1) \ + param(int, enable_fbc, -1) \ + param(int, enable_ppgtt, -1) \ + param(int, enable_execlists, -1) \ + param(int, enable_psr, -1) \ + param(int, disable_power_well, -1) \ + param(int, enable_ips, 1) \ + param(int, invert_brightness, 0) \ + param(int, enable_guc_loading, 0) \ + param(int, enable_guc_submission, 0) \ + param(int, guc_log_level, -1) \ + param(char *, guc_firmware_path, NULL) \ + param(char *, huc_firmware_path, NULL) \ + param(int, mmio_debug, 0) \ + param(int, edp_vswing, 0) \ + param(int, reset, 2) \ + param(unsigned int, inject_load_failure, 0) \ /* leave bools at the end to not create holes */ \ - func(bool, alpha_support); \ - func(bool, enable_cmd_parser); \ - func(bool, enable_hangcheck); \ - func(bool, fastboot); \ - func(bool, prefault_disable); \ - func(bool, load_detect_test); \ - func(bool, force_reset_modeset_test); \ - func(bool, error_capture); \ - func(bool, disable_display); \ - func(bool, verbose_state_checks); \ - func(bool, nuclear_pageflip); \ - func(bool, enable_dp_mst); \ - func(bool, enable_dpcd_backlight); \ - func(bool, enable_gvt) + param(bool, alpha_support, IS_ENABLED(CONFIG_DRM_I915_ALPHA_SUPPORT)) \ + param(bool, enable_cmd_parser, true) \ + param(bool, enable_hangcheck, true) \ + param(bool, fastboot, false) \ + param(bool, prefault_disable, false) \ + param(bool, load_detect_test, false) \ + param(bool, force_reset_modeset_test, false) \ + param(bool, error_capture, true) \ + param(bool, disable_display, false) \ + param(bool, verbose_state_checks, true) \ + param(bool, nuclear_pageflip, false) \ + param(bool, enable_dp_mst, true) \ + param(bool, enable_dpcd_backlight, false) \ + param(bool, enable_gvt, false) -#define MEMBER(T, member) T member +#define MEMBER(T, member, ...) T member; struct i915_params { I915_PARAMS_FOR_EACH(MEMBER); }; #undef MEMBER -extern struct i915_params i915 __read_mostly; +extern struct i915_params i915_modparams __read_mostly; #endif diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 881b5d6708aa..6458c309c039 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -54,8 +54,14 @@ .color = { .degamma_lut_size = 512, .gamma_lut_size = 512 } #define CHV_COLORS \ .color = { .degamma_lut_size = 65, .gamma_lut_size = 257 } +#define GLK_COLORS \ + .color = { .degamma_lut_size = 0, .gamma_lut_size = 1024 } /* Keep in gen based order, and chronological order within a gen */ + +#define GEN_DEFAULT_PAGE_SIZES \ + .page_sizes = I915_GTT_PAGE_SIZE_4K + #define GEN2_FEATURES \ .gen = 2, .num_pipes = 1, \ .has_overlay = 1, .overlay_needs_physical = 1, \ @@ -65,6 +71,7 @@ .ring_mask = RENDER_RING, \ .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ + GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS static const struct intel_device_info intel_i830_info __initconst = { @@ -98,6 +105,7 @@ static const struct intel_device_info intel_i865g_info __initconst = { .ring_mask = RENDER_RING, \ .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ + GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS static const struct intel_device_info intel_i915g_info __initconst = { @@ -161,6 +169,7 @@ static const struct intel_device_info intel_pineview_info __initconst = { .ring_mask = RENDER_RING, \ .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ + GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS static const struct intel_device_info intel_i965g_info __initconst = { @@ -168,6 +177,7 @@ static const struct intel_device_info intel_i965g_info __initconst = { .platform = INTEL_I965G, .has_overlay = 1, .hws_needs_physical = 1, + .has_snoop = false, }; static const struct intel_device_info intel_i965gm_info __initconst = { @@ -177,12 +187,12 @@ static const struct intel_device_info intel_i965gm_info __initconst = { .has_overlay = 1, .supports_tv = 1, .hws_needs_physical = 1, + .has_snoop = false, }; static const struct intel_device_info intel_g45_info __initconst = { GEN4_FEATURES, .platform = INTEL_G45, - .has_pipe_cxsr = 1, .ring_mask = RENDER_RING | BSD_RING, }; @@ -190,7 +200,6 @@ static const struct intel_device_info intel_gm45_info __initconst = { GEN4_FEATURES, .platform = INTEL_GM45, .is_mobile = 1, .has_fbc = 1, - .has_pipe_cxsr = 1, .supports_tv = 1, .ring_mask = RENDER_RING | BSD_RING, }; @@ -198,10 +207,10 @@ static const struct intel_device_info intel_gm45_info __initconst = { #define GEN5_FEATURES \ .gen = 5, .num_pipes = 2, \ .has_hotplug = 1, \ - .has_gmbus_irq = 1, \ .ring_mask = RENDER_RING | BSD_RING, \ .has_snoop = true, \ GEN_DEFAULT_PIPEOFFSETS, \ + GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS static const struct intel_device_info intel_ironlake_d_info __initconst = { @@ -223,9 +232,9 @@ static const struct intel_device_info intel_ironlake_m_info __initconst = { .has_llc = 1, \ .has_rc6 = 1, \ .has_rc6p = 1, \ - .has_gmbus_irq = 1, \ .has_aliasing_ppgtt = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ + GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS #define SNB_D_PLATFORM \ @@ -266,10 +275,10 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info __initconst = .has_llc = 1, \ .has_rc6 = 1, \ .has_rc6p = 1, \ - .has_gmbus_irq = 1, \ .has_aliasing_ppgtt = 1, \ .has_full_ppgtt = 1, \ GEN_DEFAULT_PIPEOFFSETS, \ + GEN_DEFAULT_PAGE_SIZES, \ IVB_CURSOR_OFFSETS #define IVB_D_PLATFORM \ @@ -319,7 +328,6 @@ static const struct intel_device_info intel_valleyview_info __initconst = { .has_psr = 1, .has_runtime_pm = 1, .has_rc6 = 1, - .has_gmbus_irq = 1, .has_gmch_display = 1, .has_hotplug = 1, .has_aliasing_ppgtt = 1, @@ -327,11 +335,12 @@ static const struct intel_device_info intel_valleyview_info __initconst = { .has_snoop = true, .ring_mask = RENDER_RING | BSD_RING | BLT_RING, .display_mmio_offset = VLV_DISPLAY_BASE, + GEN_DEFAULT_PAGE_SIZES, GEN_DEFAULT_PIPEOFFSETS, CURSOR_OFFSETS }; -#define HSW_FEATURES \ +#define G75_FEATURES \ GEN7_FEATURES, \ .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, \ .has_ddi = 1, \ @@ -343,7 +352,7 @@ static const struct intel_device_info intel_valleyview_info __initconst = { .has_runtime_pm = 1 #define HSW_PLATFORM \ - HSW_FEATURES, \ + G75_FEATURES, \ .platform = INTEL_HASWELL, \ .has_l3_dpf = 1 @@ -362,16 +371,18 @@ static const struct intel_device_info intel_haswell_gt3_info __initconst = { .gt = 3, }; -#define BDW_FEATURES \ - HSW_FEATURES, \ +#define GEN8_FEATURES \ + G75_FEATURES, \ BDW_COLORS, \ + .page_sizes = I915_GTT_PAGE_SIZE_4K | \ + I915_GTT_PAGE_SIZE_2M, \ .has_logical_ring_contexts = 1, \ .has_full_48bit_ppgtt = 1, \ .has_64bit_reloc = 1, \ .has_reset_engine = 1 #define BDW_PLATFORM \ - BDW_FEATURES, \ + GEN8_FEATURES, \ .gen = 8, \ .platform = INTEL_BROADWELL @@ -410,7 +421,6 @@ static const struct intel_device_info intel_cherryview_info __initconst = { .has_runtime_pm = 1, .has_resource_streamer = 1, .has_rc6 = 1, - .has_gmbus_irq = 1, .has_logical_ring_contexts = 1, .has_gmch_display = 1, .has_aliasing_ppgtt = 1, @@ -418,19 +428,31 @@ static const struct intel_device_info intel_cherryview_info __initconst = { .has_reset_engine = 1, .has_snoop = true, .display_mmio_offset = VLV_DISPLAY_BASE, + GEN_DEFAULT_PAGE_SIZES, GEN_CHV_PIPEOFFSETS, CURSOR_OFFSETS, CHV_COLORS, }; -#define SKL_PLATFORM \ - BDW_FEATURES, \ - .gen = 9, \ - .platform = INTEL_SKYLAKE, \ +#define GEN9_DEFAULT_PAGE_SIZES \ + .page_sizes = I915_GTT_PAGE_SIZE_4K | \ + I915_GTT_PAGE_SIZE_64K | \ + I915_GTT_PAGE_SIZE_2M + +#define GEN9_FEATURES \ + GEN8_FEATURES, \ + GEN9_DEFAULT_PAGE_SIZES, \ + .has_logical_ring_preemption = 1, \ .has_csr = 1, \ .has_guc = 1, \ + .has_ipc = 1, \ .ddb_size = 896 +#define SKL_PLATFORM \ + GEN9_FEATURES, \ + .gen = 9, \ + .platform = INTEL_SKYLAKE + static const struct intel_device_info intel_skylake_gt1_info __initconst = { SKL_PLATFORM, .gt = 1, @@ -466,20 +488,23 @@ static const struct intel_device_info intel_skylake_gt4_info __initconst = { .has_ddi = 1, \ .has_fpga_dbg = 1, \ .has_fbc = 1, \ + .has_psr = 1, \ .has_runtime_pm = 1, \ .has_pooled_eu = 0, \ .has_csr = 1, \ .has_resource_streamer = 1, \ .has_rc6 = 1, \ .has_dp_mst = 1, \ - .has_gmbus_irq = 1, \ .has_logical_ring_contexts = 1, \ + .has_logical_ring_preemption = 1, \ .has_guc = 1, \ .has_aliasing_ppgtt = 1, \ .has_full_ppgtt = 1, \ .has_full_48bit_ppgtt = 1, \ .has_reset_engine = 1, \ .has_snoop = true, \ + .has_ipc = 1, \ + GEN9_DEFAULT_PAGE_SIZES, \ GEN_DEFAULT_PIPEOFFSETS, \ IVB_CURSOR_OFFSETS, \ BDW_COLORS @@ -494,16 +519,13 @@ static const struct intel_device_info intel_geminilake_info __initconst = { GEN9_LP_FEATURES, .platform = INTEL_GEMINILAKE, .ddb_size = 1024, - .color = { .degamma_lut_size = 0, .gamma_lut_size = 1024 } + GLK_COLORS, }; #define KBL_PLATFORM \ - BDW_FEATURES, \ + GEN9_FEATURES, \ .gen = 9, \ - .platform = INTEL_KABYLAKE, \ - .has_csr = 1, \ - .has_guc = 1, \ - .ddb_size = 896 + .platform = INTEL_KABYLAKE static const struct intel_device_info intel_kabylake_gt1_info __initconst = { KBL_PLATFORM, @@ -522,13 +544,9 @@ static const struct intel_device_info intel_kabylake_gt3_info __initconst = { }; #define CFL_PLATFORM \ - .is_alpha_support = 1, \ - BDW_FEATURES, \ + GEN9_FEATURES, \ .gen = 9, \ - .platform = INTEL_COFFEELAKE, \ - .has_csr = 1, \ - .has_guc = 1, \ - .ddb_size = 896 + .platform = INTEL_COFFEELAKE static const struct intel_device_info intel_coffeelake_gt1_info __initconst = { CFL_PLATFORM, @@ -546,15 +564,17 @@ static const struct intel_device_info intel_coffeelake_gt3_info __initconst = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; +#define GEN10_FEATURES \ + GEN9_FEATURES, \ + .ddb_size = 1024, \ + GLK_COLORS + static const struct intel_device_info intel_cannonlake_gt2_info __initconst = { - BDW_FEATURES, + GEN10_FEATURES, .is_alpha_support = 1, .platform = INTEL_CANNONLAKE, .gen = 10, .gt = 2, - .ddb_size = 1024, - .has_csr = 1, - .color = { .degamma_lut_size = 0, .gamma_lut_size = 1024 } }; /* @@ -623,7 +643,7 @@ static void i915_pci_remove(struct pci_dev *pdev) struct drm_device *dev = pci_get_drvdata(pdev); i915_driver_unload(dev); - drm_dev_unref(dev); + drm_dev_put(dev); } static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) @@ -632,7 +652,7 @@ static int i915_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) (struct intel_device_info *) ent->driver_data; int err; - if (IS_ALPHA_SUPPORT(intel_info) && !i915.alpha_support) { + if (IS_ALPHA_SUPPORT(intel_info) && !i915_modparams.alpha_support) { DRM_INFO("The driver support for your hardware in this kernel version is alpha quality\n" "See CONFIG_DRM_I915_ALPHA_SUPPORT or i915.alpha_support module parameter\n" "to enable support in this kernel version, or check for kernel updates.\n"); @@ -690,10 +710,10 @@ static int __init i915_init(void) * vga_text_mode_force boot option. */ - if (i915.modeset == 0) + if (i915_modparams.modeset == 0) use_kms = false; - if (vgacon_text_force() && i915.modeset == -1) + if (vgacon_text_force() && i915_modparams.modeset == -1) use_kms = false; if (!use_kms) { diff --git a/drivers/gpu/drm/i915/i915_perf.c b/drivers/gpu/drm/i915/i915_perf.c index 94185d610673..59ee808f8fd9 100644 --- a/drivers/gpu/drm/i915/i915_perf.c +++ b/drivers/gpu/drm/i915/i915_perf.c @@ -206,6 +206,7 @@ #include "i915_oa_kblgt2.h" #include "i915_oa_kblgt3.h" #include "i915_oa_glk.h" +#include "i915_oa_cflgt2.h" /* HW requires this to be a power of two, between 128k and 16M, though driver * is currently generally designed assuming the largest 16M size is used such @@ -1213,7 +1214,7 @@ static int oa_get_render_ctx_id(struct i915_perf_stream *stream) { struct drm_i915_private *dev_priv = stream->dev_priv; - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) dev_priv->perf.oa.specific_ctx_id = stream->ctx->hw_id; else { struct intel_engine_cs *engine = dev_priv->engine[RCS]; @@ -1259,7 +1260,7 @@ static void oa_put_render_ctx_id(struct i915_perf_stream *stream) { struct drm_i915_private *dev_priv = stream->dev_priv; - if (i915.enable_execlists) { + if (i915_modparams.enable_execlists) { dev_priv->perf.oa.specific_ctx_id = INVALID_CTX_ID; } else { struct intel_engine_cs *engine = dev_priv->engine[RCS]; @@ -1850,8 +1851,7 @@ static int gen8_enable_metric_set(struct drm_i915_private *dev_priv, * be read back from automatically triggered reports, as part of the * RPT_ID field. */ - if (IS_SKYLAKE(dev_priv) || IS_BROXTON(dev_priv) || - IS_KABYLAKE(dev_priv) || IS_GEMINILAKE(dev_priv)) { + if (IS_GEN9(dev_priv)) { I915_WRITE(GEN8_OA_DEBUG, _MASKED_BIT_ENABLE(GEN9_OA_DEBUG_DISABLE_CLK_RATIO_REPORTS | GEN9_OA_DEBUG_INCLUDE_CLK_RATIO)); @@ -2537,6 +2537,10 @@ static const struct file_operations fops = { .poll = i915_perf_poll, .read = i915_perf_read, .unlocked_ioctl = i915_perf_ioctl, + /* Our ioctl have no arguments, so it's safe to use the same function + * to handle 32bits compatibility. + */ + .compat_ioctl = i915_perf_ioctl, }; @@ -2927,6 +2931,9 @@ void i915_perf_register(struct drm_i915_private *dev_priv) i915_perf_load_test_config_kblgt3(dev_priv); } else if (IS_GEMINILAKE(dev_priv)) { i915_perf_load_test_config_glk(dev_priv); + } else if (IS_COFFEELAKE(dev_priv)) { + if (IS_CFL_GT2(dev_priv)) + i915_perf_load_test_config_cflgt2(dev_priv); } if (dev_priv->perf.oa.test_config.id == 0) @@ -3405,7 +3412,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv) dev_priv->perf.oa.timestamp_frequency = 12500000; dev_priv->perf.oa.oa_formats = hsw_oa_formats; - } else if (i915.enable_execlists) { + } else if (i915_modparams.enable_execlists) { /* Note: that although we could theoretically also support the * legacy ringbuffer mode on BDW (and earlier iterations of * this driver, before upstreaming did this) it didn't seem @@ -3453,6 +3460,7 @@ void i915_perf_init(struct drm_i915_private *dev_priv) break; case INTEL_SKYLAKE: case INTEL_KABYLAKE: + case INTEL_COFFEELAKE: dev_priv->perf.oa.timestamp_frequency = 12000000; break; default: diff --git a/drivers/gpu/drm/i915/i915_pvinfo.h b/drivers/gpu/drm/i915/i915_pvinfo.h index 0679a58cdbae..195203f298df 100644 --- a/drivers/gpu/drm/i915/i915_pvinfo.h +++ b/drivers/gpu/drm/i915/i915_pvinfo.h @@ -53,6 +53,7 @@ enum vgt_g2v_type { * VGT capabilities type */ #define VGT_CAPS_FULL_48BIT_PPGTT BIT(2) +#define VGT_CAPS_HWSP_EMULATION BIT(3) struct vgt_if { u64 magic; /* VGT_MAGIC */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2eff98cdcfad..68a58cce6ab1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2336,7 +2336,7 @@ enum i915_power_well_id { #define DONE_REG _MMIO(0x40b0) #define GEN8_PRIVATE_PAT_LO _MMIO(0x40e0) #define GEN8_PRIVATE_PAT_HI _MMIO(0x40e0 + 4) -#define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + index*4) +#define GEN10_PAT_INDEX(index) _MMIO(0x40e0 + (index)*4) #define BSD_HWS_PGA_GEN7 _MMIO(0x04180) #define BLT_HWS_PGA_GEN7 _MMIO(0x04280) #define VEBOX_HWS_PGA_GEN7 _MMIO(0x04380) @@ -2371,6 +2371,9 @@ enum i915_power_well_id { #define GEN9_GAMT_ECO_REG_RW_IA _MMIO(0x4ab0) #define GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS (1<<18) +#define GEN8_GAMW_ECO_DEV_RW_IA _MMIO(0x4080) +#define GAMW_ECO_ENABLE_64K_IPS_FIELD 0xF + #define GAMT_CHKN_BIT_REG _MMIO(0x4ab8) #define GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING (1<<28) #define GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT (1<<24) @@ -2730,6 +2733,11 @@ enum i915_power_well_id { #define GEN9_F2_SS_DIS_SHIFT 20 #define GEN9_F2_SS_DIS_MASK (0xf << GEN9_F2_SS_DIS_SHIFT) +#define GEN10_F2_S_ENA_SHIFT 22 +#define GEN10_F2_S_ENA_MASK (0x3f << GEN10_F2_S_ENA_SHIFT) +#define GEN10_F2_SS_DIS_SHIFT 18 +#define GEN10_F2_SS_DIS_MASK (0xf << GEN10_F2_SS_DIS_SHIFT) + #define GEN8_EU_DISABLE0 _MMIO(0x9134) #define GEN8_EU_DIS0_S0_MASK 0xffffff #define GEN8_EU_DIS0_S1_SHIFT 24 @@ -2745,6 +2753,9 @@ enum i915_power_well_id { #define GEN9_EU_DISABLE(slice) _MMIO(0x9134 + (slice)*0x4) +#define GEN10_EU_DISABLE3 _MMIO(0x9140) +#define GEN10_EU_DIS_SS_MASK 0xff + #define GEN6_BSD_SLEEP_PSMI_CONTROL _MMIO(0x12050) #define GEN6_BSD_SLEEP_MSG_DISABLE (1 << 0) #define GEN6_BSD_SLEEP_FLUSH_DISABLE (1 << 2) @@ -3811,6 +3822,16 @@ enum { #define PWM2_GATING_DIS (1 << 14) #define PWM1_GATING_DIS (1 << 13) +#define _CLKGATE_DIS_PSL_A 0x46520 +#define _CLKGATE_DIS_PSL_B 0x46524 +#define _CLKGATE_DIS_PSL_C 0x46528 +#define DPF_GATING_DIS (1 << 10) +#define DPF_RAM_GATING_DIS (1 << 9) +#define DPFR_GATING_DIS (1 << 8) + +#define CLKGATE_DIS_PSL(pipe) \ + _MMIO_PIPE(pipe, _CLKGATE_DIS_PSL_A, _CLKGATE_DIS_PSL_B) + /* * GEN10 clock gating regs */ @@ -4047,7 +4068,7 @@ enum { #define EDP_PSR2_FRAME_BEFORE_SU_SHIFT 4 #define EDP_PSR2_FRAME_BEFORE_SU_MASK (0xf<<4) #define EDP_PSR2_IDLE_MASK 0xf -#define EDP_FRAMES_BEFORE_SU_ENTRY (1<<4) +#define EDP_PSR2_FRAME_BEFORE_SU(a) ((a)<<4) #define EDP_PSR2_STATUS_CTL _MMIO(0x6f940) #define EDP_PSR2_STATUS_STATE_MASK (0xf<<28) @@ -5221,7 +5242,7 @@ enum { #define DP_AUX_CH_CTL_TIME_OUT_400us (0 << 26) #define DP_AUX_CH_CTL_TIME_OUT_600us (1 << 26) #define DP_AUX_CH_CTL_TIME_OUT_800us (2 << 26) -#define DP_AUX_CH_CTL_TIME_OUT_1600us (3 << 26) +#define DP_AUX_CH_CTL_TIME_OUT_MAX (3 << 26) /* Varies per platform */ #define DP_AUX_CH_CTL_TIME_OUT_MASK (3 << 26) #define DP_AUX_CH_CTL_RECEIVE_ERROR (1 << 25) #define DP_AUX_CH_CTL_MESSAGE_SIZE_MASK (0x1f << 20) @@ -5663,8 +5684,7 @@ enum { #define CBR_PWM_CLOCK_MUX_SELECT (1<<30) #define CBR4_VLV _MMIO(VLV_DISPLAY_BASE + 0x70450) -#define CBR_DPLLBMD_PIPE_C (1<<29) -#define CBR_DPLLBMD_PIPE_B (1<<18) +#define CBR_DPLLBMD_PIPE(pipe) (1<<(7+(pipe)*11)) /* pipes B and C */ /* FIFO watermark sizes etc */ #define G4X_FIFO_LINE_SIZE 64 @@ -6913,7 +6933,7 @@ enum { # define CHICKEN3_DGMG_DONE_FIX_DISABLE (1 << 2) #define CHICKEN_PAR1_1 _MMIO(0x42080) -#define SKL_RC_HASH_OUTSIDE (1 << 15) +#define SKL_DE_COMPRESSED_HASH_MODE (1 << 15) #define DPA_MASK_VBLANK_SRD (1 << 15) #define FORCE_ARB_IDLE_PLANES (1 << 14) #define SKL_EDP_PSR_FIX_RDWRAP (1 << 3) @@ -6949,6 +6969,7 @@ enum { #define DISP_FBC_WM_DIS (1<<15) #define DISP_ARB_CTL2 _MMIO(0x45004) #define DISP_DATA_PARTITION_5_6 (1<<6) +#define DISP_IPC_ENABLE (1<<3) #define DBUF_CTL _MMIO(0x45008) #define DBUF_POWER_REQUEST (1<<31) #define DBUF_POWER_STATE (1<<30) @@ -6984,12 +7005,19 @@ enum { #define GEN9_CS_DEBUG_MODE1 _MMIO(0x20ec) #define GEN9_CTX_PREEMPT_REG _MMIO(0x2248) #define GEN8_CS_CHICKEN1 _MMIO(0x2580) +#define GEN9_PREEMPT_3D_OBJECT_LEVEL (1<<0) +#define GEN9_PREEMPT_GPGPU_LEVEL(hi, lo) (((hi) << 2) | ((lo) << 1)) +#define GEN9_PREEMPT_GPGPU_MID_THREAD_LEVEL GEN9_PREEMPT_GPGPU_LEVEL(0, 0) +#define GEN9_PREEMPT_GPGPU_THREAD_GROUP_LEVEL GEN9_PREEMPT_GPGPU_LEVEL(0, 1) +#define GEN9_PREEMPT_GPGPU_COMMAND_LEVEL GEN9_PREEMPT_GPGPU_LEVEL(1, 0) +#define GEN9_PREEMPT_GPGPU_LEVEL_MASK GEN9_PREEMPT_GPGPU_LEVEL(1, 1) /* GEN7 chicken */ #define GEN7_COMMON_SLICE_CHICKEN1 _MMIO(0x7010) # define GEN7_CSC1_RHWO_OPT_DISABLE_IN_RCC ((1<<10) | (1<<26)) # define GEN9_RHWO_OPTIMIZATION_DISABLE (1<<14) #define COMMON_SLICE_CHICKEN2 _MMIO(0x7014) +# define GEN9_PBE_COMPRESSED_HASH_SELECTION (1<<13) # define GEN9_DISABLE_GATHER_AT_SET_SHADER_COMMON_SLICE (1<<12) # define GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION (1<<8) # define GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE (1<<0) @@ -7013,6 +7041,7 @@ enum { */ #define L3_GENERAL_PRIO_CREDITS(x) (((x) >> 1) << 19) #define L3_HIGH_PRIO_CREDITS(x) (((x) >> 1) << 14) +#define L3_PRIO_CREDITS_MASK ((0x1f << 19) | (0x1f << 14)) #define GEN7_L3CNTLREG1 _MMIO(0xB01C) #define GEN7_WA_FOR_GEN7_L3_CONTROL 0x3C47FF8C @@ -7154,9 +7183,6 @@ enum { #define SERR_INT _MMIO(0xc4040) #define SERR_INT_POISON (1<<31) -#define SERR_INT_TRANS_C_FIFO_UNDERRUN (1<<6) -#define SERR_INT_TRANS_B_FIFO_UNDERRUN (1<<3) -#define SERR_INT_TRANS_A_FIFO_UNDERRUN (1<<0) #define SERR_INT_TRANS_FIFO_UNDERRUN(pipe) (1<<((pipe)*3)) /* digital port hotplug */ @@ -7469,6 +7495,8 @@ enum { #define FDI_PHASE_SYNC_OVR(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_OVR - ((pipe) * 2))) #define FDI_PHASE_SYNC_EN(pipe) (1<<(FDIA_PHASE_SYNC_SHIFT_EN - ((pipe) * 2))) #define FDI_BC_BIFURCATION_SELECT (1 << 12) +#define CHASSIS_CLK_REQ_DURATION_MASK (0xf << 8) +#define CHASSIS_CLK_REQ_DURATION(x) ((x) << 8) #define SPT_PWM_GRANULARITY (1<<0) #define SOUTH_CHICKEN2 _MMIO(0xc2004) #define FDI_MPHY_IOSFSB_RESET_STATUS (1<<13) @@ -7953,8 +7981,8 @@ enum { #define GEN7_PCODE_TIMEOUT 0x2 #define GEN7_PCODE_ILLEGAL_DATA 0x3 #define GEN7_PCODE_MIN_FREQ_TABLE_GT_RATIO_OUT_OF_RANGE 0x10 -#define GEN6_PCODE_WRITE_RC6VIDS 0x4 -#define GEN6_PCODE_READ_RC6VIDS 0x5 +#define GEN6_PCODE_WRITE_RC6VIDS 0x4 +#define GEN6_PCODE_READ_RC6VIDS 0x5 #define GEN6_ENCODE_RC6_VID(mv) (((mv) - 245) / 5) #define GEN6_DECODE_RC6_VID(vids) (((vids) * 5) + 245) #define BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ 0x18 @@ -7973,7 +8001,9 @@ enum { #define GEN6_PCODE_WRITE_D_COMP 0x11 #define HSW_PCODE_DE_WRITE_FREQ_REQ 0x17 #define DISPLAY_IPS_CONTROL 0x19 -#define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A + /* See also IPS_CTL */ +#define IPS_PCODE_CONTROL (1 << 30) +#define HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL 0x1A #define GEN9_PCODE_SAGV_CONTROL 0x21 #define GEN9_SAGV_DISABLE 0x0 #define GEN9_SAGV_IS_DISABLED 0x1 @@ -8082,6 +8112,7 @@ enum { #define GEN8_SAMPLER_POWER_BYPASS_DIS (1<<1) #define GEN9_HALF_SLICE_CHICKEN7 _MMIO(0xe194) +#define GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR (1<<8) #define GEN9_ENABLE_YV12_BUGFIX (1<<4) #define GEN9_ENABLE_GPGPU_PREEMPTION (1<<2) @@ -8594,7 +8625,7 @@ enum skl_power_gate { #define DPLL_CFGCR0_LINK_RATE_3240 (6 << 25) #define DPLL_CFGCR0_LINK_RATE_4050 (7 << 25) #define DPLL_CFGCR0_DCO_FRACTION_MASK (0x7fff << 10) -#define DPLL_CFGCR0_DCO_FRAC_SHIFT (10) +#define DPLL_CFGCR0_DCO_FRACTION_SHIFT (10) #define DPLL_CFGCR0_DCO_FRACTION(x) ((x) << 10) #define DPLL_CFGCR0_DCO_INTEGER_MASK (0x3ff) #define CNL_DPLL_CFGCR0(pll) _MMIO_PLL(pll, _CNL_DPLL0_CFGCR0, _CNL_DPLL1_CFGCR0) @@ -8801,6 +8832,15 @@ enum skl_power_gate { #define MIPIO_TXESC_CLK_DIV2 _MMIO(0x160008) #define GLK_TX_ESC_CLK_DIV2_MASK 0x3FF +/* Gen4+ Timestamp and Pipe Frame time stamp registers */ +#define GEN4_TIMESTAMP _MMIO(0x2358) +#define ILK_TIMESTAMP_HI _MMIO(0x70070) +#define IVB_TIMESTAMP_CTR _MMIO(0x44070) + +#define _PIPE_FRMTMSTMP_A 0x70048 +#define PIPE_FRMTMSTMP(pipe) \ + _MMIO_PIPE2(pipe, _PIPE_FRMTMSTMP_A) + /* BXT MIPI clock controls */ #define BXT_MAX_VAR_OUTPUT_KHZ 39500 @@ -9382,4 +9422,8 @@ enum skl_power_gate { #define GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_SKL 0x67F1427F /* " " */ #define GEN9_L3_LRA_1_GPGPU_DEFAULT_VALUE_BXT 0x5FF101FF /* " " */ +#define MMCD_MISC_CTRL _MMIO(0x4ddc) /* skl+ */ +#define MMCD_PCLA (1 << 31) +#define MMCD_HOTSPOT_EN (1 << 27) + #endif /* _I915_REG_H_ */ diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 5c86925a0294..8f3aa4dc0c98 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -108,8 +108,6 @@ int i915_restore_state(struct drm_i915_private *dev_priv) mutex_lock(&dev_priv->drm.struct_mutex); - i915_gem_restore_fences(dev_priv); - if (IS_GEN4(dev_priv)) pci_write_config_word(pdev, GCDGMBUS, dev_priv->regfile.saveGCDGMBUS); diff --git a/drivers/gpu/drm/i915/i915_sw_fence.c b/drivers/gpu/drm/i915/i915_sw_fence.c index f29540f922af..e8ca67a129d2 100644 --- a/drivers/gpu/drm/i915/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/i915_sw_fence.c @@ -9,6 +9,7 @@ #include <linux/slab.h> #include <linux/dma-fence.h> +#include <linux/irq_work.h> #include <linux/reservation.h> #include "i915_sw_fence.h" @@ -40,6 +41,11 @@ static inline void debug_fence_init(struct i915_sw_fence *fence) debug_object_init(fence, &i915_sw_fence_debug_descr); } +static inline void debug_fence_init_onstack(struct i915_sw_fence *fence) +{ + debug_object_init_on_stack(fence, &i915_sw_fence_debug_descr); +} + static inline void debug_fence_activate(struct i915_sw_fence *fence) { debug_object_activate(fence, &i915_sw_fence_debug_descr); @@ -78,6 +84,10 @@ static inline void debug_fence_init(struct i915_sw_fence *fence) { } +static inline void debug_fence_init_onstack(struct i915_sw_fence *fence) +{ +} + static inline void debug_fence_activate(struct i915_sw_fence *fence) { } @@ -356,31 +366,44 @@ struct i915_sw_dma_fence_cb { struct i915_sw_fence *fence; struct dma_fence *dma; struct timer_list timer; + struct irq_work work; }; -static void timer_i915_sw_fence_wake(unsigned long data) +static void timer_i915_sw_fence_wake(struct timer_list *t) { - struct i915_sw_dma_fence_cb *cb = (struct i915_sw_dma_fence_cb *)data; + struct i915_sw_dma_fence_cb *cb = from_timer(cb, t, timer); + struct i915_sw_fence *fence; + + fence = xchg(&cb->fence, NULL); + if (!fence) + return; pr_warn("asynchronous wait on fence %s:%s:%x timed out\n", cb->dma->ops->get_driver_name(cb->dma), cb->dma->ops->get_timeline_name(cb->dma), cb->dma->seqno); - dma_fence_put(cb->dma); - cb->dma = NULL; - i915_sw_fence_complete(cb->fence); - cb->timer.function = NULL; + i915_sw_fence_complete(fence); } static void dma_i915_sw_fence_wake(struct dma_fence *dma, struct dma_fence_cb *data) { struct i915_sw_dma_fence_cb *cb = container_of(data, typeof(*cb), base); + struct i915_sw_fence *fence; + + fence = xchg(&cb->fence, NULL); + if (fence) + i915_sw_fence_complete(fence); + + irq_work_queue(&cb->work); +} + +static void irq_i915_sw_fence_work(struct irq_work *wrk) +{ + struct i915_sw_dma_fence_cb *cb = container_of(wrk, typeof(*cb), work); del_timer_sync(&cb->timer); - if (cb->timer.function) - i915_sw_fence_complete(cb->fence); dma_fence_put(cb->dma); kfree(cb); @@ -411,9 +434,8 @@ int i915_sw_fence_await_dma_fence(struct i915_sw_fence *fence, i915_sw_fence_await(fence); cb->dma = NULL; - __setup_timer(&cb->timer, - timer_i915_sw_fence_wake, (unsigned long)cb, - TIMER_IRQSAFE); + timer_setup(&cb->timer, timer_i915_sw_fence_wake, TIMER_IRQSAFE); + init_irq_work(&cb->work, irq_i915_sw_fence_work); if (timeout) { cb->dma = dma_fence_get(dma); mod_timer(&cb->timer, round_jiffies_up(jiffies + timeout)); @@ -492,5 +514,6 @@ int i915_sw_fence_await_reservation(struct i915_sw_fence *fence, } #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) +#include "selftests/lib_sw_fence.c" #include "selftests/i915_sw_fence.c" #endif diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index d61c8727f756..791759f632e1 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -49,7 +49,7 @@ static u32 calc_residency(struct drm_i915_private *dev_priv, static ssize_t show_rc6_mask(struct device *kdev, struct device_attribute *attr, char *buf) { - return snprintf(buf, PAGE_SIZE, "%x\n", intel_enable_rc6()); + return snprintf(buf, PAGE_SIZE, "%x\n", intel_rc6_enabled()); } static ssize_t @@ -246,7 +246,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev, intel_runtime_pm_get(dev_priv); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { u32 freq; freq = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); @@ -261,7 +261,7 @@ static ssize_t gt_act_freq_mhz_show(struct device *kdev, ret = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; ret = intel_gpu_freq(dev_priv, ret); } - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); intel_runtime_pm_put(dev_priv); @@ -275,7 +275,7 @@ static ssize_t gt_cur_freq_mhz_show(struct device *kdev, return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, - dev_priv->rps.cur_freq)); + dev_priv->gt_pm.rps.cur_freq)); } static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) @@ -284,7 +284,7 @@ static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribu return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, - dev_priv->rps.boost_freq)); + dev_priv->gt_pm.rps.boost_freq)); } static ssize_t gt_boost_freq_mhz_store(struct device *kdev, @@ -292,6 +292,7 @@ static ssize_t gt_boost_freq_mhz_store(struct device *kdev, const char *buf, size_t count) { struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 val; ssize_t ret; @@ -301,12 +302,12 @@ static ssize_t gt_boost_freq_mhz_store(struct device *kdev, /* Validate against (static) hardware limits */ val = intel_freq_opcode(dev_priv, val); - if (val < dev_priv->rps.min_freq || val > dev_priv->rps.max_freq) + if (val < rps->min_freq || val > rps->max_freq) return -EINVAL; - mutex_lock(&dev_priv->rps.hw_lock); - dev_priv->rps.boost_freq = val; - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); + rps->boost_freq = val; + mutex_unlock(&dev_priv->pcu_lock); return count; } @@ -318,7 +319,7 @@ static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, - dev_priv->rps.efficient_freq)); + dev_priv->gt_pm.rps.efficient_freq)); } static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) @@ -327,7 +328,7 @@ static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, - dev_priv->rps.max_freq_softlimit)); + dev_priv->gt_pm.rps.max_freq_softlimit)); } static ssize_t gt_max_freq_mhz_store(struct device *kdev, @@ -335,6 +336,7 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, const char *buf, size_t count) { struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 val; ssize_t ret; @@ -344,34 +346,34 @@ static ssize_t gt_max_freq_mhz_store(struct device *kdev, intel_runtime_pm_get(dev_priv); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); val = intel_freq_opcode(dev_priv, val); - if (val < dev_priv->rps.min_freq || - val > dev_priv->rps.max_freq || - val < dev_priv->rps.min_freq_softlimit) { - mutex_unlock(&dev_priv->rps.hw_lock); + if (val < rps->min_freq || + val > rps->max_freq || + val < rps->min_freq_softlimit) { + mutex_unlock(&dev_priv->pcu_lock); intel_runtime_pm_put(dev_priv); return -EINVAL; } - if (val > dev_priv->rps.rp0_freq) + if (val > rps->rp0_freq) DRM_DEBUG("User requested overclocking to %d\n", intel_gpu_freq(dev_priv, val)); - dev_priv->rps.max_freq_softlimit = val; + rps->max_freq_softlimit = val; - val = clamp_t(int, dev_priv->rps.cur_freq, - dev_priv->rps.min_freq_softlimit, - dev_priv->rps.max_freq_softlimit); + val = clamp_t(int, rps->cur_freq, + rps->min_freq_softlimit, + rps->max_freq_softlimit); /* We still need *_set_rps to process the new max_delay and * update the interrupt limits and PMINTRMSK even though * frequency request may be unchanged. */ ret = intel_set_rps(dev_priv, val); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); intel_runtime_pm_put(dev_priv); @@ -384,7 +386,7 @@ static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute return snprintf(buf, PAGE_SIZE, "%d\n", intel_gpu_freq(dev_priv, - dev_priv->rps.min_freq_softlimit)); + dev_priv->gt_pm.rps.min_freq_softlimit)); } static ssize_t gt_min_freq_mhz_store(struct device *kdev, @@ -392,6 +394,7 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, const char *buf, size_t count) { struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 val; ssize_t ret; @@ -401,30 +404,30 @@ static ssize_t gt_min_freq_mhz_store(struct device *kdev, intel_runtime_pm_get(dev_priv); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); val = intel_freq_opcode(dev_priv, val); - if (val < dev_priv->rps.min_freq || - val > dev_priv->rps.max_freq || - val > dev_priv->rps.max_freq_softlimit) { - mutex_unlock(&dev_priv->rps.hw_lock); + if (val < rps->min_freq || + val > rps->max_freq || + val > rps->max_freq_softlimit) { + mutex_unlock(&dev_priv->pcu_lock); intel_runtime_pm_put(dev_priv); return -EINVAL; } - dev_priv->rps.min_freq_softlimit = val; + rps->min_freq_softlimit = val; - val = clamp_t(int, dev_priv->rps.cur_freq, - dev_priv->rps.min_freq_softlimit, - dev_priv->rps.max_freq_softlimit); + val = clamp_t(int, rps->cur_freq, + rps->min_freq_softlimit, + rps->max_freq_softlimit); /* We still need *_set_rps to process the new min_delay and * update the interrupt limits and PMINTRMSK even though * frequency request may be unchanged. */ ret = intel_set_rps(dev_priv, val); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); intel_runtime_pm_put(dev_priv); @@ -448,14 +451,15 @@ static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) { struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 val; if (attr == &dev_attr_gt_RP0_freq_mhz) - val = intel_gpu_freq(dev_priv, dev_priv->rps.rp0_freq); + val = intel_gpu_freq(dev_priv, rps->rp0_freq); else if (attr == &dev_attr_gt_RP1_freq_mhz) - val = intel_gpu_freq(dev_priv, dev_priv->rps.rp1_freq); + val = intel_gpu_freq(dev_priv, rps->rp1_freq); else if (attr == &dev_attr_gt_RPn_freq_mhz) - val = intel_gpu_freq(dev_priv, dev_priv->rps.min_freq); + val = intel_gpu_freq(dev_priv, rps->min_freq); else BUG(); diff --git a/drivers/gpu/drm/i915/i915_trace.h b/drivers/gpu/drm/i915/i915_trace.h index 92f4c5bb7aa7..9cab91ddeb79 100644 --- a/drivers/gpu/drm/i915/i915_trace.h +++ b/drivers/gpu/drm/i915/i915_trace.h @@ -345,7 +345,7 @@ TRACE_EVENT(i915_gem_object_create, TP_STRUCT__entry( __field(struct drm_i915_gem_object *, obj) - __field(u32, size) + __field(u64, size) ), TP_fast_assign( @@ -353,7 +353,7 @@ TRACE_EVENT(i915_gem_object_create, __entry->size = obj->base.size; ), - TP_printk("obj=%p, size=%u", __entry->obj, __entry->size) + TP_printk("obj=%p, size=0x%llx", __entry->obj, __entry->size) ); TRACE_EVENT(i915_gem_shrink, @@ -384,7 +384,7 @@ TRACE_EVENT(i915_vma_bind, __field(struct drm_i915_gem_object *, obj) __field(struct i915_address_space *, vm) __field(u64, offset) - __field(u32, size) + __field(u64, size) __field(unsigned, flags) ), @@ -396,7 +396,7 @@ TRACE_EVENT(i915_vma_bind, __entry->flags = flags; ), - TP_printk("obj=%p, offset=%016llx size=%x%s vm=%p", + TP_printk("obj=%p, offset=0x%016llx size=0x%llx%s vm=%p", __entry->obj, __entry->offset, __entry->size, __entry->flags & PIN_MAPPABLE ? ", mappable" : "", __entry->vm) @@ -410,7 +410,7 @@ TRACE_EVENT(i915_vma_unbind, __field(struct drm_i915_gem_object *, obj) __field(struct i915_address_space *, vm) __field(u64, offset) - __field(u32, size) + __field(u64, size) ), TP_fast_assign( @@ -420,18 +420,18 @@ TRACE_EVENT(i915_vma_unbind, __entry->size = vma->node.size; ), - TP_printk("obj=%p, offset=%016llx size=%x vm=%p", + TP_printk("obj=%p, offset=0x%016llx size=0x%llx vm=%p", __entry->obj, __entry->offset, __entry->size, __entry->vm) ); TRACE_EVENT(i915_gem_object_pwrite, - TP_PROTO(struct drm_i915_gem_object *obj, u32 offset, u32 len), + TP_PROTO(struct drm_i915_gem_object *obj, u64 offset, u64 len), TP_ARGS(obj, offset, len), TP_STRUCT__entry( __field(struct drm_i915_gem_object *, obj) - __field(u32, offset) - __field(u32, len) + __field(u64, offset) + __field(u64, len) ), TP_fast_assign( @@ -440,18 +440,18 @@ TRACE_EVENT(i915_gem_object_pwrite, __entry->len = len; ), - TP_printk("obj=%p, offset=%u, len=%u", + TP_printk("obj=%p, offset=0x%llx, len=0x%llx", __entry->obj, __entry->offset, __entry->len) ); TRACE_EVENT(i915_gem_object_pread, - TP_PROTO(struct drm_i915_gem_object *obj, u32 offset, u32 len), + TP_PROTO(struct drm_i915_gem_object *obj, u64 offset, u64 len), TP_ARGS(obj, offset, len), TP_STRUCT__entry( __field(struct drm_i915_gem_object *, obj) - __field(u32, offset) - __field(u32, len) + __field(u64, offset) + __field(u64, len) ), TP_fast_assign( @@ -460,17 +460,17 @@ TRACE_EVENT(i915_gem_object_pread, __entry->len = len; ), - TP_printk("obj=%p, offset=%u, len=%u", + TP_printk("obj=%p, offset=0x%llx, len=0x%llx", __entry->obj, __entry->offset, __entry->len) ); TRACE_EVENT(i915_gem_object_fault, - TP_PROTO(struct drm_i915_gem_object *obj, u32 index, bool gtt, bool write), + TP_PROTO(struct drm_i915_gem_object *obj, u64 index, bool gtt, bool write), TP_ARGS(obj, index, gtt, write), TP_STRUCT__entry( __field(struct drm_i915_gem_object *, obj) - __field(u32, index) + __field(u64, index) __field(bool, gtt) __field(bool, write) ), @@ -482,7 +482,7 @@ TRACE_EVENT(i915_gem_object_fault, __entry->write = write; ), - TP_printk("obj=%p, %s index=%u %s", + TP_printk("obj=%p, %s index=%llu %s", __entry->obj, __entry->gtt ? "GTT" : "CPU", __entry->index, @@ -515,14 +515,14 @@ DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy, ); TRACE_EVENT(i915_gem_evict, - TP_PROTO(struct i915_address_space *vm, u32 size, u32 align, unsigned int flags), + TP_PROTO(struct i915_address_space *vm, u64 size, u64 align, unsigned int flags), TP_ARGS(vm, size, align, flags), TP_STRUCT__entry( __field(u32, dev) __field(struct i915_address_space *, vm) - __field(u32, size) - __field(u32, align) + __field(u64, size) + __field(u64, align) __field(unsigned int, flags) ), @@ -534,43 +534,11 @@ TRACE_EVENT(i915_gem_evict, __entry->flags = flags; ), - TP_printk("dev=%d, vm=%p, size=%d, align=%d %s", + TP_printk("dev=%d, vm=%p, size=0x%llx, align=0x%llx %s", __entry->dev, __entry->vm, __entry->size, __entry->align, __entry->flags & PIN_MAPPABLE ? ", mappable" : "") ); -TRACE_EVENT(i915_gem_evict_everything, - TP_PROTO(struct drm_device *dev), - TP_ARGS(dev), - - TP_STRUCT__entry( - __field(u32, dev) - ), - - TP_fast_assign( - __entry->dev = dev->primary->index; - ), - - TP_printk("dev=%d", __entry->dev) -); - -TRACE_EVENT(i915_gem_evict_vm, - TP_PROTO(struct i915_address_space *vm), - TP_ARGS(vm), - - TP_STRUCT__entry( - __field(u32, dev) - __field(struct i915_address_space *, vm) - ), - - TP_fast_assign( - __entry->dev = vm->i915->drm.primary->index; - __entry->vm = vm; - ), - - TP_printk("dev=%d, vm=%p", __entry->dev, __entry->vm) -); - TRACE_EVENT(i915_gem_evict_node, TP_PROTO(struct i915_address_space *vm, struct drm_mm_node *node, unsigned int flags), TP_ARGS(vm, node, flags), @@ -593,12 +561,29 @@ TRACE_EVENT(i915_gem_evict_node, __entry->flags = flags; ), - TP_printk("dev=%d, vm=%p, start=%llx size=%llx, color=%lx, flags=%x", + TP_printk("dev=%d, vm=%p, start=0x%llx size=0x%llx, color=0x%lx, flags=%x", __entry->dev, __entry->vm, __entry->start, __entry->size, __entry->color, __entry->flags) ); +TRACE_EVENT(i915_gem_evict_vm, + TP_PROTO(struct i915_address_space *vm), + TP_ARGS(vm), + + TP_STRUCT__entry( + __field(u32, dev) + __field(struct i915_address_space *, vm) + ), + + TP_fast_assign( + __entry->dev = vm->i915->drm.primary->index; + __entry->vm = vm; + ), + + TP_printk("dev=%d, vm=%p", __entry->dev, __entry->vm) +); + TRACE_EVENT(i915_gem_ring_sync_to, TP_PROTO(struct drm_i915_gem_request *to, struct drm_i915_gem_request *from), @@ -649,29 +634,6 @@ TRACE_EVENT(i915_gem_request_queue, __entry->flags) ); -TRACE_EVENT(i915_gem_ring_flush, - TP_PROTO(struct drm_i915_gem_request *req, u32 invalidate, u32 flush), - TP_ARGS(req, invalidate, flush), - - TP_STRUCT__entry( - __field(u32, dev) - __field(u32, ring) - __field(u32, invalidate) - __field(u32, flush) - ), - - TP_fast_assign( - __entry->dev = req->i915->drm.primary->index; - __entry->ring = req->engine->id; - __entry->invalidate = invalidate; - __entry->flush = flush; - ), - - TP_printk("dev=%u, ring=%x, invalidate=%04x, flush=%04x", - __entry->dev, __entry->ring, - __entry->invalidate, __entry->flush) -); - DECLARE_EVENT_CLASS(i915_gem_request, TP_PROTO(struct drm_i915_gem_request *req), TP_ARGS(req), diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 12fc250b47b9..af3d7cc53fa1 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -99,6 +99,11 @@ __T; \ }) +static inline u64 ptr_to_u64(const void *ptr) +{ + return (uintptr_t)ptr; +} + #define u64_to_ptr(T, x) ({ \ typecheck(u64, x); \ (T *)(uintptr_t)(x); \ @@ -119,4 +124,17 @@ static inline void __list_del_many(struct list_head *head, WRITE_ONCE(head->next, first); } +/* + * Wait until the work is finally complete, even if it tries to postpone + * by requeueing itself. Note, that if the worker never cancels itself, + * we will spin forever. + */ +static inline void drain_delayed_work(struct delayed_work *dw) +{ + do { + while (flush_delayed_work(dw)) + ; + } while (delayed_work_pending(dw)); +} + #endif /* !__I915_UTILS_H */ diff --git a/drivers/gpu/drm/i915/i915_vgpu.h b/drivers/gpu/drm/i915/i915_vgpu.h index b72bd2956b70..bb8338450dc1 100644 --- a/drivers/gpu/drm/i915/i915_vgpu.h +++ b/drivers/gpu/drm/i915/i915_vgpu.h @@ -30,6 +30,12 @@ void i915_check_vgpu(struct drm_i915_private *dev_priv); bool intel_vgpu_has_full_48bit_ppgtt(struct drm_i915_private *dev_priv); +static inline bool +intel_vgpu_has_hwsp_emulation(struct drm_i915_private *dev_priv) +{ + return dev_priv->vgpu.caps & VGT_CAPS_HWSP_EMULATION; +} + int intel_vgt_balloon(struct drm_i915_private *dev_priv); void intel_vgt_deballoon(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 02d1a5eacb00..fbfab2f33023 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -54,12 +54,21 @@ i915_vma_retire(struct i915_gem_active *active, if (--obj->active_count) return; + /* Prune the shared fence arrays iff completely idle (inc. external) */ + if (reservation_object_trylock(obj->resv)) { + if (reservation_object_test_signaled_rcu(obj->resv, true)) + reservation_object_add_excl_fence(obj->resv, NULL); + reservation_object_unlock(obj->resv); + } + /* Bump our place on the bound list to keep it roughly in LRU order * so that we don't steal from recently used but inactive objects * (unless we are forced to ofc!) */ + spin_lock(&rq->i915->mm.obj_lock); if (obj->bind_count) - list_move_tail(&obj->global_link, &rq->i915->mm.bound_list); + list_move_tail(&obj->mm.link, &rq->i915->mm.bound_list); + spin_unlock(&rq->i915->mm.obj_lock); obj->mm.dirty = true; /* be paranoid */ @@ -266,6 +275,8 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, if (bind_flags == 0) return 0; + GEM_BUG_ON(!vma->pages); + trace_i915_vma_bind(vma, bind_flags); ret = vma->vm->bind_vma(vma, cache_level, bind_flags); if (ret) @@ -278,13 +289,16 @@ int i915_vma_bind(struct i915_vma *vma, enum i915_cache_level cache_level, void __iomem *i915_vma_pin_iomap(struct i915_vma *vma) { void __iomem *ptr; + int err; /* Access through the GTT requires the device to be awake. */ assert_rpm_wakelock_held(vma->vm->i915); lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); - if (WARN_ON(!i915_vma_is_map_and_fenceable(vma))) - return IO_ERR_PTR(-ENODEV); + if (WARN_ON(!i915_vma_is_map_and_fenceable(vma))) { + err = -ENODEV; + goto err; + } GEM_BUG_ON(!i915_vma_is_ggtt(vma)); GEM_BUG_ON((vma->flags & I915_VMA_GLOBAL_BIND) == 0); @@ -294,14 +308,36 @@ void __iomem *i915_vma_pin_iomap(struct i915_vma *vma) ptr = io_mapping_map_wc(&i915_vm_to_ggtt(vma->vm)->mappable, vma->node.start, vma->node.size); - if (ptr == NULL) - return IO_ERR_PTR(-ENOMEM); + if (ptr == NULL) { + err = -ENOMEM; + goto err; + } vma->iomap = ptr; } __i915_vma_pin(vma); + + err = i915_vma_pin_fence(vma); + if (err) + goto err_unpin; + return ptr; + +err_unpin: + __i915_vma_unpin(vma); +err: + return IO_ERR_PTR(err); +} + +void i915_vma_unpin_iomap(struct i915_vma *vma) +{ + lockdep_assert_held(&vma->obj->base.dev->struct_mutex); + + GEM_BUG_ON(vma->iomap == NULL); + + i915_vma_unpin_fence(vma); + i915_vma_unpin(vma); } void i915_vma_unpin_and_release(struct i915_vma **p_vma) @@ -471,25 +507,64 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) if (ret) return ret; + GEM_BUG_ON(vma->pages); + + ret = vma->vm->set_pages(vma); + if (ret) + goto err_unpin; + if (flags & PIN_OFFSET_FIXED) { u64 offset = flags & PIN_OFFSET_MASK; if (!IS_ALIGNED(offset, alignment) || range_overflows(offset, size, end)) { ret = -EINVAL; - goto err_unpin; + goto err_clear; } ret = i915_gem_gtt_reserve(vma->vm, &vma->node, size, offset, obj->cache_level, flags); if (ret) - goto err_unpin; + goto err_clear; } else { + /* + * We only support huge gtt pages through the 48b PPGTT, + * however we also don't want to force any alignment for + * objects which need to be tightly packed into the low 32bits. + * + * Note that we assume that GGTT are limited to 4GiB for the + * forseeable future. See also i915_ggtt_offset(). + */ + if (upper_32_bits(end - 1) && + vma->page_sizes.sg > I915_GTT_PAGE_SIZE) { + /* + * We can't mix 64K and 4K PTEs in the same page-table + * (2M block), and so to avoid the ugliness and + * complexity of coloring we opt for just aligning 64K + * objects to 2M. + */ + u64 page_alignment = + rounddown_pow_of_two(vma->page_sizes.sg | + I915_GTT_PAGE_SIZE_2M); + + /* + * Check we don't expand for the limited Global GTT + * (mappable aperture is even more precious!). This + * also checks that we exclude the aliasing-ppgtt. + */ + GEM_BUG_ON(i915_vma_is_ggtt(vma)); + + alignment = max(alignment, page_alignment); + + if (vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) + size = round_up(size, I915_GTT_PAGE_SIZE_2M); + } + ret = i915_gem_gtt_insert(vma->vm, &vma->node, size, alignment, obj->cache_level, start, end, flags); if (ret) - goto err_unpin; + goto err_clear; GEM_BUG_ON(vma->node.start < start); GEM_BUG_ON(vma->node.start + vma->node.size > end); @@ -497,13 +572,19 @@ i915_vma_insert(struct i915_vma *vma, u64 size, u64 alignment, u64 flags) GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, obj->cache_level)); - list_move_tail(&obj->global_link, &dev_priv->mm.bound_list); list_move_tail(&vma->vm_link, &vma->vm->inactive_list); + + spin_lock(&dev_priv->mm.obj_lock); + list_move_tail(&obj->mm.link, &dev_priv->mm.bound_list); obj->bind_count++; + spin_unlock(&dev_priv->mm.obj_lock); + GEM_BUG_ON(atomic_read(&obj->mm.pages_pin_count) < obj->bind_count); return 0; +err_clear: + vma->vm->clear_pages(vma); err_unpin: i915_gem_object_unpin_pages(obj); return ret; @@ -512,20 +593,24 @@ err_unpin: static void i915_vma_remove(struct i915_vma *vma) { + struct drm_i915_private *i915 = vma->vm->i915; struct drm_i915_gem_object *obj = vma->obj; GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); GEM_BUG_ON(vma->flags & (I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND)); + vma->vm->clear_pages(vma); + drm_mm_remove_node(&vma->node); list_move_tail(&vma->vm_link, &vma->vm->unbound_list); /* Since the unbound list is global, only move to that list if * no more VMAs exist. */ + spin_lock(&i915->mm.obj_lock); if (--obj->bind_count == 0) - list_move_tail(&obj->global_link, - &to_i915(obj->base.dev)->mm.unbound_list); + list_move_tail(&obj->mm.link, &i915->mm.unbound_list); + spin_unlock(&i915->mm.obj_lock); /* And finally now the object is completely decoupled from this vma, * we can drop its hold on the backing storage and allow it to be @@ -569,8 +654,8 @@ int __i915_vma_do_pin(struct i915_vma *vma, err_remove: if ((bound & I915_VMA_BIND_MASK) == 0) { - GEM_BUG_ON(vma->pages); i915_vma_remove(vma); + GEM_BUG_ON(vma->pages); } err_unpin: __i915_vma_unpin(vma); @@ -620,6 +705,30 @@ static void __i915_vma_iounmap(struct i915_vma *vma) vma->iomap = NULL; } +void i915_vma_revoke_mmap(struct i915_vma *vma) +{ + struct drm_vma_offset_node *node = &vma->obj->base.vma_node; + u64 vma_offset; + + lockdep_assert_held(&vma->vm->i915->drm.struct_mutex); + + if (!i915_vma_has_userfault(vma)) + return; + + GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma)); + GEM_BUG_ON(!vma->obj->userfault_count); + + vma_offset = vma->ggtt_view.partial.offset << PAGE_SHIFT; + unmap_mapping_range(vma->vm->i915->drm.anon_inode->i_mapping, + drm_vma_node_offset_addr(node) + vma_offset, + vma->size, + 1); + + i915_vma_unset_userfault(vma); + if (!--vma->obj->userfault_count) + list_del(&vma->obj->userfault_link); +} + int i915_vma_unbind(struct i915_vma *vma) { struct drm_i915_gem_object *obj = vma->obj; @@ -683,11 +792,13 @@ int i915_vma_unbind(struct i915_vma *vma) return ret; /* Force a pagefault for domain tracking on next user access */ - i915_gem_release_mmap(obj); + i915_vma_revoke_mmap(vma); __i915_vma_iounmap(vma); vma->flags &= ~I915_VMA_CAN_FENCE; } + GEM_BUG_ON(vma->fence); + GEM_BUG_ON(i915_vma_has_userfault(vma)); if (likely(!vma->vm->closed)) { trace_i915_vma_unbind(vma); @@ -695,13 +806,6 @@ int i915_vma_unbind(struct i915_vma *vma) } vma->flags &= ~(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND); - if (vma->pages != obj->mm.pages) { - GEM_BUG_ON(!vma->pages); - sg_free_table(vma->pages); - kfree(vma->pages); - } - vma->pages = NULL; - i915_vma_remove(vma); destroy: diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index e811067c7724..1e2bc9b3c3ac 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -55,6 +55,7 @@ struct i915_vma { void __iomem *iomap; u64 size; u64 display_alignment; + struct i915_page_sizes page_sizes; u32 fence_size; u32 fence_alignment; @@ -65,7 +66,7 @@ struct i915_vma { * that exist in the ctx->handle_vmas LUT for this vma. */ unsigned int open_count; - unsigned int flags; + unsigned long flags; /** * How many users have pinned this object in GTT space. The following * users can each hold at most one reference: pwrite/pread, execbuffer @@ -87,6 +88,8 @@ struct i915_vma { #define I915_VMA_GGTT BIT(8) #define I915_VMA_CAN_FENCE BIT(9) #define I915_VMA_CLOSED BIT(10) +#define I915_VMA_USERFAULT_BIT 11 +#define I915_VMA_USERFAULT BIT(I915_VMA_USERFAULT_BIT) unsigned int active; struct i915_gem_active last_read[I915_NUM_ENGINES]; @@ -145,6 +148,22 @@ static inline bool i915_vma_is_closed(const struct i915_vma *vma) return vma->flags & I915_VMA_CLOSED; } +static inline bool i915_vma_set_userfault(struct i915_vma *vma) +{ + GEM_BUG_ON(!i915_vma_is_map_and_fenceable(vma)); + return __test_and_set_bit(I915_VMA_USERFAULT_BIT, &vma->flags); +} + +static inline void i915_vma_unset_userfault(struct i915_vma *vma) +{ + return __clear_bit(I915_VMA_USERFAULT_BIT, &vma->flags); +} + +static inline bool i915_vma_has_userfault(const struct i915_vma *vma) +{ + return test_bit(I915_VMA_USERFAULT_BIT, &vma->flags); +} + static inline unsigned int i915_vma_get_active(const struct i915_vma *vma) { return vma->active; @@ -243,6 +262,7 @@ bool i915_gem_valid_gtt_space(struct i915_vma *vma, unsigned long cache_level); bool i915_vma_misplaced(const struct i915_vma *vma, u64 size, u64 alignment, u64 flags); void __i915_vma_set_map_and_fenceable(struct i915_vma *vma); +void i915_vma_revoke_mmap(struct i915_vma *vma); int __must_check i915_vma_unbind(struct i915_vma *vma); void i915_vma_unlink_ctx(struct i915_vma *vma); void i915_vma_close(struct i915_vma *vma); @@ -321,12 +341,7 @@ void __iomem *i915_vma_pin_iomap(struct i915_vma *vma); * Callers must hold the struct_mutex. This function is only valid to be * called on a VMA previously iomapped by the caller with i915_vma_pin_iomap(). */ -static inline void i915_vma_unpin_iomap(struct i915_vma *vma) -{ - lockdep_assert_held(&vma->obj->base.dev->struct_mutex); - GEM_BUG_ON(vma->iomap == NULL); - i915_vma_unpin(vma); -} +void i915_vma_unpin_iomap(struct i915_vma *vma); static inline struct page *i915_vma_first_page(struct i915_vma *vma) { @@ -349,15 +364,13 @@ static inline struct page *i915_vma_first_page(struct i915_vma *vma) * * True if the vma has a fence, false otherwise. */ -static inline bool -i915_vma_pin_fence(struct i915_vma *vma) +int i915_vma_pin_fence(struct i915_vma *vma); +int __must_check i915_vma_put_fence(struct i915_vma *vma); + +static inline void __i915_vma_unpin_fence(struct i915_vma *vma) { - lockdep_assert_held(&vma->obj->base.dev->struct_mutex); - if (vma->fence) { - vma->fence->pin_count++; - return true; - } else - return false; + GEM_BUG_ON(vma->fence->pin_count <= 0); + vma->fence->pin_count--; } /** @@ -372,10 +385,8 @@ static inline void i915_vma_unpin_fence(struct i915_vma *vma) { lockdep_assert_held(&vma->obj->base.dev->struct_mutex); - if (vma->fence) { - GEM_BUG_ON(vma->fence->pin_count <= 0); - vma->fence->pin_count--; - } + if (vma->fence) + __i915_vma_unpin_fence(vma); } #endif diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index d805b6e6fe71..0ddba16fde1b 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -606,11 +606,6 @@ void intel_audio_codec_enable(struct intel_encoder *intel_encoder, connector->encoder->base.id, connector->encoder->name); - /* ELD Conn_Type */ - connector->eld[5] &= ~(3 << 2); - if (intel_crtc_has_dp_encoder(crtc_state)) - connector->eld[5] |= (1 << 2); - connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; if (dev_priv->display.audio_codec_enable) @@ -759,7 +754,7 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, { struct intel_encoder *encoder; - if (WARN_ON(pipe >= I915_MAX_PIPES)) + if (WARN_ON(pipe >= INTEL_INFO(dev_priv)->num_pipes)) return NULL; /* MST */ diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 5949750a35ee..fd23023df7c1 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -356,7 +356,7 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv, struct drm_display_mode *panel_fixed_mode; int index; - index = i915.vbt_sdvo_panel_type; + index = i915_modparams.vbt_sdvo_panel_type; if (index == -2) { DRM_DEBUG_KMS("Ignore SDVO panel mode from BIOS VBT tables.\n"); return; @@ -431,27 +431,6 @@ parse_general_features(struct drm_i915_private *dev_priv, dev_priv->vbt.fdi_rx_polarity_inverted); } -static void -parse_general_definitions(struct drm_i915_private *dev_priv, - const struct bdb_header *bdb) -{ - const struct bdb_general_definitions *general; - - general = find_section(bdb, BDB_GENERAL_DEFINITIONS); - if (general) { - u16 block_size = get_blocksize(general); - if (block_size >= sizeof(*general)) { - int bus_pin = general->crt_ddc_gmbus_pin; - DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); - if (intel_gmbus_is_valid_pin(dev_priv, bus_pin)) - dev_priv->vbt.crt_ddc_pin = bus_pin; - } else { - DRM_DEBUG_KMS("BDB_GD too small (%d). Invalid.\n", - block_size); - } - } -} - static const struct child_device_config * child_device_ptr(const struct bdb_general_definitions *defs, int i) { @@ -459,41 +438,24 @@ child_device_ptr(const struct bdb_general_definitions *defs, int i) } static void -parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, - const struct bdb_header *bdb) +parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, u8 bdb_version) { struct sdvo_device_mapping *mapping; - const struct bdb_general_definitions *defs; const struct child_device_config *child; - int i, child_device_num, count; - u16 block_size; - - defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); - if (!defs) { - DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n"); - return; - } + int i, count = 0; /* - * Only parse SDVO mappings when the general definitions block child - * device size matches that of the *legacy* child device config - * struct. Thus, SDVO mapping will be skipped for newer VBT. + * Only parse SDVO mappings on gens that could have SDVO. This isn't + * accurate and doesn't have to be, as long as it's not too strict. */ - if (defs->child_dev_size != LEGACY_CHILD_DEVICE_CONFIG_SIZE) { - DRM_DEBUG_KMS("Unsupported child device size for SDVO mapping.\n"); + if (!IS_GEN(dev_priv, 3, 7)) { + DRM_DEBUG_KMS("Skipping SDVO device mapping\n"); return; } - /* get the block size of general definitions */ - block_size = get_blocksize(defs); - /* get the number of child device */ - child_device_num = (block_size - sizeof(*defs)) / defs->child_dev_size; - count = 0; - for (i = 0; i < child_device_num; i++) { - child = child_device_ptr(defs, i); - if (!child->device_type) { - /* skip the device block if device type is invalid */ - continue; - } + + for (i = 0, count = 0; i < dev_priv->vbt.child_dev_num; i++) { + child = dev_priv->vbt.child_dev + i; + if (child->slave_addr != SLAVE_ADDR1 && child->slave_addr != SLAVE_ADDR2) { /* @@ -544,7 +506,6 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv, /* No SDVO device info is found */ DRM_DEBUG_KMS("No SDVO device info is found in VBT\n"); } - return; } static void @@ -675,8 +636,9 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) uint8_t vswing; /* Don't read from VBT if module parameter has valid value*/ - if (i915.edp_vswing) { - dev_priv->vbt.edp.low_vswing = i915.edp_vswing == 1; + if (i915_modparams.edp_vswing) { + dev_priv->vbt.edp.low_vswing = + i915_modparams.edp_vswing == 1; } else { vswing = (edp->edp_vswing_preemph >> (panel_type * 4)) & 0xF; dev_priv->vbt.edp.low_vswing = vswing == 0; @@ -729,6 +691,48 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) dev_priv->vbt.psr.tp2_tp3_wakeup_time = psr_table->tp2_tp3_wakeup_time; } +static void parse_dsi_backlight_ports(struct drm_i915_private *dev_priv, + u16 version, enum port port) +{ + if (!dev_priv->vbt.dsi.config->dual_link || version < 197) { + dev_priv->vbt.dsi.bl_ports = BIT(port); + if (dev_priv->vbt.dsi.config->cabc_supported) + dev_priv->vbt.dsi.cabc_ports = BIT(port); + + return; + } + + switch (dev_priv->vbt.dsi.config->dl_dcs_backlight_ports) { + case DL_DCS_PORT_A: + dev_priv->vbt.dsi.bl_ports = BIT(PORT_A); + break; + case DL_DCS_PORT_C: + dev_priv->vbt.dsi.bl_ports = BIT(PORT_C); + break; + default: + case DL_DCS_PORT_A_AND_C: + dev_priv->vbt.dsi.bl_ports = BIT(PORT_A) | BIT(PORT_C); + break; + } + + if (!dev_priv->vbt.dsi.config->cabc_supported) + return; + + switch (dev_priv->vbt.dsi.config->dl_dcs_cabc_ports) { + case DL_DCS_PORT_A: + dev_priv->vbt.dsi.cabc_ports = BIT(PORT_A); + break; + case DL_DCS_PORT_C: + dev_priv->vbt.dsi.cabc_ports = BIT(PORT_C); + break; + default: + case DL_DCS_PORT_A_AND_C: + dev_priv->vbt.dsi.cabc_ports = + BIT(PORT_A) | BIT(PORT_C); + break; + } +} + static void parse_mipi_config(struct drm_i915_private *dev_priv, const struct bdb_header *bdb) @@ -737,9 +741,10 @@ parse_mipi_config(struct drm_i915_private *dev_priv, const struct mipi_config *config; const struct mipi_pps_data *pps; int panel_type = dev_priv->vbt.panel_type; + enum port port; /* parse MIPI blocks only if LFP type is MIPI */ - if (!intel_bios_is_dsi_present(dev_priv, NULL)) + if (!intel_bios_is_dsi_present(dev_priv, &port)) return; /* Initialize this to undefined indicating no generic MIPI support */ @@ -780,15 +785,7 @@ parse_mipi_config(struct drm_i915_private *dev_priv, return; } - /* - * These fields are introduced from the VBT version 197 onwards, - * so making sure that these bits are set zero in the previous - * versions. - */ - if (dev_priv->vbt.dsi.config->dual_link && bdb->version < 197) { - dev_priv->vbt.dsi.config->dl_dcs_cabc_ports = 0; - dev_priv->vbt.dsi.config->dl_dcs_backlight_ports = 0; - } + parse_dsi_backlight_ports(dev_priv, bdb->version, port); /* We have mandatory mipi config blocks. Initialize as generic panel */ dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID; @@ -1109,8 +1106,24 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv, } } +static const u8 cnp_ddc_pin_map[] = { + [DDC_BUS_DDI_B] = GMBUS_PIN_1_BXT, + [DDC_BUS_DDI_C] = GMBUS_PIN_2_BXT, + [DDC_BUS_DDI_D] = GMBUS_PIN_4_CNP, /* sic */ + [DDC_BUS_DDI_F] = GMBUS_PIN_3_BXT, /* sic */ +}; + +static u8 map_ddc_pin(struct drm_i915_private *dev_priv, u8 vbt_pin) +{ + if (HAS_PCH_CNP(dev_priv) && + vbt_pin > 0 && vbt_pin < ARRAY_SIZE(cnp_ddc_pin_map)) + return cnp_ddc_pin_map[vbt_pin]; + + return vbt_pin; +} + static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, - const struct bdb_header *bdb) + u8 bdb_version) { struct child_device_config *it, *child = NULL; struct ddi_vbt_port_info *info = &dev_priv->vbt.ddi_port_info[port]; @@ -1162,6 +1175,20 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, is_hdmi = is_dvi && (child->device_type & DEVICE_TYPE_NOT_HDMI_OUTPUT) == 0; is_edp = is_dp && (child->device_type & DEVICE_TYPE_INTERNAL_CONNECTOR); + if (port == PORT_A && is_dvi) { + DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n", + is_hdmi ? "/HDMI" : ""); + is_dvi = false; + is_hdmi = false; + } + + if (port == PORT_A && is_dvi) { + DRM_DEBUG_KMS("VBT claims port A supports DVI%s, ignoring\n", + is_hdmi ? "/HDMI" : ""); + is_dvi = false; + is_hdmi = false; + } + info->supports_dvi = is_dvi; info->supports_hdmi = is_hdmi; info->supports_dp = is_dp; @@ -1187,16 +1214,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, DRM_DEBUG_KMS("Port %c is internal DP\n", port_name(port)); if (is_dvi) { - info->alternate_ddc_pin = ddc_pin; - - /* - * All VBTs that we got so far for B Stepping has this - * information wrong for Port D. So, let's just ignore for now. - */ - if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0) && - port == PORT_D) { - info->alternate_ddc_pin = 0; - } + info->alternate_ddc_pin = map_ddc_pin(dev_priv, ddc_pin); sanitize_ddc_pin(dev_priv, port); } @@ -1207,7 +1225,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, sanitize_aux_ch(dev_priv, port); } - if (bdb->version >= 158) { + if (bdb_version >= 158) { /* The VBT HDMI level shift values match the table we have. */ hdmi_level_shift = child->hdmi_level_shifter_value; DRM_DEBUG_KMS("VBT HDMI level shift for port %c: %d\n", @@ -1217,7 +1235,7 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, } /* Parse the I_boost config for SKL and above */ - if (bdb->version >= 196 && child->iboost) { + if (bdb_version >= 196 && child->iboost) { info->dp_boost_level = translate_iboost(child->dp_iboost_level); DRM_DEBUG_KMS("VBT (e)DP boost level for port %c: %d\n", port_name(port), info->dp_boost_level); @@ -1227,40 +1245,52 @@ static void parse_ddi_port(struct drm_i915_private *dev_priv, enum port port, } } -static void parse_ddi_ports(struct drm_i915_private *dev_priv, - const struct bdb_header *bdb) +static void parse_ddi_ports(struct drm_i915_private *dev_priv, u8 bdb_version) { enum port port; - if (!HAS_DDI(dev_priv)) + if (!HAS_DDI(dev_priv) && !IS_CHERRYVIEW(dev_priv)) return; if (!dev_priv->vbt.child_dev_num) return; - if (bdb->version < 155) + if (bdb_version < 155) return; for (port = PORT_A; port < I915_MAX_PORTS; port++) - parse_ddi_port(dev_priv, port, bdb); + parse_ddi_port(dev_priv, port, bdb_version); } static void -parse_device_mapping(struct drm_i915_private *dev_priv, - const struct bdb_header *bdb) +parse_general_definitions(struct drm_i915_private *dev_priv, + const struct bdb_header *bdb) { const struct bdb_general_definitions *defs; const struct child_device_config *child; - struct child_device_config *child_dev_ptr; int i, child_device_num, count; u8 expected_size; u16 block_size; + int bus_pin; defs = find_section(bdb, BDB_GENERAL_DEFINITIONS); if (!defs) { DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n"); return; } + + block_size = get_blocksize(defs); + if (block_size < sizeof(*defs)) { + DRM_DEBUG_KMS("General definitions block too small (%u)\n", + block_size); + return; + } + + bus_pin = defs->crt_ddc_gmbus_pin; + DRM_DEBUG_KMS("crt_ddc_bus_pin: %d\n", bus_pin); + if (intel_gmbus_is_valid_pin(dev_priv, bus_pin)) + dev_priv->vbt.crt_ddc_pin = bus_pin; + if (bdb->version < 106) { expected_size = 22; } else if (bdb->version < 111) { @@ -1290,18 +1320,14 @@ parse_device_mapping(struct drm_i915_private *dev_priv, return; } - /* get the block size of general definitions */ - block_size = get_blocksize(defs); /* get the number of child device */ child_device_num = (block_size - sizeof(*defs)) / defs->child_dev_size; count = 0; /* get the number of child device that is present */ for (i = 0; i < child_device_num; i++) { child = child_device_ptr(defs, i); - if (!child->device_type) { - /* skip the device block if device type is invalid */ + if (!child->device_type) continue; - } count++; } if (!count) { @@ -1318,36 +1344,18 @@ parse_device_mapping(struct drm_i915_private *dev_priv, count = 0; for (i = 0; i < child_device_num; i++) { child = child_device_ptr(defs, i); - if (!child->device_type) { - /* skip the device block if device type is invalid */ + if (!child->device_type) continue; - } - - child_dev_ptr = dev_priv->vbt.child_dev + count; - count++; /* * Copy as much as we know (sizeof) and is available * (child_dev_size) of the child device. Accessing the data must * depend on VBT version. */ - memcpy(child_dev_ptr, child, + memcpy(dev_priv->vbt.child_dev + count, child, min_t(size_t, defs->child_dev_size, sizeof(*child))); - - /* - * copied full block, now init values when they are not - * available in current version - */ - if (bdb->version < 196) { - /* Set default values for bits added from v196 */ - child_dev_ptr->iboost = 0; - child_dev_ptr->hpd_invert = 0; - } - - if (bdb->version < 192) - child_dev_ptr->lspcon = 0; + count++; } - return; } /* Common defaults which may be overridden by VBT. */ @@ -1528,14 +1536,15 @@ void intel_bios_init(struct drm_i915_private *dev_priv) parse_lfp_panel_data(dev_priv, bdb); parse_lfp_backlight(dev_priv, bdb); parse_sdvo_panel_data(dev_priv, bdb); - parse_sdvo_device_mapping(dev_priv, bdb); - parse_device_mapping(dev_priv, bdb); parse_driver_features(dev_priv, bdb); parse_edp(dev_priv, bdb); parse_psr(dev_priv, bdb); parse_mipi_config(dev_priv, bdb); parse_mipi_sequence(dev_priv, bdb); - parse_ddi_ports(dev_priv, bdb); + + /* Further processing on pre-parsed data */ + parse_sdvo_device_mapping(dev_priv, bdb->version); + parse_ddi_ports(dev_priv, bdb->version); out: if (!vbt) { diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 4e00e5cb9fa1..48e1ba01ccf8 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -64,7 +64,7 @@ static unsigned long wait_timeout(void) static noinline void missed_breadcrumb(struct intel_engine_cs *engine) { - DRM_DEBUG_DRIVER("%s missed breadcrumb at %pF, irq posted? %s, current seqno=%x, last=%x\n", + DRM_DEBUG_DRIVER("%s missed breadcrumb at %pS, irq posted? %s, current seqno=%x, last=%x\n", engine->name, __builtin_return_address(0), yesno(test_bit(ENGINE_IRQ_BREADCRUMB, &engine->irq_posted)), @@ -74,9 +74,10 @@ static noinline void missed_breadcrumb(struct intel_engine_cs *engine) set_bit(engine->id, &engine->i915->gpu_error.missed_irq_rings); } -static void intel_breadcrumbs_hangcheck(unsigned long data) +static void intel_breadcrumbs_hangcheck(struct timer_list *t) { - struct intel_engine_cs *engine = (struct intel_engine_cs *)data; + struct intel_engine_cs *engine = from_timer(engine, t, + breadcrumbs.hangcheck); struct intel_breadcrumbs *b = &engine->breadcrumbs; if (!b->irq_armed) @@ -108,9 +109,10 @@ static void intel_breadcrumbs_hangcheck(unsigned long data) } } -static void intel_breadcrumbs_fake_irq(unsigned long data) +static void intel_breadcrumbs_fake_irq(struct timer_list *t) { - struct intel_engine_cs *engine = (struct intel_engine_cs *)data; + struct intel_engine_cs *engine = from_timer(engine, t, + breadcrumbs.fake_irq); struct intel_breadcrumbs *b = &engine->breadcrumbs; /* The timer persists in case we cannot enable interrupts, @@ -787,12 +789,8 @@ int intel_engine_init_breadcrumbs(struct intel_engine_cs *engine) spin_lock_init(&b->rb_lock); spin_lock_init(&b->irq_lock); - setup_timer(&b->fake_irq, - intel_breadcrumbs_fake_irq, - (unsigned long)engine); - setup_timer(&b->hangcheck, - intel_breadcrumbs_hangcheck, - (unsigned long)engine); + timer_setup(&b->fake_irq, intel_breadcrumbs_fake_irq, 0); + timer_setup(&b->hangcheck, intel_breadcrumbs_hangcheck, 0); /* Spawn a thread to provide a common bottom-half for all signals. * As this is an asynchronous interface we cannot steal the current diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index d32911816fc2..b2a6d62b71c0 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -503,7 +503,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv, else cmd = 0; - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); val &= ~DSPFREQGUAR_MASK; val |= (cmd << DSPFREQGUAR_SHIFT); @@ -513,7 +513,7 @@ static void vlv_set_cdclk(struct drm_i915_private *dev_priv, 50)) { DRM_ERROR("timed out waiting for CDclk change\n"); } - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); mutex_lock(&dev_priv->sb_lock); @@ -590,7 +590,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv, */ cmd = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1; - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); val &= ~DSPFREQGUAR_MASK_CHV; val |= (cmd << DSPFREQGUAR_SHIFT_CHV); @@ -600,7 +600,7 @@ static void chv_set_cdclk(struct drm_i915_private *dev_priv, 50)) { DRM_ERROR("timed out waiting for CDclk change\n"); } - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); intel_update_cdclk(dev_priv); @@ -656,10 +656,10 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv, "trying to change cdclk frequency with cdclk not enabled\n")) return; - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); ret = sandybridge_pcode_write(dev_priv, BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); if (ret) { DRM_ERROR("failed to inform pcode about cdclk change\n"); return; @@ -669,8 +669,12 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv, val |= LCPLL_CD_SOURCE_FCLK; I915_WRITE(LCPLL_CTL, val); + /* + * According to the spec, it should be enough to poll for this 1 us. + * However, extensive testing shows that this can take longer. + */ if (wait_for_us(I915_READ(LCPLL_CTL) & - LCPLL_CD_SOURCE_FCLK_DONE, 1)) + LCPLL_CD_SOURCE_FCLK_DONE, 100)) DRM_ERROR("Switching to FCLK failed\n"); val = I915_READ(LCPLL_CTL); @@ -708,9 +712,9 @@ static void bdw_set_cdclk(struct drm_i915_private *dev_priv, LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1)) DRM_ERROR("Switching back to LCPLL failed\n"); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, data); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); I915_WRITE(CDCLK_FREQ, DIV_ROUND_CLOSEST(cdclk, 1000) - 1); @@ -924,12 +928,12 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, WARN_ON((cdclk == 24000) != (vco == 0)); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL, SKL_CDCLK_PREPARE_FOR_CHANGE, SKL_CDCLK_READY_FOR_CHANGE, SKL_CDCLK_READY_FOR_CHANGE, 3); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); if (ret) { DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n", ret); @@ -971,9 +975,9 @@ static void skl_set_cdclk(struct drm_i915_private *dev_priv, POSTING_READ(CDCLK_CTL); /* inform PCU of the change */ - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); intel_update_cdclk(dev_priv); } @@ -1264,10 +1268,10 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, } /* Inform power controller of upcoming frequency change */ - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, 0x80000000); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); if (ret) { DRM_ERROR("PCode CDCLK freq change notify failed (err %d, freq %d)\n", @@ -1296,10 +1300,10 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE; I915_WRITE(CDCLK_CTL, val); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, DIV_ROUND_UP(cdclk, 25000)); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); if (ret) { DRM_ERROR("PCode CDCLK freq set failed, (err %d, freq %d)\n", @@ -1514,12 +1518,12 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv, u32 val, divider, pcu_ack; int ret; - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); ret = skl_pcode_request(dev_priv, SKL_PCODE_CDCLK_CONTROL, SKL_CDCLK_PREPARE_FOR_CHANGE, SKL_CDCLK_READY_FOR_CHANGE, SKL_CDCLK_READY_FOR_CHANGE, 3); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); if (ret) { DRM_ERROR("Failed to inform PCU about cdclk change (%d)\n", ret); @@ -1571,9 +1575,9 @@ static void cnl_set_cdclk(struct drm_i915_private *dev_priv, I915_WRITE(CDCLK_CTL, val); /* inform PCU of the change */ - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); sandybridge_pcode_write(dev_priv, SKL_PCODE_CDCLK_CONTROL, pcu_ack); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); intel_update_cdclk(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_color.c b/drivers/gpu/drm/i915/intel_color.c index ff9ecd211abb..b8315bca852b 100644 --- a/drivers/gpu/drm/i915/intel_color.c +++ b/drivers/gpu/drm/i915/intel_color.c @@ -74,7 +74,7 @@ #define I9XX_CSC_COEFF_1_0 \ ((7 << 12) | I9XX_CSC_COEFF_FP(CTM_COEFF_1_0, 8)) -static bool crtc_state_is_legacy(struct drm_crtc_state *state) +static bool crtc_state_is_legacy_gamma(struct drm_crtc_state *state) { return !state->degamma_lut && !state->ctm && @@ -288,7 +288,7 @@ static void cherryview_load_csc_matrix(struct drm_crtc_state *state) } mode = (state->ctm ? CGM_PIPE_MODE_CSC : 0); - if (!crtc_state_is_legacy(state)) { + if (!crtc_state_is_legacy_gamma(state)) { mode |= (state->degamma_lut ? CGM_PIPE_MODE_DEGAMMA : 0) | (state->gamma_lut ? CGM_PIPE_MODE_GAMMA : 0); } @@ -469,7 +469,7 @@ static void broadwell_load_luts(struct drm_crtc_state *state) struct intel_crtc_state *intel_state = to_intel_crtc_state(state); enum pipe pipe = to_intel_crtc(state->crtc)->pipe; - if (crtc_state_is_legacy(state)) { + if (crtc_state_is_legacy_gamma(state)) { haswell_load_luts(state); return; } @@ -529,7 +529,7 @@ static void glk_load_luts(struct drm_crtc_state *state) glk_load_degamma_lut(state); - if (crtc_state_is_legacy(state)) { + if (crtc_state_is_legacy_gamma(state)) { haswell_load_luts(state); return; } @@ -551,7 +551,7 @@ static void cherryview_load_luts(struct drm_crtc_state *state) uint32_t i, lut_size; uint32_t word0, word1; - if (crtc_state_is_legacy(state)) { + if (crtc_state_is_legacy_gamma(state)) { /* Turn off degamma/gamma on CGM block. */ I915_WRITE(CGM_PIPE_MODE(pipe), (state->ctm ? CGM_PIPE_MODE_CSC : 0)); @@ -632,12 +632,10 @@ int intel_color_check(struct drm_crtc *crtc, return 0; /* - * We also allow no degamma lut and a gamma lut at the legacy + * We also allow no degamma lut/ctm and a gamma lut at the legacy * size (256 entries). */ - if (!crtc_state->degamma_lut && - crtc_state->gamma_lut && - crtc_state->gamma_lut->length == LEGACY_LUT_LENGTH) + if (crtc_state_is_legacy_gamma(crtc_state)) return 0; return -EINVAL; diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index a77dd80a97f2..437339f5d098 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -213,6 +213,19 @@ static void pch_post_disable_crt(struct intel_encoder *encoder, intel_disable_crt(encoder, old_crtc_state, old_conn_state); } +static void hsw_disable_crt(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct drm_crtc *crtc = old_crtc_state->base.crtc; + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + WARN_ON(!intel_crtc->config->has_pch_encoder); + + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); +} + static void hsw_post_disable_crt(struct intel_encoder *encoder, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) @@ -225,6 +238,58 @@ static void hsw_post_disable_crt(struct intel_encoder *encoder, lpt_disable_iclkip(dev_priv); intel_ddi_fdi_post_disable(encoder, old_crtc_state, old_conn_state); + + WARN_ON(!old_crtc_state->has_pch_encoder); + + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); +} + +static void hsw_pre_pll_enable_crt(struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) +{ + struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + + WARN_ON(!intel_crtc->config->has_pch_encoder); + + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); +} + +static void hsw_pre_enable_crt(struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) +{ + struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + + WARN_ON(!intel_crtc->config->has_pch_encoder); + + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); + + dev_priv->display.fdi_link_train(intel_crtc, pipe_config); +} + +static void hsw_enable_crt(struct intel_encoder *encoder, + const struct intel_crtc_state *pipe_config, + const struct drm_connector_state *conn_state) +{ + struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; + + WARN_ON(!intel_crtc->config->has_pch_encoder); + + intel_crt_set_dpms(encoder, pipe_config, DRM_MODE_DPMS_ON); + + intel_wait_for_vblank(dev_priv, pipe); + intel_wait_for_vblank(dev_priv, pipe); + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } static void intel_enable_crt(struct intel_encoder *encoder, @@ -279,10 +344,25 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, struct drm_connector_state *conn_state) { + return true; +} + +static bool pch_crt_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) +{ + pipe_config->has_pch_encoder = true; + + return true; +} + +static bool hsw_crt_compute_config(struct intel_encoder *encoder, + struct intel_crtc_state *pipe_config, + struct drm_connector_state *conn_state) +{ struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - if (HAS_PCH_SPLIT(dev_priv)) - pipe_config->has_pch_encoder = true; + pipe_config->has_pch_encoder = true; /* LPT FDI RX only supports 8bpc. */ if (HAS_PCH_LPT(dev_priv)) { @@ -295,8 +375,7 @@ static bool intel_crt_compute_config(struct intel_encoder *encoder, } /* FDI must always be 2.7 GHz */ - if (HAS_DDI(dev_priv)) - pipe_config->port_clock = 135000 * 2; + pipe_config->port_clock = 135000 * 2; return true; } @@ -712,7 +791,7 @@ intel_crt_detect(struct drm_connector *connector, * broken monitor (without edid) to work behind a broken kvm (that fails * to have the right resistors for HP detection) needs to fix this up. * For now just bail out. */ - if (I915_HAS_HOTPLUG(dev_priv) && !i915.load_detect_test) { + if (I915_HAS_HOTPLUG(dev_priv) && !i915_modparams.load_detect_test) { status = connector_status_disconnected; goto out; } @@ -730,7 +809,7 @@ intel_crt_detect(struct drm_connector *connector, else if (INTEL_GEN(dev_priv) < 4) status = intel_crt_load_detect(crt, to_intel_crtc(connector->state->crtc)->pipe); - else if (i915.load_detect_test) + else if (i915_modparams.load_detect_test) status = connector_status_disconnected; else status = connector_status_unknown; @@ -890,26 +969,33 @@ void intel_crt_init(struct drm_i915_private *dev_priv) crt->base.power_domain = POWER_DOMAIN_PORT_CRT; - crt->base.compute_config = intel_crt_compute_config; - if (HAS_PCH_SPLIT(dev_priv)) { - crt->base.disable = pch_disable_crt; - crt->base.post_disable = pch_post_disable_crt; - } else { - crt->base.disable = intel_disable_crt; - } - crt->base.enable = intel_enable_crt; if (I915_HAS_HOTPLUG(dev_priv) && !dmi_check_system(intel_spurious_crt_detect)) crt->base.hpd_pin = HPD_CRT; + if (HAS_DDI(dev_priv)) { crt->base.port = PORT_E; crt->base.get_config = hsw_crt_get_config; crt->base.get_hw_state = intel_ddi_get_hw_state; + crt->base.compute_config = hsw_crt_compute_config; + crt->base.pre_pll_enable = hsw_pre_pll_enable_crt; + crt->base.pre_enable = hsw_pre_enable_crt; + crt->base.enable = hsw_enable_crt; + crt->base.disable = hsw_disable_crt; crt->base.post_disable = hsw_post_disable_crt; } else { + if (HAS_PCH_SPLIT(dev_priv)) { + crt->base.compute_config = pch_crt_compute_config; + crt->base.disable = pch_disable_crt; + crt->base.post_disable = pch_post_disable_crt; + } else { + crt->base.compute_config = intel_crt_compute_config; + crt->base.disable = intel_disable_crt; + } crt->base.port = PORT_NONE; crt->base.get_config = intel_crt_get_config; crt->base.get_hw_state = intel_crt_get_hw_state; + crt->base.enable = intel_enable_crt; } intel_connector->get_hw_state = intel_connector_get_hw_state; diff --git a/drivers/gpu/drm/i915/intel_csr.c b/drivers/gpu/drm/i915/intel_csr.c index 965988f79a55..da9de47562b8 100644 --- a/drivers/gpu/drm/i915/intel_csr.c +++ b/drivers/gpu/drm/i915/intel_csr.c @@ -52,10 +52,6 @@ MODULE_FIRMWARE(I915_CSR_SKL); MODULE_FIRMWARE(I915_CSR_BXT); #define BXT_CSR_VERSION_REQUIRED CSR_VERSION(1, 7) -#define FIRMWARE_URL "https://01.org/linuxgraphics/downloads/firmware" - - - #define CSR_MAX_FW_SIZE 0x2FFF #define CSR_DEFAULT_FW_OFFSET 0xFFFFFFFF @@ -216,7 +212,7 @@ static void gen9_set_dc_state_debugmask(struct drm_i915_private *dev_priv) mask = DC_STATE_DEBUG_MASK_MEMORY_UP; - if (IS_BROXTON(dev_priv)) + if (IS_GEN9_LP(dev_priv)) mask |= DC_STATE_DEBUG_MASK_CORES; /* The below bit doesn't need to be cleared ever afterwards */ @@ -252,8 +248,14 @@ void intel_csr_load_program(struct drm_i915_private *dev_priv) } fw_size = dev_priv->csr.dmc_fw_size; + assert_rpm_wakelock_held(dev_priv); + + preempt_disable(); + for (i = 0; i < fw_size; i++) - I915_WRITE(CSR_PROGRAM(i), payload[i]); + I915_WRITE_FW(CSR_PROGRAM(i), payload[i]); + + preempt_enable(); for (i = 0; i < dev_priv->csr.mmio_count; i++) { I915_WRITE(dev_priv->csr.mmioaddr[i], @@ -285,7 +287,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, css_header = (struct intel_css_header *)fw->data; if (sizeof(struct intel_css_header) != (css_header->header_len * 4)) { - DRM_ERROR("Firmware has wrong CSS header length %u bytes\n", + DRM_ERROR("DMC firmware has wrong CSS header length " + "(%u bytes)\n", (css_header->header_len * 4)); return NULL; } @@ -309,7 +312,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, if (csr->version != required_version) { DRM_INFO("Refusing to load DMC firmware v%u.%u," - " please use v%u.%u [" FIRMWARE_URL "].\n", + " please use v%u.%u\n", CSR_VERSION_MAJOR(csr->version), CSR_VERSION_MINOR(csr->version), CSR_VERSION_MAJOR(required_version), @@ -324,7 +327,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, &fw->data[readcount]; if (sizeof(struct intel_package_header) != (package_header->header_len * 4)) { - DRM_ERROR("Firmware has wrong package header length %u bytes\n", + DRM_ERROR("DMC firmware has wrong package header length " + "(%u bytes)\n", (package_header->header_len * 4)); return NULL; } @@ -345,7 +349,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, dmc_offset = package_header->fw_info[i].offset; } if (dmc_offset == CSR_DEFAULT_FW_OFFSET) { - DRM_ERROR("Firmware not supported for %c stepping\n", + DRM_ERROR("DMC firmware not supported for %c stepping\n", si->stepping); return NULL; } @@ -354,7 +358,8 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, /* Extract dmc_header information. */ dmc_header = (struct intel_dmc_header *)&fw->data[readcount]; if (sizeof(struct intel_dmc_header) != (dmc_header->header_len)) { - DRM_ERROR("Firmware has wrong dmc header length %u bytes\n", + DRM_ERROR("DMC firmware has wrong dmc header length " + "(%u bytes)\n", (dmc_header->header_len)); return NULL; } @@ -362,7 +367,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, /* Cache the dmc header info. */ if (dmc_header->mmio_count > ARRAY_SIZE(csr->mmioaddr)) { - DRM_ERROR("Firmware has wrong mmio count %u\n", + DRM_ERROR("DMC firmware has wrong mmio count %u\n", dmc_header->mmio_count); return NULL; } @@ -370,7 +375,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, for (i = 0; i < dmc_header->mmio_count; i++) { if (dmc_header->mmioaddr[i] < CSR_MMIO_START_RANGE || dmc_header->mmioaddr[i] > CSR_MMIO_END_RANGE) { - DRM_ERROR(" Firmware has wrong mmio address 0x%x\n", + DRM_ERROR("DMC firmware has wrong mmio address 0x%x\n", dmc_header->mmioaddr[i]); return NULL; } @@ -381,7 +386,7 @@ static uint32_t *parse_csr_fw(struct drm_i915_private *dev_priv, /* fw_size is in dwords, so multiplied by 4 to convert into bytes. */ nbytes = dmc_header->fw_size * 4; if (nbytes > CSR_MAX_FW_SIZE) { - DRM_ERROR("CSR firmware too big (%u) bytes\n", nbytes); + DRM_ERROR("DMC firmware too big (%u bytes)\n", nbytes); return NULL; } csr->dmc_fw_size = dmc_header->fw_size; @@ -419,9 +424,11 @@ static void csr_load_work_fn(struct work_struct *work) CSR_VERSION_MINOR(csr->version)); } else { dev_notice(dev_priv->drm.dev, - "Failed to load DMC firmware" - " [" FIRMWARE_URL "]," - " disabling runtime power management.\n"); + "Failed to load DMC firmware %s." + " Disabling runtime power management.\n", + csr->fw_path); + dev_notice(dev_priv->drm.dev, "DMC firmware homepage: %s", + INTEL_UC_FIRMWARE_URL); } release_firmware(fw); diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index 1da3bb2cc4b4..933c18fd4258 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c @@ -301,39 +301,38 @@ static const struct ddi_buf_trans skl_y_ddi_translations_hdmi[] = { }; struct bxt_ddi_buf_trans { - u32 margin; /* swing value */ - u32 scale; /* scale value */ - u32 enable; /* scale enable */ - u32 deemphasis; - bool default_index; /* true if the entry represents default value */ + u8 margin; /* swing value */ + u8 scale; /* scale value */ + u8 enable; /* scale enable */ + u8 deemphasis; }; static const struct bxt_ddi_buf_trans bxt_ddi_translations_dp[] = { /* Idx NT mV diff db */ - { 52, 0x9A, 0, 128, true }, /* 0: 400 0 */ - { 78, 0x9A, 0, 85, false }, /* 1: 400 3.5 */ - { 104, 0x9A, 0, 64, false }, /* 2: 400 6 */ - { 154, 0x9A, 0, 43, false }, /* 3: 400 9.5 */ - { 77, 0x9A, 0, 128, false }, /* 4: 600 0 */ - { 116, 0x9A, 0, 85, false }, /* 5: 600 3.5 */ - { 154, 0x9A, 0, 64, false }, /* 6: 600 6 */ - { 102, 0x9A, 0, 128, false }, /* 7: 800 0 */ - { 154, 0x9A, 0, 85, false }, /* 8: 800 3.5 */ - { 154, 0x9A, 1, 128, false }, /* 9: 1200 0 */ + { 52, 0x9A, 0, 128, }, /* 0: 400 0 */ + { 78, 0x9A, 0, 85, }, /* 1: 400 3.5 */ + { 104, 0x9A, 0, 64, }, /* 2: 400 6 */ + { 154, 0x9A, 0, 43, }, /* 3: 400 9.5 */ + { 77, 0x9A, 0, 128, }, /* 4: 600 0 */ + { 116, 0x9A, 0, 85, }, /* 5: 600 3.5 */ + { 154, 0x9A, 0, 64, }, /* 6: 600 6 */ + { 102, 0x9A, 0, 128, }, /* 7: 800 0 */ + { 154, 0x9A, 0, 85, }, /* 8: 800 3.5 */ + { 154, 0x9A, 1, 128, }, /* 9: 1200 0 */ }; static const struct bxt_ddi_buf_trans bxt_ddi_translations_edp[] = { /* Idx NT mV diff db */ - { 26, 0, 0, 128, false }, /* 0: 200 0 */ - { 38, 0, 0, 112, false }, /* 1: 200 1.5 */ - { 48, 0, 0, 96, false }, /* 2: 200 4 */ - { 54, 0, 0, 69, false }, /* 3: 200 6 */ - { 32, 0, 0, 128, false }, /* 4: 250 0 */ - { 48, 0, 0, 104, false }, /* 5: 250 1.5 */ - { 54, 0, 0, 85, false }, /* 6: 250 4 */ - { 43, 0, 0, 128, false }, /* 7: 300 0 */ - { 54, 0, 0, 101, false }, /* 8: 300 1.5 */ - { 48, 0, 0, 128, false }, /* 9: 300 0 */ + { 26, 0, 0, 128, }, /* 0: 200 0 */ + { 38, 0, 0, 112, }, /* 1: 200 1.5 */ + { 48, 0, 0, 96, }, /* 2: 200 4 */ + { 54, 0, 0, 69, }, /* 3: 200 6 */ + { 32, 0, 0, 128, }, /* 4: 250 0 */ + { 48, 0, 0, 104, }, /* 5: 250 1.5 */ + { 54, 0, 0, 85, }, /* 6: 250 4 */ + { 43, 0, 0, 128, }, /* 7: 300 0 */ + { 54, 0, 0, 101, }, /* 8: 300 1.5 */ + { 48, 0, 0, 128, }, /* 9: 300 0 */ }; /* BSpec has 2 recommended values - entries 0 and 8. @@ -341,24 +340,24 @@ static const struct bxt_ddi_buf_trans bxt_ddi_translations_edp[] = { */ static const struct bxt_ddi_buf_trans bxt_ddi_translations_hdmi[] = { /* Idx NT mV diff db */ - { 52, 0x9A, 0, 128, false }, /* 0: 400 0 */ - { 52, 0x9A, 0, 85, false }, /* 1: 400 3.5 */ - { 52, 0x9A, 0, 64, false }, /* 2: 400 6 */ - { 42, 0x9A, 0, 43, false }, /* 3: 400 9.5 */ - { 77, 0x9A, 0, 128, false }, /* 4: 600 0 */ - { 77, 0x9A, 0, 85, false }, /* 5: 600 3.5 */ - { 77, 0x9A, 0, 64, false }, /* 6: 600 6 */ - { 102, 0x9A, 0, 128, false }, /* 7: 800 0 */ - { 102, 0x9A, 0, 85, false }, /* 8: 800 3.5 */ - { 154, 0x9A, 1, 128, true }, /* 9: 1200 0 */ + { 52, 0x9A, 0, 128, }, /* 0: 400 0 */ + { 52, 0x9A, 0, 85, }, /* 1: 400 3.5 */ + { 52, 0x9A, 0, 64, }, /* 2: 400 6 */ + { 42, 0x9A, 0, 43, }, /* 3: 400 9.5 */ + { 77, 0x9A, 0, 128, }, /* 4: 600 0 */ + { 77, 0x9A, 0, 85, }, /* 5: 600 3.5 */ + { 77, 0x9A, 0, 64, }, /* 6: 600 6 */ + { 102, 0x9A, 0, 128, }, /* 7: 800 0 */ + { 102, 0x9A, 0, 85, }, /* 8: 800 3.5 */ + { 154, 0x9A, 1, 128, }, /* 9: 1200 0 */ }; struct cnl_ddi_buf_trans { - u32 dw2_swing_sel; - u32 dw7_n_scalar; - u32 dw4_cursor_coeff; - u32 dw4_post_cursor_2; - u32 dw4_post_cursor_1; + u8 dw2_swing_sel; + u8 dw7_n_scalar; + u8 dw4_cursor_coeff; + u8 dw4_post_cursor_2; + u8 dw4_post_cursor_1; }; /* Voltage Swing Programming for VccIO 0.85V for DP */ @@ -588,6 +587,120 @@ skl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) } } +static int skl_buf_trans_num_entries(enum port port, int n_entries) +{ + /* Only DDIA and DDIE can select the 10th register with DP */ + if (port == PORT_A || port == PORT_E) + return min(n_entries, 10); + else + return min(n_entries, 9); +} + +static const struct ddi_buf_trans * +intel_ddi_get_buf_trans_dp(struct drm_i915_private *dev_priv, + enum port port, int *n_entries) +{ + if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { + const struct ddi_buf_trans *ddi_translations = + kbl_get_buf_trans_dp(dev_priv, n_entries); + *n_entries = skl_buf_trans_num_entries(port, *n_entries); + return ddi_translations; + } else if (IS_SKYLAKE(dev_priv)) { + const struct ddi_buf_trans *ddi_translations = + skl_get_buf_trans_dp(dev_priv, n_entries); + *n_entries = skl_buf_trans_num_entries(port, *n_entries); + return ddi_translations; + } else if (IS_BROADWELL(dev_priv)) { + *n_entries = ARRAY_SIZE(bdw_ddi_translations_dp); + return bdw_ddi_translations_dp; + } else if (IS_HASWELL(dev_priv)) { + *n_entries = ARRAY_SIZE(hsw_ddi_translations_dp); + return hsw_ddi_translations_dp; + } + + *n_entries = 0; + return NULL; +} + +static const struct ddi_buf_trans * +intel_ddi_get_buf_trans_edp(struct drm_i915_private *dev_priv, + enum port port, int *n_entries) +{ + if (IS_GEN9_BC(dev_priv)) { + const struct ddi_buf_trans *ddi_translations = + skl_get_buf_trans_edp(dev_priv, n_entries); + *n_entries = skl_buf_trans_num_entries(port, *n_entries); + return ddi_translations; + } else if (IS_BROADWELL(dev_priv)) { + return bdw_get_buf_trans_edp(dev_priv, n_entries); + } else if (IS_HASWELL(dev_priv)) { + *n_entries = ARRAY_SIZE(hsw_ddi_translations_dp); + return hsw_ddi_translations_dp; + } + + *n_entries = 0; + return NULL; +} + +static const struct ddi_buf_trans * +intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv, + int *n_entries) +{ + if (IS_BROADWELL(dev_priv)) { + *n_entries = ARRAY_SIZE(bdw_ddi_translations_fdi); + return bdw_ddi_translations_fdi; + } else if (IS_HASWELL(dev_priv)) { + *n_entries = ARRAY_SIZE(hsw_ddi_translations_fdi); + return hsw_ddi_translations_fdi; + } + + *n_entries = 0; + return NULL; +} + +static const struct ddi_buf_trans * +intel_ddi_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, + int *n_entries) +{ + if (IS_GEN9_BC(dev_priv)) { + return skl_get_buf_trans_hdmi(dev_priv, n_entries); + } else if (IS_BROADWELL(dev_priv)) { + *n_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); + return bdw_ddi_translations_hdmi; + } else if (IS_HASWELL(dev_priv)) { + *n_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); + return hsw_ddi_translations_hdmi; + } + + *n_entries = 0; + return NULL; +} + +static const struct bxt_ddi_buf_trans * +bxt_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) +{ + *n_entries = ARRAY_SIZE(bxt_ddi_translations_dp); + return bxt_ddi_translations_dp; +} + +static const struct bxt_ddi_buf_trans * +bxt_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) +{ + if (dev_priv->vbt.edp.low_vswing) { + *n_entries = ARRAY_SIZE(bxt_ddi_translations_edp); + return bxt_ddi_translations_edp; + } + + return bxt_get_buf_trans_dp(dev_priv, n_entries); +} + +static const struct bxt_ddi_buf_trans * +bxt_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) +{ + *n_entries = ARRAY_SIZE(bxt_ddi_translations_hdmi); + return bxt_ddi_translations_hdmi; +} + static const struct cnl_ddi_buf_trans * cnl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) { @@ -602,8 +715,10 @@ cnl_get_buf_trans_hdmi(struct drm_i915_private *dev_priv, int *n_entries) } else if (voltage == VOLTAGE_INFO_1_05V) { *n_entries = ARRAY_SIZE(cnl_ddi_translations_hdmi_1_05V); return cnl_ddi_translations_hdmi_1_05V; - } else + } else { + *n_entries = 1; /* shut up gcc */ MISSING_CASE(voltage); + } return NULL; } @@ -621,8 +736,10 @@ cnl_get_buf_trans_dp(struct drm_i915_private *dev_priv, int *n_entries) } else if (voltage == VOLTAGE_INFO_1_05V) { *n_entries = ARRAY_SIZE(cnl_ddi_translations_dp_1_05V); return cnl_ddi_translations_dp_1_05V; - } else + } else { + *n_entries = 1; /* shut up gcc */ MISSING_CASE(voltage); + } return NULL; } @@ -641,8 +758,10 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) } else if (voltage == VOLTAGE_INFO_1_05V) { *n_entries = ARRAY_SIZE(cnl_ddi_translations_edp_1_05V); return cnl_ddi_translations_edp_1_05V; - } else + } else { + *n_entries = 1; /* shut up gcc */ MISSING_CASE(voltage); + } return NULL; } else { return cnl_get_buf_trans_dp(dev_priv, n_entries); @@ -651,92 +770,40 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries) static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port) { - int n_hdmi_entries; - int hdmi_level; - int hdmi_default_entry; - - hdmi_level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; + int n_entries, level, default_entry; - if (IS_GEN9_LP(dev_priv)) - return hdmi_level; + level = dev_priv->vbt.ddi_port_info[port].hdmi_level_shift; if (IS_CANNONLAKE(dev_priv)) { - cnl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); - hdmi_default_entry = n_hdmi_entries - 1; + cnl_get_buf_trans_hdmi(dev_priv, &n_entries); + default_entry = n_entries - 1; + } else if (IS_GEN9_LP(dev_priv)) { + bxt_get_buf_trans_hdmi(dev_priv, &n_entries); + default_entry = n_entries - 1; } else if (IS_GEN9_BC(dev_priv)) { - skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); - hdmi_default_entry = 8; + intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + default_entry = 8; } else if (IS_BROADWELL(dev_priv)) { - n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); - hdmi_default_entry = 7; + intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + default_entry = 7; } else if (IS_HASWELL(dev_priv)) { - n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); - hdmi_default_entry = 6; + intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + default_entry = 6; } else { WARN(1, "ddi translation table missing\n"); - n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); - hdmi_default_entry = 7; + return 0; } /* Choose a good default if VBT is badly populated */ - if (hdmi_level == HDMI_LEVEL_SHIFT_UNKNOWN || - hdmi_level >= n_hdmi_entries) - hdmi_level = hdmi_default_entry; - - return hdmi_level; -} - -static const struct ddi_buf_trans * -intel_ddi_get_buf_trans_dp(struct drm_i915_private *dev_priv, - int *n_entries) -{ - if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { - return kbl_get_buf_trans_dp(dev_priv, n_entries); - } else if (IS_SKYLAKE(dev_priv)) { - return skl_get_buf_trans_dp(dev_priv, n_entries); - } else if (IS_BROADWELL(dev_priv)) { - *n_entries = ARRAY_SIZE(bdw_ddi_translations_dp); - return bdw_ddi_translations_dp; - } else if (IS_HASWELL(dev_priv)) { - *n_entries = ARRAY_SIZE(hsw_ddi_translations_dp); - return hsw_ddi_translations_dp; - } - - *n_entries = 0; - return NULL; -} - -static const struct ddi_buf_trans * -intel_ddi_get_buf_trans_edp(struct drm_i915_private *dev_priv, - int *n_entries) -{ - if (IS_GEN9_BC(dev_priv)) { - return skl_get_buf_trans_edp(dev_priv, n_entries); - } else if (IS_BROADWELL(dev_priv)) { - return bdw_get_buf_trans_edp(dev_priv, n_entries); - } else if (IS_HASWELL(dev_priv)) { - *n_entries = ARRAY_SIZE(hsw_ddi_translations_dp); - return hsw_ddi_translations_dp; - } - - *n_entries = 0; - return NULL; -} + if (level == HDMI_LEVEL_SHIFT_UNKNOWN || level >= n_entries) + level = default_entry; -static const struct ddi_buf_trans * -intel_ddi_get_buf_trans_fdi(struct drm_i915_private *dev_priv, - int *n_entries) -{ - if (IS_BROADWELL(dev_priv)) { - *n_entries = ARRAY_SIZE(hsw_ddi_translations_fdi); - return hsw_ddi_translations_fdi; - } else if (IS_HASWELL(dev_priv)) { - *n_entries = ARRAY_SIZE(hsw_ddi_translations_fdi); - return hsw_ddi_translations_fdi; - } + if (WARN_ON_ONCE(n_entries == 0)) + return 0; + if (WARN_ON_ONCE(level >= n_entries)) + level = n_entries - 1; - *n_entries = 0; - return NULL; + return level; } /* @@ -754,11 +821,11 @@ static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) switch (encoder->type) { case INTEL_OUTPUT_EDP: - ddi_translations = intel_ddi_get_buf_trans_edp(dev_priv, + ddi_translations = intel_ddi_get_buf_trans_edp(dev_priv, port, &n_entries); break; case INTEL_OUTPUT_DP: - ddi_translations = intel_ddi_get_buf_trans_dp(dev_priv, + ddi_translations = intel_ddi_get_buf_trans_dp(dev_priv, port, &n_entries); break; case INTEL_OUTPUT_ANALOG: @@ -770,16 +837,10 @@ static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) return; } - if (IS_GEN9_BC(dev_priv)) { - /* If we're boosting the current, set bit 31 of trans1 */ - if (dev_priv->vbt.ddi_port_info[port].dp_boost_level) - iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; - - if (WARN_ON(encoder->type == INTEL_OUTPUT_EDP && - port != PORT_A && port != PORT_E && - n_entries > 9)) - n_entries = 9; - } + /* If we're boosting the current, set bit 31 of trans1 */ + if (IS_GEN9_BC(dev_priv) && + dev_priv->vbt.ddi_port_info[port].dp_boost_level) + iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; for (i = 0; i < n_entries; i++) { I915_WRITE(DDI_BUF_TRANS_LO(port, i), @@ -794,39 +855,32 @@ static void intel_prepare_dp_ddi_buffers(struct intel_encoder *encoder) * values in advance. This function programs the correct values for * HDMI/DVI use cases. */ -static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder) +static void intel_prepare_hdmi_ddi_buffers(struct intel_encoder *encoder, + int level) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 iboost_bit = 0; - int n_hdmi_entries, hdmi_level; + int n_entries; enum port port = intel_ddi_get_encoder_port(encoder); - const struct ddi_buf_trans *ddi_translations_hdmi; + const struct ddi_buf_trans *ddi_translations; - hdmi_level = intel_ddi_hdmi_level(dev_priv, port); + ddi_translations = intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); - if (IS_GEN9_BC(dev_priv)) { - ddi_translations_hdmi = skl_get_buf_trans_hdmi(dev_priv, &n_hdmi_entries); + if (WARN_ON_ONCE(!ddi_translations)) + return; + if (WARN_ON_ONCE(level >= n_entries)) + level = n_entries - 1; - /* If we're boosting the current, set bit 31 of trans1 */ - if (dev_priv->vbt.ddi_port_info[port].hdmi_boost_level) - iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; - } else if (IS_BROADWELL(dev_priv)) { - ddi_translations_hdmi = bdw_ddi_translations_hdmi; - n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); - } else if (IS_HASWELL(dev_priv)) { - ddi_translations_hdmi = hsw_ddi_translations_hdmi; - n_hdmi_entries = ARRAY_SIZE(hsw_ddi_translations_hdmi); - } else { - WARN(1, "ddi translation table missing\n"); - ddi_translations_hdmi = bdw_ddi_translations_hdmi; - n_hdmi_entries = ARRAY_SIZE(bdw_ddi_translations_hdmi); - } + /* If we're boosting the current, set bit 31 of trans1 */ + if (IS_GEN9_BC(dev_priv) && + dev_priv->vbt.ddi_port_info[port].hdmi_boost_level) + iboost_bit = DDI_BUF_BALANCE_LEG_ENABLE; /* Entry 9 is for HDMI: */ I915_WRITE(DDI_BUF_TRANS_LO(port, 9), - ddi_translations_hdmi[hdmi_level].trans1 | iboost_bit); + ddi_translations[level].trans1 | iboost_bit); I915_WRITE(DDI_BUF_TRANS_HI(port, 9), - ddi_translations_hdmi[hdmi_level].trans2); + ddi_translations[level].trans2); } static void intel_wait_ddi_buf_idle(struct drm_i915_private *dev_priv, @@ -1102,14 +1156,14 @@ static int hsw_ddi_calc_wrpll_link(struct drm_i915_private *dev_priv, } static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv, - uint32_t dpll) + enum intel_dpll_id pll_id) { i915_reg_t cfgcr1_reg, cfgcr2_reg; uint32_t cfgcr1_val, cfgcr2_val; uint32_t p0, p1, p2, dco_freq; - cfgcr1_reg = DPLL_CFGCR1(dpll); - cfgcr2_reg = DPLL_CFGCR2(dpll); + cfgcr1_reg = DPLL_CFGCR1(pll_id); + cfgcr2_reg = DPLL_CFGCR2(pll_id); cfgcr1_val = I915_READ(cfgcr1_reg); cfgcr2_val = I915_READ(cfgcr2_reg); @@ -1162,7 +1216,7 @@ static int skl_calc_wrpll_link(struct drm_i915_private *dev_priv, } static int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv, - uint32_t pll_id) + enum intel_dpll_id pll_id) { uint32_t cfgcr0, cfgcr1; uint32_t p0, p1, p2, dco_freq, ref_clock; @@ -1212,7 +1266,10 @@ static int cnl_calc_wrpll_link(struct drm_i915_private *dev_priv, dco_freq = (cfgcr0 & DPLL_CFGCR0_DCO_INTEGER_MASK) * ref_clock; dco_freq += (((cfgcr0 & DPLL_CFGCR0_DCO_FRACTION_MASK) >> - DPLL_CFGCR0_DCO_FRAC_SHIFT) * ref_clock) / 0x8000; + DPLL_CFGCR0_DCO_FRACTION_SHIFT) * ref_clock) / 0x8000; + + if (WARN_ON(p0 == 0 || p1 == 0 || p2 == 0)) + return 0; return dco_freq / (p0 * p1 * p2 * 5); } @@ -1246,7 +1303,8 @@ static void cnl_ddi_clock_get(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int link_clock = 0; - uint32_t cfgcr0, pll_id; + uint32_t cfgcr0; + enum intel_dpll_id pll_id; pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll); @@ -1299,17 +1357,18 @@ static void skl_ddi_clock_get(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); int link_clock = 0; - uint32_t dpll_ctl1, dpll; + uint32_t dpll_ctl1; + enum intel_dpll_id pll_id; - dpll = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll); + pll_id = intel_get_shared_dpll_id(dev_priv, pipe_config->shared_dpll); dpll_ctl1 = I915_READ(DPLL_CTRL1); - if (dpll_ctl1 & DPLL_CTRL1_HDMI_MODE(dpll)) { - link_clock = skl_calc_wrpll_link(dev_priv, dpll); + if (dpll_ctl1 & DPLL_CTRL1_HDMI_MODE(pll_id)) { + link_clock = skl_calc_wrpll_link(dev_priv, pll_id); } else { - link_clock = dpll_ctl1 & DPLL_CTRL1_LINK_RATE_MASK(dpll); - link_clock >>= DPLL_CTRL1_LINK_RATE_SHIFT(dpll); + link_clock = dpll_ctl1 & DPLL_CTRL1_LINK_RATE_MASK(pll_id); + link_clock >>= DPLL_CTRL1_LINK_RATE_SHIFT(pll_id); switch (link_clock) { case DPLL_CTRL1_LINK_RATE_810: @@ -1390,17 +1449,17 @@ static void hsw_ddi_clock_get(struct intel_encoder *encoder, } static int bxt_calc_pll_link(struct drm_i915_private *dev_priv, - enum intel_dpll_id dpll) + enum intel_dpll_id pll_id) { struct intel_shared_dpll *pll; struct intel_dpll_hw_state *state; struct dpll clock; /* For DDI ports we always use a shared PLL. */ - if (WARN_ON(dpll == DPLL_ID_PRIVATE)) + if (WARN_ON(pll_id == DPLL_ID_PRIVATE)) return 0; - pll = &dev_priv->shared_dplls[dpll]; + pll = &dev_priv->shared_dplls[pll_id]; state = &pll->state.hw_state; clock.m1 = 2; @@ -1419,9 +1478,9 @@ static void bxt_ddi_clock_get(struct intel_encoder *encoder, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = intel_ddi_get_encoder_port(encoder); - uint32_t dpll = port; + enum intel_dpll_id pll_id = port; - pipe_config->port_clock = bxt_calc_pll_link(dev_priv, dpll); + pipe_config->port_clock = bxt_calc_pll_link(dev_priv, pll_id); ddi_dotclock_get(pipe_config); } @@ -1713,7 +1772,8 @@ bool intel_ddi_get_hw_state(struct intel_encoder *encoder, out: if (ret && IS_GEN9_LP(dev_priv)) { tmp = I915_READ(BXT_PHY_CTL(port)); - if ((tmp & (BXT_PHY_LANE_POWERDOWN_ACK | + if ((tmp & (BXT_PHY_CMNLANE_POWERDOWN_ACK | + BXT_PHY_LANE_POWERDOWN_ACK | BXT_PHY_LANE_ENABLED)) != BXT_PHY_LANE_ENABLED) DRM_ERROR("Port %c enabled but PHY powered down? " "(PHY_CTL %08x)\n", port_name(port), tmp); @@ -1772,54 +1832,36 @@ static void _skl_ddi_set_iboost(struct drm_i915_private *dev_priv, I915_WRITE(DISPIO_CR_TX_BMU_CR0, tmp); } -static void skl_ddi_set_iboost(struct intel_encoder *encoder, u32 level) +static void skl_ddi_set_iboost(struct intel_encoder *encoder, + int level, enum intel_output_type type) { struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); enum port port = intel_dig_port->port; - int type = encoder->type; - const struct ddi_buf_trans *ddi_translations; uint8_t iboost; - uint8_t dp_iboost, hdmi_iboost; - int n_entries; - /* VBT may override standard boost values */ - dp_iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level; - hdmi_iboost = dev_priv->vbt.ddi_port_info[port].hdmi_boost_level; + if (type == INTEL_OUTPUT_HDMI) + iboost = dev_priv->vbt.ddi_port_info[port].hdmi_boost_level; + else + iboost = dev_priv->vbt.ddi_port_info[port].dp_boost_level; - if (type == INTEL_OUTPUT_DP) { - if (dp_iboost) { - iboost = dp_iboost; - } else { - if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) - ddi_translations = kbl_get_buf_trans_dp(dev_priv, - &n_entries); - else - ddi_translations = skl_get_buf_trans_dp(dev_priv, - &n_entries); - iboost = ddi_translations[level].i_boost; - } - } else if (type == INTEL_OUTPUT_EDP) { - if (dp_iboost) { - iboost = dp_iboost; - } else { - ddi_translations = skl_get_buf_trans_edp(dev_priv, &n_entries); + if (iboost == 0) { + const struct ddi_buf_trans *ddi_translations; + int n_entries; - if (WARN_ON(port != PORT_A && - port != PORT_E && n_entries > 9)) - n_entries = 9; + if (type == INTEL_OUTPUT_HDMI) + ddi_translations = intel_ddi_get_buf_trans_hdmi(dev_priv, &n_entries); + else if (type == INTEL_OUTPUT_EDP) + ddi_translations = intel_ddi_get_buf_trans_edp(dev_priv, port, &n_entries); + else + ddi_translations = intel_ddi_get_buf_trans_dp(dev_priv, port, &n_entries); - iboost = ddi_translations[level].i_boost; - } - } else if (type == INTEL_OUTPUT_HDMI) { - if (hdmi_iboost) { - iboost = hdmi_iboost; - } else { - ddi_translations = skl_get_buf_trans_hdmi(dev_priv, &n_entries); - iboost = ddi_translations[level].i_boost; - } - } else { - return; + if (WARN_ON_ONCE(!ddi_translations)) + return; + if (WARN_ON_ONCE(level >= n_entries)) + level = n_entries - 1; + + iboost = ddi_translations[level].i_boost; } /* Make sure that the requested I_boost is valid */ @@ -1834,38 +1876,25 @@ static void skl_ddi_set_iboost(struct intel_encoder *encoder, u32 level) _skl_ddi_set_iboost(dev_priv, PORT_E, iboost); } -static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, - u32 level, enum port port, int type) +static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder, + int level, enum intel_output_type type) { + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); const struct bxt_ddi_buf_trans *ddi_translations; - u32 n_entries, i; - - if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) { - n_entries = ARRAY_SIZE(bxt_ddi_translations_edp); - ddi_translations = bxt_ddi_translations_edp; - } else if (type == INTEL_OUTPUT_DP - || type == INTEL_OUTPUT_EDP) { - n_entries = ARRAY_SIZE(bxt_ddi_translations_dp); - ddi_translations = bxt_ddi_translations_dp; - } else if (type == INTEL_OUTPUT_HDMI) { - n_entries = ARRAY_SIZE(bxt_ddi_translations_hdmi); - ddi_translations = bxt_ddi_translations_hdmi; - } else { - DRM_DEBUG_KMS("Vswing programming not done for encoder %d\n", - type); - return; - } + enum port port = encoder->port; + int n_entries; - /* Check if default value has to be used */ - if (level >= n_entries || - (type == INTEL_OUTPUT_HDMI && level == HDMI_LEVEL_SHIFT_UNKNOWN)) { - for (i = 0; i < n_entries; i++) { - if (ddi_translations[i].default_index) { - level = i; - break; - } - } - } + if (type == INTEL_OUTPUT_HDMI) + ddi_translations = bxt_get_buf_trans_hdmi(dev_priv, &n_entries); + else if (type == INTEL_OUTPUT_EDP) + ddi_translations = bxt_get_buf_trans_edp(dev_priv, &n_entries); + else + ddi_translations = bxt_get_buf_trans_dp(dev_priv, &n_entries); + + if (WARN_ON_ONCE(!ddi_translations)) + return; + if (WARN_ON_ONCE(level >= n_entries)) + level = n_entries - 1; bxt_ddi_phy_set_signal_level(dev_priv, port, ddi_translations[level].margin, @@ -1877,6 +1906,7 @@ static void bxt_ddi_vswing_sequence(struct drm_i915_private *dev_priv, u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = encoder->port; int n_entries; if (IS_CANNONLAKE(dev_priv)) { @@ -1884,11 +1914,16 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) cnl_get_buf_trans_edp(dev_priv, &n_entries); else cnl_get_buf_trans_dp(dev_priv, &n_entries); + } else if (IS_GEN9_LP(dev_priv)) { + if (encoder->type == INTEL_OUTPUT_EDP) + bxt_get_buf_trans_edp(dev_priv, &n_entries); + else + bxt_get_buf_trans_dp(dev_priv, &n_entries); } else { if (encoder->type == INTEL_OUTPUT_EDP) - intel_ddi_get_buf_trans_edp(dev_priv, &n_entries); + intel_ddi_get_buf_trans_edp(dev_priv, port, &n_entries); else - intel_ddi_get_buf_trans_dp(dev_priv, &n_entries); + intel_ddi_get_buf_trans_dp(dev_priv, port, &n_entries); } if (WARN_ON(n_entries < 1)) @@ -1900,28 +1935,26 @@ u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder) DP_TRAIN_VOLTAGE_SWING_MASK; } -static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, - u32 level, enum port port, int type) +static void cnl_ddi_vswing_program(struct intel_encoder *encoder, + int level, enum intel_output_type type) { - const struct cnl_ddi_buf_trans *ddi_translations = NULL; - u32 n_entries, val; - int ln; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); + const struct cnl_ddi_buf_trans *ddi_translations; + int n_entries, ln; + u32 val; - if (type == INTEL_OUTPUT_HDMI) { + if (type == INTEL_OUTPUT_HDMI) ddi_translations = cnl_get_buf_trans_hdmi(dev_priv, &n_entries); - } else if (type == INTEL_OUTPUT_DP) { - ddi_translations = cnl_get_buf_trans_dp(dev_priv, &n_entries); - } else if (type == INTEL_OUTPUT_EDP) { + else if (type == INTEL_OUTPUT_EDP) ddi_translations = cnl_get_buf_trans_edp(dev_priv, &n_entries); - } + else + ddi_translations = cnl_get_buf_trans_dp(dev_priv, &n_entries); - if (WARN_ON(ddi_translations == NULL)) + if (WARN_ON_ONCE(!ddi_translations)) return; - - if (level >= n_entries) { - DRM_DEBUG_KMS("DDI translation not found for level %d. Using %d instead.", level, n_entries - 1); + if (WARN_ON_ONCE(level >= n_entries)) level = n_entries - 1; - } /* Set PORT_TX_DW5 Scaling Mode Sel to 010b. */ val = I915_READ(CNL_PORT_TX_DW5_LN0(port)); @@ -1939,7 +1972,7 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, val |= RCOMP_SCALAR(0x98); I915_WRITE(CNL_PORT_TX_DW2_GRP(port), val); - /* Program PORT_TX_DW4 */ + /* Program PORT_TX_DW4 */ /* We cannot write to GRP. It would overrite individual loadgen */ for (ln = 0; ln < 4; ln++) { val = I915_READ(CNL_PORT_TX_DW4_LN(port, ln)); @@ -1951,7 +1984,7 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, I915_WRITE(CNL_PORT_TX_DW4_LN(port, ln), val); } - /* Program PORT_TX_DW5 */ + /* Program PORT_TX_DW5 */ /* All DW5 values are fixed for every table entry */ val = I915_READ(CNL_PORT_TX_DW5_LN0(port)); val &= ~RTERM_SELECT_MASK; @@ -1959,33 +1992,29 @@ static void cnl_ddi_vswing_program(struct drm_i915_private *dev_priv, val |= TAP3_DISABLE; I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val); - /* Program PORT_TX_DW7 */ + /* Program PORT_TX_DW7 */ val = I915_READ(CNL_PORT_TX_DW7_LN0(port)); val &= ~N_SCALAR_MASK; val |= N_SCALAR(ddi_translations[level].dw7_n_scalar); I915_WRITE(CNL_PORT_TX_DW7_GRP(port), val); } -static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level) +static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, + int level, enum intel_output_type type) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); enum port port = intel_ddi_get_encoder_port(encoder); - int type = encoder->type; - int width = 0; - int rate = 0; + int width, rate, ln; u32 val; - int ln = 0; - if ((intel_dp) && (type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP)) { - width = intel_dp->lane_count; - rate = intel_dp->link_rate; - } else if (type == INTEL_OUTPUT_HDMI) { + if (type == INTEL_OUTPUT_HDMI) { width = 4; - /* Rate is always < than 6GHz for HDMI */ + rate = 0; /* Rate is always < than 6GHz for HDMI */ } else { - MISSING_CASE(type); - return; + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + + width = intel_dp->lane_count; + rate = intel_dp->link_rate; } /* @@ -1994,7 +2023,7 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level) * else clear to 0b. */ val = I915_READ(CNL_PORT_PCS_DW1_LN0(port)); - if (type == INTEL_OUTPUT_EDP || type == INTEL_OUTPUT_DP) + if (type != INTEL_OUTPUT_HDMI) val |= COMMON_KEEPER_EN; else val &= ~COMMON_KEEPER_EN; @@ -2029,7 +2058,7 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder, u32 level) I915_WRITE(CNL_PORT_TX_DW5_GRP(port), val); /* 5. Program swing and de-emphasis */ - cnl_ddi_vswing_program(dev_priv, level, port, type); + cnl_ddi_vswing_program(encoder, level, type); /* 6. Set training enable to trigger update */ val = I915_READ(CNL_PORT_TX_DW5_LN0(port)); @@ -2066,13 +2095,12 @@ u32 bxt_signal_levels(struct intel_dp *intel_dp) struct intel_digital_port *dport = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); struct intel_encoder *encoder = &dport->base; - enum port port = dport->port; - u32 level = intel_ddi_dp_level(intel_dp); + int level = intel_ddi_dp_level(intel_dp); if (IS_CANNONLAKE(dev_priv)) - cnl_ddi_vswing_sequence(encoder, level); + cnl_ddi_vswing_sequence(encoder, level, encoder->type); else - bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); + bxt_ddi_vswing_sequence(encoder, level, encoder->type); return 0; } @@ -2082,10 +2110,10 @@ uint32_t ddi_signal_levels(struct intel_dp *intel_dp) struct intel_digital_port *dport = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(dport->base.base.dev); struct intel_encoder *encoder = &dport->base; - uint32_t level = intel_ddi_dp_level(intel_dp); + int level = intel_ddi_dp_level(intel_dp); if (IS_GEN9_BC(dev_priv)) - skl_ddi_set_iboost(encoder, level); + skl_ddi_set_iboost(encoder, level, encoder->type); return DDI_BUF_TRANS_SELECT(level); } @@ -2112,8 +2140,7 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, * register writes. */ val = I915_READ(DPCLKA_CFGCR0); - val &= ~(DPCLKA_CFGCR0_DDI_CLK_OFF(port) | - DPCLKA_CFGCR0_DDI_CLK_SEL_MASK(port)); + val &= ~DPCLKA_CFGCR0_DDI_CLK_OFF(port); I915_WRITE(DPCLKA_CFGCR0, val); } else if (IS_GEN9_BC(dev_priv)) { /* DDI -> PLL mapping */ @@ -2131,47 +2158,61 @@ static void intel_ddi_clk_select(struct intel_encoder *encoder, } } +static void intel_ddi_clk_disable(struct intel_encoder *encoder) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); + + if (IS_CANNONLAKE(dev_priv)) + I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) | + DPCLKA_CFGCR0_DDI_CLK_OFF(port)); + else if (IS_GEN9_BC(dev_priv)) + I915_WRITE(DPLL_CTRL2, I915_READ(DPLL_CTRL2) | + DPLL_CTRL2_DDI_CLK_OFF(port)); + else if (INTEL_GEN(dev_priv) < 9) + I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); +} + static void intel_ddi_pre_enable_dp(struct intel_encoder *encoder, - int link_rate, uint32_t lane_count, - struct intel_shared_dpll *pll, - bool link_mst) + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); enum port port = intel_ddi_get_encoder_port(encoder); struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); - uint32_t level = intel_ddi_dp_level(intel_dp); + bool is_mst = intel_crtc_has_type(crtc_state, INTEL_OUTPUT_DP_MST); + int level = intel_ddi_dp_level(intel_dp); - WARN_ON(link_mst && (port == PORT_A || port == PORT_E)); + WARN_ON(is_mst && (port == PORT_A || port == PORT_E)); - intel_dp_set_link_params(intel_dp, link_rate, lane_count, - link_mst); - if (encoder->type == INTEL_OUTPUT_EDP) - intel_edp_panel_on(intel_dp); + intel_dp_set_link_params(intel_dp, crtc_state->port_clock, + crtc_state->lane_count, is_mst); - intel_ddi_clk_select(encoder, pll); + intel_edp_panel_on(intel_dp); + + intel_ddi_clk_select(encoder, crtc_state->shared_dpll); intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); if (IS_CANNONLAKE(dev_priv)) - cnl_ddi_vswing_sequence(encoder, level); + cnl_ddi_vswing_sequence(encoder, level, encoder->type); else if (IS_GEN9_LP(dev_priv)) - bxt_ddi_vswing_sequence(dev_priv, level, port, encoder->type); + bxt_ddi_vswing_sequence(encoder, level, encoder->type); else intel_prepare_dp_ddi_buffers(encoder); intel_ddi_init_dp_buf_reg(encoder); - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); + if (!is_mst) + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_ON); intel_dp_start_link_train(intel_dp); if (port != PORT_A || INTEL_GEN(dev_priv) >= 9) intel_dp_stop_link_train(intel_dp); } static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, - bool has_infoframe, const struct intel_crtc_state *crtc_state, - const struct drm_connector_state *conn_state, - const struct intel_shared_dpll *pll) + const struct drm_connector_state *conn_state) { struct intel_digital_port *intel_dig_port = enc_to_dig_port(&encoder->base); struct intel_hdmi *intel_hdmi = &intel_dig_port->hdmi; @@ -2181,67 +2222,49 @@ static void intel_ddi_pre_enable_hdmi(struct intel_encoder *encoder, struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); intel_dp_dual_mode_set_tmds_output(intel_hdmi, true); - intel_ddi_clk_select(encoder, pll); + intel_ddi_clk_select(encoder, crtc_state->shared_dpll); intel_display_power_get(dev_priv, dig_port->ddi_io_power_domain); if (IS_CANNONLAKE(dev_priv)) - cnl_ddi_vswing_sequence(encoder, level); + cnl_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI); else if (IS_GEN9_LP(dev_priv)) - bxt_ddi_vswing_sequence(dev_priv, level, port, - INTEL_OUTPUT_HDMI); + bxt_ddi_vswing_sequence(encoder, level, INTEL_OUTPUT_HDMI); else - intel_prepare_hdmi_ddi_buffers(encoder); + intel_prepare_hdmi_ddi_buffers(encoder, level); if (IS_GEN9_BC(dev_priv)) - skl_ddi_set_iboost(encoder, level); + skl_ddi_set_iboost(encoder, level, INTEL_OUTPUT_HDMI); intel_dig_port->set_infoframes(&encoder->base, - has_infoframe, + crtc_state->has_infoframe, crtc_state, conn_state); } static void intel_ddi_pre_enable(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, + const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - int type = encoder->type; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum pipe pipe = crtc->pipe; - if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { - intel_ddi_pre_enable_dp(encoder, - pipe_config->port_clock, - pipe_config->lane_count, - pipe_config->shared_dpll, - intel_crtc_has_type(pipe_config, - INTEL_OUTPUT_DP_MST)); - } - if (type == INTEL_OUTPUT_HDMI) { - intel_ddi_pre_enable_hdmi(encoder, - pipe_config->has_infoframe, - pipe_config, conn_state, - pipe_config->shared_dpll); - } + WARN_ON(crtc_state->has_pch_encoder); + + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + intel_ddi_pre_enable_hdmi(encoder, crtc_state, conn_state); + else + intel_ddi_pre_enable_dp(encoder, crtc_state, conn_state); } -static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) +static void intel_disable_ddi_buf(struct intel_encoder *encoder) { - struct drm_encoder *encoder = &intel_encoder->base; - struct drm_i915_private *dev_priv = to_i915(encoder->dev); - enum port port = intel_ddi_get_encoder_port(intel_encoder); - struct intel_digital_port *dig_port = enc_to_dig_port(encoder); - int type = intel_encoder->type; - uint32_t val; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + enum port port = intel_ddi_get_encoder_port(encoder); bool wait = false; - - /* old_crtc_state and old_conn_state are NULL when called from DP_MST */ - - if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); - } + u32 val; val = I915_READ(DDI_BUF_CTL(port)); if (val & DDI_BUF_CTL_ENABLE) { @@ -2257,36 +2280,75 @@ static void intel_ddi_post_disable(struct intel_encoder *intel_encoder, if (wait) intel_wait_ddi_buf_idle(dev_priv, port); +} - if (type == INTEL_OUTPUT_HDMI) { - dig_port->set_infoframes(encoder, false, - old_crtc_state, old_conn_state); - } +static void intel_ddi_post_disable_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); + struct intel_dp *intel_dp = &dig_port->dp; + /* + * old_crtc_state and old_conn_state are NULL when called from + * DP_MST. The main connector associated with this port is never + * bound to a crtc for MST. + */ + bool is_mst = !old_crtc_state; - if (type == INTEL_OUTPUT_DP || type == INTEL_OUTPUT_EDP) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + /* + * Power down sink before disabling the port, otherwise we end + * up getting interrupts from the sink on detecting link loss. + */ + if (!is_mst) + intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); - intel_edp_panel_vdd_on(intel_dp); - intel_edp_panel_off(intel_dp); - } + intel_disable_ddi_buf(encoder); - if (dig_port) - intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain); + intel_edp_panel_vdd_on(intel_dp); + intel_edp_panel_off(intel_dp); - if (IS_CANNONLAKE(dev_priv)) - I915_WRITE(DPCLKA_CFGCR0, I915_READ(DPCLKA_CFGCR0) | - DPCLKA_CFGCR0_DDI_CLK_OFF(port)); - else if (IS_GEN9_BC(dev_priv)) - I915_WRITE(DPLL_CTRL2, (I915_READ(DPLL_CTRL2) | - DPLL_CTRL2_DDI_CLK_OFF(port))); - else if (INTEL_GEN(dev_priv) < 9) - I915_WRITE(PORT_CLK_SEL(port), PORT_CLK_SEL_NONE); + intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain); - if (type == INTEL_OUTPUT_HDMI) { - struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); + intel_ddi_clk_disable(encoder); +} - intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); - } +static void intel_ddi_post_disable_hdmi(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); + struct intel_hdmi *intel_hdmi = &dig_port->hdmi; + + intel_disable_ddi_buf(encoder); + + dig_port->set_infoframes(&encoder->base, false, + old_crtc_state, old_conn_state); + + intel_display_power_put(dev_priv, dig_port->ddi_io_power_domain); + + intel_ddi_clk_disable(encoder); + + intel_dp_dual_mode_set_tmds_output(intel_hdmi, false); +} + +static void intel_ddi_post_disable(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + /* + * old_crtc_state and old_conn_state are NULL when called from + * DP_MST. The main connector associated with this port is never + * bound to a crtc for MST. + */ + if (old_crtc_state && + intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) + intel_ddi_post_disable_hdmi(encoder, + old_crtc_state, old_conn_state); + else + intel_ddi_post_disable_dp(encoder, + old_crtc_state, old_conn_state); } void intel_ddi_fdi_post_disable(struct intel_encoder *encoder, @@ -2306,7 +2368,8 @@ void intel_ddi_fdi_post_disable(struct intel_encoder *encoder, val &= ~FDI_RX_ENABLE; I915_WRITE(FDI_RX_CTL(PIPE_A), val); - intel_ddi_post_disable(encoder, old_crtc_state, old_conn_state); + intel_disable_ddi_buf(encoder); + intel_ddi_clk_disable(encoder); val = I915_READ(FDI_RX_MISC(PIPE_A)); val &= ~(FDI_RX_PWRDN_LANE1_MASK | FDI_RX_PWRDN_LANE0_MASK); @@ -2322,70 +2385,93 @@ void intel_ddi_fdi_post_disable(struct intel_encoder *encoder, I915_WRITE(FDI_RX_CTL(PIPE_A), val); } -static void intel_enable_ddi(struct intel_encoder *intel_encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) +static void intel_enable_ddi_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) { - struct drm_encoder *encoder = &intel_encoder->base; - struct drm_i915_private *dev_priv = to_i915(encoder->dev); - enum port port = intel_ddi_get_encoder_port(intel_encoder); - int type = intel_encoder->type; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + enum port port = intel_ddi_get_encoder_port(encoder); - if (type == INTEL_OUTPUT_HDMI) { - struct intel_digital_port *intel_dig_port = - enc_to_dig_port(encoder); - bool clock_ratio = pipe_config->hdmi_high_tmds_clock_ratio; - bool scrambling = pipe_config->hdmi_scrambling; - - intel_hdmi_handle_sink_scrambling(intel_encoder, - conn_state->connector, - clock_ratio, scrambling); - - /* In HDMI/DVI mode, the port width, and swing/emphasis values - * are ignored so nothing special needs to be done besides - * enabling the port. - */ - I915_WRITE(DDI_BUF_CTL(port), - intel_dig_port->saved_port_bits | - DDI_BUF_CTL_ENABLE); - } else if (type == INTEL_OUTPUT_EDP) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + if (port == PORT_A && INTEL_GEN(dev_priv) < 9) + intel_dp_stop_link_train(intel_dp); - if (port == PORT_A && INTEL_GEN(dev_priv) < 9) - intel_dp_stop_link_train(intel_dp); + intel_edp_backlight_on(crtc_state, conn_state); + intel_psr_enable(intel_dp, crtc_state); + intel_edp_drrs_enable(intel_dp, crtc_state); - intel_edp_backlight_on(pipe_config, conn_state); - intel_psr_enable(intel_dp, pipe_config); - intel_edp_drrs_enable(intel_dp, pipe_config); - } + if (crtc_state->has_audio) + intel_audio_codec_enable(encoder, crtc_state, conn_state); +} - if (pipe_config->has_audio) - intel_audio_codec_enable(intel_encoder, pipe_config, conn_state); +static void intel_enable_ddi_hdmi(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) +{ + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_digital_port *dig_port = enc_to_dig_port(&encoder->base); + enum port port = intel_ddi_get_encoder_port(encoder); + + intel_hdmi_handle_sink_scrambling(encoder, + conn_state->connector, + crtc_state->hdmi_high_tmds_clock_ratio, + crtc_state->hdmi_scrambling); + + /* In HDMI/DVI mode, the port width, and swing/emphasis values + * are ignored so nothing special needs to be done besides + * enabling the port. + */ + I915_WRITE(DDI_BUF_CTL(port), + dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE); + + if (crtc_state->has_audio) + intel_audio_codec_enable(encoder, crtc_state, conn_state); } -static void intel_disable_ddi(struct intel_encoder *intel_encoder, - const struct intel_crtc_state *old_crtc_state, - const struct drm_connector_state *old_conn_state) +static void intel_enable_ddi(struct intel_encoder *encoder, + const struct intel_crtc_state *crtc_state, + const struct drm_connector_state *conn_state) { - struct drm_encoder *encoder = &intel_encoder->base; - int type = intel_encoder->type; + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) + intel_enable_ddi_hdmi(encoder, crtc_state, conn_state); + else + intel_enable_ddi_dp(encoder, crtc_state, conn_state); +} + +static void intel_disable_ddi_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); if (old_crtc_state->has_audio) - intel_audio_codec_disable(intel_encoder); + intel_audio_codec_disable(encoder); - if (type == INTEL_OUTPUT_HDMI) { - intel_hdmi_handle_sink_scrambling(intel_encoder, - old_conn_state->connector, - false, false); - } + intel_edp_drrs_disable(intel_dp, old_crtc_state); + intel_psr_disable(intel_dp, old_crtc_state); + intel_edp_backlight_off(old_conn_state); +} - if (type == INTEL_OUTPUT_EDP) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); +static void intel_disable_ddi_hdmi(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + if (old_crtc_state->has_audio) + intel_audio_codec_disable(encoder); - intel_edp_drrs_disable(intel_dp, old_crtc_state); - intel_psr_disable(intel_dp, old_crtc_state); - intel_edp_backlight_off(old_conn_state); - } + intel_hdmi_handle_sink_scrambling(encoder, + old_conn_state->connector, + false, false); +} + +static void intel_disable_ddi(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + if (intel_crtc_has_type(old_crtc_state, INTEL_OUTPUT_HDMI)) + intel_disable_ddi_hdmi(encoder, old_crtc_state, old_conn_state); + else + intel_disable_ddi_dp(encoder, old_crtc_state, old_conn_state); } static void bxt_ddi_pre_pll_enable(struct intel_encoder *encoder, diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index b17f7045c8f8..875d428ea75f 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -82,6 +82,39 @@ void intel_device_info_dump(struct drm_i915_private *dev_priv) #undef PRINT_FLAG } +static void gen10_sseu_info_init(struct drm_i915_private *dev_priv) +{ + struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; + const u32 fuse2 = I915_READ(GEN8_FUSE2); + + sseu->slice_mask = (fuse2 & GEN10_F2_S_ENA_MASK) >> + GEN10_F2_S_ENA_SHIFT; + sseu->subslice_mask = (1 << 4) - 1; + sseu->subslice_mask &= ~((fuse2 & GEN10_F2_SS_DIS_MASK) >> + GEN10_F2_SS_DIS_SHIFT); + + sseu->eu_total = hweight32(~I915_READ(GEN8_EU_DISABLE0)); + sseu->eu_total += hweight32(~I915_READ(GEN8_EU_DISABLE1)); + sseu->eu_total += hweight32(~I915_READ(GEN8_EU_DISABLE2)); + sseu->eu_total += hweight8(~(I915_READ(GEN10_EU_DISABLE3) & + GEN10_EU_DIS_SS_MASK)); + + /* + * CNL is expected to always have a uniform distribution + * of EU across subslices with the exception that any one + * EU in any one subslice may be fused off for die + * recovery. + */ + sseu->eu_per_subslice = sseu_subslice_total(sseu) ? + DIV_ROUND_UP(sseu->eu_total, + sseu_subslice_total(sseu)) : 0; + + /* No restrictions on Power Gating */ + sseu->has_slice_pg = 1; + sseu->has_subslice_pg = 1; + sseu->has_eu_pg = 1; +} + static void cherryview_sseu_info_init(struct drm_i915_private *dev_priv) { struct sseu_dev_info *sseu = &mkwrite_device_info(dev_priv)->sseu; @@ -343,7 +376,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) info->num_sprites[pipe] = 1; } - if (i915.disable_display) { + if (i915_modparams.disable_display) { DRM_INFO("Display disabled (module parameter)\n"); info->num_pipes = 0; } else if (info->num_pipes > 0 && @@ -409,10 +442,10 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) cherryview_sseu_info_init(dev_priv); else if (IS_BROADWELL(dev_priv)) broadwell_sseu_info_init(dev_priv); - else if (INTEL_INFO(dev_priv)->gen >= 9) + else if (INTEL_GEN(dev_priv) == 9) gen9_sseu_info_init(dev_priv); - - WARN_ON(info->has_snoop != !info->has_llc); + else if (INTEL_GEN(dev_priv) >= 10) + gen10_sseu_info_init(dev_priv); DRM_DEBUG_DRIVER("slice mask: %04x\n", info->sseu.slice_mask); DRM_DEBUG_DRIVER("slice total: %u\n", hweight8(info->sseu.slice_mask)); diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 97406166417d..053ae6d3d339 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1539,7 +1539,7 @@ static void chv_enable_pll(struct intel_crtc *crtc, * DPLLCMD is AWOL. Use chicken bits to propagate * the value from DPLLBMD to either pipe B or C. */ - I915_WRITE(CBR4_VLV, pipe == PIPE_B ? CBR_DPLLBMD_PIPE_B : CBR_DPLLBMD_PIPE_C); + I915_WRITE(CBR4_VLV, CBR_DPLLBMD_PIPE(pipe)); I915_WRITE(DPLL_MD(PIPE_B), pipe_config->dpll_hw_state.dpll_md); I915_WRITE(CBR4_VLV, 0); dev_priv->chv_dpll_md[pipe] = pipe_config->dpll_hw_state.dpll_md; @@ -1568,11 +1568,12 @@ static int intel_num_dvo_pipes(struct drm_i915_private *dev_priv) return count; } -static void i9xx_enable_pll(struct intel_crtc *crtc) +static void i9xx_enable_pll(struct intel_crtc *crtc, + const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); i915_reg_t reg = DPLL(crtc->pipe); - u32 dpll = crtc->config->dpll_hw_state.dpll; + u32 dpll = crtc_state->dpll_hw_state.dpll; int i; assert_pipe_disabled(dev_priv, crtc->pipe); @@ -1609,7 +1610,7 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) if (INTEL_GEN(dev_priv) >= 4) { I915_WRITE(DPLL_MD(crtc->pipe), - crtc->config->dpll_hw_state.dpll_md); + crtc_state->dpll_hw_state.dpll_md); } else { /* The pixel multiplier can only be updated once the * DPLL is enabled and the clocks are stable. @@ -1627,15 +1628,6 @@ static void i9xx_enable_pll(struct intel_crtc *crtc) } } -/** - * i9xx_disable_pll - disable a PLL - * @dev_priv: i915 private structure - * @pipe: pipe PLL to disable - * - * Disable the PLL for @pipe, making sure the pipe is off first. - * - * Note! This is for pre-ILK only. - */ static void i9xx_disable_pll(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -2219,8 +2211,7 @@ intel_pin_and_fence_fb_obj(struct drm_framebuffer *fb, unsigned int rotation) * something and try to run the system in a "less than optimal" * mode that matches the user configuration. */ - if (i915_vma_get_fence(vma) == 0) - i915_vma_pin_fence(vma); + i915_vma_pin_fence(vma); } i915_vma_get(vma); @@ -2856,7 +2847,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc, if (intel_plane_ggtt_offset(state) == plane_config->base) { fb = c->primary->fb; - drm_framebuffer_reference(fb); + drm_framebuffer_get(fb); goto valid_fb; } } @@ -2887,7 +2878,7 @@ valid_fb: intel_crtc->pipe, PTR_ERR(intel_state->vma)); intel_state->vma = NULL; - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); return; } @@ -2908,7 +2899,7 @@ valid_fb: if (i915_gem_object_is_tiled(obj)) dev_priv->preserve_bios_swizzle = true; - drm_framebuffer_reference(fb); + drm_framebuffer_get(fb); primary->fb = primary->state->fb = fb; primary->crtc = primary->state->crtc = &intel_crtc->base; @@ -3298,7 +3289,6 @@ static void i9xx_update_primary_plane(struct intel_plane *primary, const struct intel_plane_state *plane_state) { struct drm_i915_private *dev_priv = to_i915(primary->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); const struct drm_framebuffer *fb = plane_state->base.fb; enum plane plane = primary->plane; u32 linear_offset; @@ -3307,16 +3297,14 @@ static void i9xx_update_primary_plane(struct intel_plane *primary, int x = plane_state->main.x; int y = plane_state->main.y; unsigned long irqflags; + u32 dspaddr_offset; linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); if (INTEL_GEN(dev_priv) >= 4) - crtc->dspaddr_offset = plane_state->main.offset; + dspaddr_offset = plane_state->main.offset; else - crtc->dspaddr_offset = linear_offset; - - crtc->adjusted_x = x; - crtc->adjusted_y = y; + dspaddr_offset = linear_offset; spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); @@ -3342,18 +3330,18 @@ static void i9xx_update_primary_plane(struct intel_plane *primary, if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { I915_WRITE_FW(DSPSURF(plane), intel_plane_ggtt_offset(plane_state) + - crtc->dspaddr_offset); + dspaddr_offset); I915_WRITE_FW(DSPOFFSET(plane), (y << 16) | x); } else if (INTEL_GEN(dev_priv) >= 4) { I915_WRITE_FW(DSPSURF(plane), intel_plane_ggtt_offset(plane_state) + - crtc->dspaddr_offset); + dspaddr_offset); I915_WRITE_FW(DSPTILEOFF(plane), (y << 16) | x); I915_WRITE_FW(DSPLINOFF(plane), linear_offset); } else { I915_WRITE_FW(DSPADDR(plane), intel_plane_ggtt_offset(plane_state) + - crtc->dspaddr_offset); + dspaddr_offset); } POSTING_READ_FW(reg); @@ -3553,100 +3541,6 @@ u32 skl_plane_ctl(const struct intel_crtc_state *crtc_state, return plane_ctl; } -static void skylake_update_primary_plane(struct intel_plane *plane, - const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) -{ - struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - const struct drm_framebuffer *fb = plane_state->base.fb; - enum plane_id plane_id = plane->id; - enum pipe pipe = plane->pipe; - u32 plane_ctl = plane_state->ctl; - unsigned int rotation = plane_state->base.rotation; - u32 stride = skl_plane_stride(fb, 0, rotation); - u32 aux_stride = skl_plane_stride(fb, 1, rotation); - u32 surf_addr = plane_state->main.offset; - int scaler_id = plane_state->scaler_id; - int src_x = plane_state->main.x; - int src_y = plane_state->main.y; - int src_w = drm_rect_width(&plane_state->base.src) >> 16; - int src_h = drm_rect_height(&plane_state->base.src) >> 16; - int dst_x = plane_state->base.dst.x1; - int dst_y = plane_state->base.dst.y1; - int dst_w = drm_rect_width(&plane_state->base.dst); - int dst_h = drm_rect_height(&plane_state->base.dst); - unsigned long irqflags; - - /* Sizes are 0 based */ - src_w--; - src_h--; - dst_w--; - dst_h--; - - crtc->dspaddr_offset = surf_addr; - - crtc->adjusted_x = src_x; - crtc->adjusted_y = src_y; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - if (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) { - I915_WRITE_FW(PLANE_COLOR_CTL(pipe, plane_id), - PLANE_COLOR_PIPE_GAMMA_ENABLE | - PLANE_COLOR_PIPE_CSC_ENABLE | - PLANE_COLOR_PLANE_GAMMA_DISABLE); - } - - I915_WRITE_FW(PLANE_CTL(pipe, plane_id), plane_ctl); - I915_WRITE_FW(PLANE_OFFSET(pipe, plane_id), (src_y << 16) | src_x); - I915_WRITE_FW(PLANE_STRIDE(pipe, plane_id), stride); - I915_WRITE_FW(PLANE_SIZE(pipe, plane_id), (src_h << 16) | src_w); - I915_WRITE_FW(PLANE_AUX_DIST(pipe, plane_id), - (plane_state->aux.offset - surf_addr) | aux_stride); - I915_WRITE_FW(PLANE_AUX_OFFSET(pipe, plane_id), - (plane_state->aux.y << 16) | plane_state->aux.x); - - if (scaler_id >= 0) { - uint32_t ps_ctrl = 0; - - WARN_ON(!dst_w || !dst_h); - ps_ctrl = PS_SCALER_EN | PS_PLANE_SEL(plane_id) | - crtc_state->scaler_state.scalers[scaler_id].mode; - I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id), ps_ctrl); - I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0); - I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (dst_x << 16) | dst_y); - I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (dst_w << 16) | dst_h); - I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0); - } else { - I915_WRITE_FW(PLANE_POS(pipe, plane_id), (dst_y << 16) | dst_x); - } - - I915_WRITE_FW(PLANE_SURF(pipe, plane_id), - intel_plane_ggtt_offset(plane_state) + surf_addr); - - POSTING_READ_FW(PLANE_SURF(pipe, plane_id)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); -} - -static void skylake_disable_primary_plane(struct intel_plane *primary, - struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(primary->base.dev); - enum plane_id plane_id = primary->id; - enum pipe pipe = primary->pipe; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - - I915_WRITE_FW(PLANE_CTL(pipe, plane_id), 0); - I915_WRITE_FW(PLANE_SURF(pipe, plane_id), 0); - POSTING_READ_FW(PLANE_SURF(pipe, plane_id)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); -} - static int __intel_display_resume(struct drm_device *dev, struct drm_atomic_state *state, @@ -3701,7 +3595,7 @@ void intel_prepare_reset(struct drm_i915_private *dev_priv) /* reset doesn't touch the display */ - if (!i915.force_reset_modeset_test && + if (!i915_modparams.force_reset_modeset_test && !gpu_reset_clobbers_display(dev_priv)) return; @@ -3757,7 +3651,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) int ret; /* reset doesn't touch the display */ - if (!i915.force_reset_modeset_test && + if (!i915_modparams.force_reset_modeset_test && !gpu_reset_clobbers_display(dev_priv)) return; @@ -3782,6 +3676,7 @@ void intel_finish_reset(struct drm_i915_private *dev_priv) intel_pps_unlock_regs_wa(dev_priv); intel_modeset_init_hw(dev); + intel_init_clock_gating(dev_priv); spin_lock_irq(&dev_priv->irq_lock); if (dev_priv->display.hpd_irq_setup) @@ -4955,9 +4850,10 @@ void hsw_enable_ips(struct intel_crtc *crtc) assert_plane_enabled(dev_priv, crtc->plane); if (IS_BROADWELL(dev_priv)) { - mutex_lock(&dev_priv->rps.hw_lock); - WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0xc0000000)); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); + WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, + IPS_ENABLE | IPS_PCODE_CONTROL)); + mutex_unlock(&dev_priv->pcu_lock); /* Quoting Art Runyan: "its not safe to expect any particular * value in IPS_CTL bit 31 after enabling IPS through the * mailbox." Moreover, the mailbox may return a bogus state, @@ -4987,9 +4883,9 @@ void hsw_disable_ips(struct intel_crtc *crtc) assert_plane_enabled(dev_priv, crtc->plane); if (IS_BROADWELL(dev_priv)) { - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); WARN_ON(sandybridge_pcode_write(dev_priv, DISPLAY_IPS_CONTROL, 0)); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); /* wait for pcode to finish disabling IPS, which may take up to 42ms */ if (intel_wait_for_register(dev_priv, IPS_CTL, IPS_ENABLE, 0, @@ -5458,6 +5354,20 @@ static bool hsw_crtc_supports_ips(struct intel_crtc *crtc) return HAS_IPS(to_i915(crtc->base.dev)) && crtc->pipe == PIPE_A; } +static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv, + enum pipe pipe, bool apply) +{ + u32 val = I915_READ(CLKGATE_DIS_PSL(pipe)); + u32 mask = DPF_GATING_DIS | DPF_RAM_GATING_DIS | DPFR_GATING_DIS; + + if (apply) + val |= mask; + else + val &= ~mask; + + I915_WRITE(CLKGATE_DIS_PSL(pipe), val); +} + static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, struct drm_atomic_state *old_state) { @@ -5468,13 +5378,11 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; struct intel_atomic_state *old_intel_state = to_intel_atomic_state(old_state); + bool psl_clkgate_wa; if (WARN_ON(intel_crtc->active)) return; - if (intel_crtc->config->has_pch_encoder) - intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); - intel_encoders_pre_pll_enable(crtc, pipe_config, old_state); if (intel_crtc->config->shared_dpll) @@ -5508,19 +5416,17 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_crtc->active = true; - if (intel_crtc->config->has_pch_encoder) - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, false); - else - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_encoders_pre_enable(crtc, pipe_config, old_state); - if (intel_crtc->config->has_pch_encoder) - dev_priv->display.fdi_link_train(intel_crtc, pipe_config); - if (!transcoder_is_dsi(cpu_transcoder)) intel_ddi_enable_pipe_clock(pipe_config); + /* Display WA #1180: WaDisableScalarClockGating: glk, cnl */ + psl_clkgate_wa = (IS_GEMINILAKE(dev_priv) || IS_CANNONLAKE(dev_priv)) && + intel_crtc->config->pch_pfit.enabled; + if (psl_clkgate_wa) + glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, true); + if (INTEL_GEN(dev_priv) >= 9) skylake_pfit_enable(intel_crtc); else @@ -5554,11 +5460,9 @@ static void haswell_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_enable(crtc, pipe_config, old_state); - if (intel_crtc->config->has_pch_encoder) { + if (psl_clkgate_wa) { intel_wait_for_vblank(dev_priv, pipe); - intel_wait_for_vblank(dev_priv, pipe); - intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); - intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); + glk_pipe_scaler_clock_gating_wa(dev_priv, pipe, false); } /* If we change the relative order between pipe/planes enabling, we need @@ -5654,9 +5558,6 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, struct intel_crtc *intel_crtc = to_intel_crtc(crtc); enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; - if (intel_crtc->config->has_pch_encoder) - intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, false); - intel_encoders_disable(crtc, old_crtc_state, old_state); drm_crtc_vblank_off(crtc); @@ -5681,9 +5582,6 @@ static void haswell_crtc_disable(struct intel_crtc_state *old_crtc_state, intel_ddi_disable_pipe_clock(intel_crtc->config); intel_encoders_post_disable(crtc, old_crtc_state, old_state); - - if (old_crtc_state->has_pch_encoder) - intel_set_pch_fifo_underrun_reporting(dev_priv, PIPE_A, true); } static void i9xx_pfit_enable(struct intel_crtc *crtc) @@ -5893,7 +5791,7 @@ static void i9xx_crtc_enable(struct intel_crtc_state *pipe_config, intel_encoders_pre_enable(crtc, pipe_config, old_state); - i9xx_enable_pll(intel_crtc); + i9xx_enable_pll(intel_crtc, pipe_config); i9xx_pfit_enable(intel_crtc); @@ -6145,6 +6043,19 @@ struct intel_connector *intel_connector_alloc(void) return connector; } +/* + * Free the bits allocated by intel_connector_alloc. + * This should only be used after intel_connector_alloc has returned + * successfully, and before drm_connector_init returns successfully. + * Otherwise the destroy callbacks for the connector and the state should + * take care of proper cleanup/free + */ +void intel_connector_free(struct intel_connector *connector) +{ + kfree(to_intel_digital_connector_state(connector->base.state)); + kfree(connector); +} + /* Simple connector->get_hw_state implementation for encoders that support only * one connector and no cloning and hence the encoder state determines the state * of the connector. */ @@ -6312,7 +6223,7 @@ static void hsw_compute_ips_config(struct intel_crtc *crtc, struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - pipe_config->ips_enabled = i915.enable_ips && + pipe_config->ips_enabled = i915_modparams.enable_ips && hsw_crtc_supports_ips(crtc) && pipe_config_supports_ips(dev_priv, pipe_config); } @@ -6493,8 +6404,8 @@ intel_link_compute_m_n(int bits_per_pixel, int nlanes, static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv) { - if (i915.panel_use_ssc >= 0) - return i915.panel_use_ssc != 0; + if (i915_modparams.panel_use_ssc >= 0) + return i915_modparams.panel_use_ssc != 0; return dev_priv->vbt.lvds_use_ssc && !(dev_priv->quirks & QUIRK_LVDS_SSC_DISABLE); } @@ -6528,11 +6439,9 @@ static void i9xx_update_pll_dividers(struct intel_crtc *crtc, crtc_state->dpll_hw_state.fp0 = fp; - crtc->lowfreq_avail = false; if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && reduced_clock) { crtc_state->dpll_hw_state.fp1 = fp2; - crtc->lowfreq_avail = true; } else { crtc_state->dpll_hw_state.fp1 = fp; } @@ -7227,15 +7136,6 @@ static void i9xx_set_pipeconf(struct intel_crtc *intel_crtc) } } - if (HAS_PIPE_CXSR(dev_priv)) { - if (intel_crtc->lowfreq_avail) { - DRM_DEBUG_KMS("enabling CxSR downclocking\n"); - pipeconf |= PIPECONF_CXSR_DOWNCLOCK; - } else { - DRM_DEBUG_KMS("disabling CxSR downclocking\n"); - } - } - if (intel_crtc->config->base.adjusted_mode.flags & DRM_MODE_FLAG_INTERLACE) { if (INTEL_GEN(dev_priv) < 4 || intel_crtc_has_type(intel_crtc->config, INTEL_OUTPUT_SDVO)) @@ -8371,8 +8271,6 @@ static int ironlake_crtc_compute_clock(struct intel_crtc *crtc, memset(&crtc_state->dpll_hw_state, 0, sizeof(crtc_state->dpll_hw_state)); - crtc->lowfreq_avail = false; - /* CPU eDP is the only output that doesn't need a PCH PLL of its own. */ if (!crtc_state->has_pch_encoder) return 0; @@ -8845,11 +8743,11 @@ static uint32_t hsw_read_dcomp(struct drm_i915_private *dev_priv) static void hsw_write_dcomp(struct drm_i915_private *dev_priv, uint32_t val) { if (IS_HASWELL(dev_priv)) { - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); if (sandybridge_pcode_write(dev_priv, GEN6_PCODE_WRITE_D_COMP, val)) DRM_DEBUG_KMS("Failed to write to D_COMP\n"); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } else { I915_WRITE(D_COMP_BDW, val); POSTING_READ(D_COMP_BDW); @@ -9031,8 +8929,6 @@ static int haswell_crtc_compute_clock(struct intel_crtc *crtc, } } - crtc->lowfreq_avail = false; - return 0; } @@ -9309,11 +9205,11 @@ static bool haswell_get_pipe_config(struct intel_crtc *crtc, pipe_config->gamma_mode = I915_READ(GAMMA_MODE(crtc->pipe)) & GAMMA_MODE_MODE_MASK; - if (IS_BROADWELL(dev_priv) || dev_priv->info.gen >= 9) { + if (IS_BROADWELL(dev_priv) || INTEL_GEN(dev_priv) >= 9) { u32 tmp = I915_READ(PIPEMISC(crtc->pipe)); bool clrspace_yuv = tmp & PIPEMISC_OUTPUT_COLORSPACE_YUV; - if (IS_GEMINILAKE(dev_priv) || dev_priv->info.gen >= 10) { + if (IS_GEMINILAKE(dev_priv) || INTEL_GEN(dev_priv) >= 10) { bool blend_mode_420 = tmp & PIPEMISC_YUV420_MODE_FULL_BLEND; @@ -9853,7 +9749,7 @@ mode_fits_in_fbdev(struct drm_device *dev, if (obj->base.size < mode->vdisplay * fb->pitches[0]) return NULL; - drm_framebuffer_reference(fb); + drm_framebuffer_get(fb); return fb; #else return NULL; @@ -10034,7 +9930,7 @@ found: if (ret) goto fail; - drm_framebuffer_unreference(fb); + drm_framebuffer_put(fb); ret = drm_atomic_set_mode_for_crtc(&crtc_state->base, mode); if (ret) @@ -10224,7 +10120,7 @@ int intel_dotclock_calculate(int link_freq, if (!m_n->link_n) return 0; - return div_u64((u64)m_n->link_m * link_freq, m_n->link_n); + return div_u64(mul_u32_u32(m_n->link_m, link_freq), m_n->link_n); } static void ironlake_pch_clock_get(struct intel_crtc *crtc, @@ -10245,58 +10141,44 @@ static void ironlake_pch_clock_get(struct intel_crtc *crtc, &pipe_config->fdi_m_n); } -/** Returns the currently programmed mode of the given pipe. */ -struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, - struct drm_crtc *crtc) +/* Returns the currently programmed mode of the given encoder. */ +struct drm_display_mode * +intel_encoder_current_mode(struct intel_encoder *encoder) { - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); - enum transcoder cpu_transcoder = intel_crtc->config->cpu_transcoder; + struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); + struct intel_crtc_state *crtc_state; struct drm_display_mode *mode; - struct intel_crtc_state *pipe_config; - int htot = I915_READ(HTOTAL(cpu_transcoder)); - int hsync = I915_READ(HSYNC(cpu_transcoder)); - int vtot = I915_READ(VTOTAL(cpu_transcoder)); - int vsync = I915_READ(VSYNC(cpu_transcoder)); - enum pipe pipe = intel_crtc->pipe; + struct intel_crtc *crtc; + enum pipe pipe; + + if (!encoder->get_hw_state(encoder, &pipe)) + return NULL; + + crtc = intel_get_crtc_for_pipe(dev_priv, pipe); mode = kzalloc(sizeof(*mode), GFP_KERNEL); if (!mode) return NULL; - pipe_config = kzalloc(sizeof(*pipe_config), GFP_KERNEL); - if (!pipe_config) { + crtc_state = kzalloc(sizeof(*crtc_state), GFP_KERNEL); + if (!crtc_state) { kfree(mode); return NULL; } - /* - * Construct a pipe_config sufficient for getting the clock info - * back out of crtc_clock_get. - * - * Note, if LVDS ever uses a non-1 pixel multiplier, we'll need - * to use a real value here instead. - */ - pipe_config->cpu_transcoder = (enum transcoder) pipe; - pipe_config->pixel_multiplier = 1; - pipe_config->dpll_hw_state.dpll = I915_READ(DPLL(pipe)); - pipe_config->dpll_hw_state.fp0 = I915_READ(FP0(pipe)); - pipe_config->dpll_hw_state.fp1 = I915_READ(FP1(pipe)); - i9xx_crtc_clock_get(intel_crtc, pipe_config); - - mode->clock = pipe_config->port_clock / pipe_config->pixel_multiplier; - mode->hdisplay = (htot & 0xffff) + 1; - mode->htotal = ((htot & 0xffff0000) >> 16) + 1; - mode->hsync_start = (hsync & 0xffff) + 1; - mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; - mode->vdisplay = (vtot & 0xffff) + 1; - mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; - mode->vsync_start = (vsync & 0xffff) + 1; - mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; + crtc_state->base.crtc = &crtc->base; - drm_mode_set_name(mode); + if (!dev_priv->display.get_pipe_config(crtc, crtc_state)) { + kfree(crtc_state); + kfree(mode); + return NULL; + } - kfree(pipe_config); + encoder->get_config(encoder, crtc_state); + + intel_mode_from_pipe_config(mode, crtc_state); + + kfree(crtc_state); return mode; } @@ -10683,6 +10565,52 @@ intel_dump_m_n_config(struct intel_crtc_state *pipe_config, char *id, m_n->link_m, m_n->link_n, m_n->tu); } +#define OUTPUT_TYPE(x) [INTEL_OUTPUT_ ## x] = #x + +static const char * const output_type_str[] = { + OUTPUT_TYPE(UNUSED), + OUTPUT_TYPE(ANALOG), + OUTPUT_TYPE(DVO), + OUTPUT_TYPE(SDVO), + OUTPUT_TYPE(LVDS), + OUTPUT_TYPE(TVOUT), + OUTPUT_TYPE(HDMI), + OUTPUT_TYPE(DP), + OUTPUT_TYPE(EDP), + OUTPUT_TYPE(DSI), + OUTPUT_TYPE(UNKNOWN), + OUTPUT_TYPE(DP_MST), +}; + +#undef OUTPUT_TYPE + +static void snprintf_output_types(char *buf, size_t len, + unsigned int output_types) +{ + char *str = buf; + int i; + + str[0] = '\0'; + + for (i = 0; i < ARRAY_SIZE(output_type_str); i++) { + int r; + + if ((output_types & BIT(i)) == 0) + continue; + + r = snprintf(str, len, "%s%s", + str != buf ? "," : "", output_type_str[i]); + if (r >= len) + break; + str += r; + len -= r; + + output_types &= ~BIT(i); + } + + WARN_ON_ONCE(output_types != 0); +} + static void intel_dump_pipe_config(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config, const char *context) @@ -10693,10 +10621,15 @@ static void intel_dump_pipe_config(struct intel_crtc *crtc, struct intel_plane *intel_plane; struct intel_plane_state *state; struct drm_framebuffer *fb; + char buf[64]; DRM_DEBUG_KMS("[CRTC:%d:%s]%s\n", crtc->base.base.id, crtc->base.name, context); + snprintf_output_types(buf, sizeof(buf), pipe_config->output_types); + DRM_DEBUG_KMS("output_types: %s (0x%x)\n", + buf, pipe_config->output_types); + DRM_DEBUG_KMS("cpu_transcoder: %s, pipe bpp: %i, dithering: %i\n", transcoder_name(pipe_config->cpu_transcoder), pipe_config->pipe_bpp, pipe_config->dither); @@ -11336,6 +11269,18 @@ intel_pipe_config_compare(struct drm_i915_private *dev_priv, PIPE_CONF_CHECK_X(dpll_hw_state.ctrl1); PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr1); PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr2); + PIPE_CONF_CHECK_X(dpll_hw_state.cfgcr0); + PIPE_CONF_CHECK_X(dpll_hw_state.ebb0); + PIPE_CONF_CHECK_X(dpll_hw_state.ebb4); + PIPE_CONF_CHECK_X(dpll_hw_state.pll0); + PIPE_CONF_CHECK_X(dpll_hw_state.pll1); + PIPE_CONF_CHECK_X(dpll_hw_state.pll2); + PIPE_CONF_CHECK_X(dpll_hw_state.pll3); + PIPE_CONF_CHECK_X(dpll_hw_state.pll6); + PIPE_CONF_CHECK_X(dpll_hw_state.pll8); + PIPE_CONF_CHECK_X(dpll_hw_state.pll9); + PIPE_CONF_CHECK_X(dpll_hw_state.pll10); + PIPE_CONF_CHECK_X(dpll_hw_state.pcsdw12); PIPE_CONF_CHECK_X(dsi_pll.ctrl); PIPE_CONF_CHECK_X(dsi_pll.div); @@ -12084,7 +12029,7 @@ static int intel_atomic_check(struct drm_device *dev, return ret; } - if (i915.fastboot && + if (i915_modparams.fastboot && intel_pipe_config_compare(dev_priv, to_intel_crtc_state(old_crtc_state), pipe_config, true)) { @@ -12220,7 +12165,10 @@ static void skl_update_crtcs(struct drm_atomic_state *state) if (updated & cmask || !cstate->base.active) continue; - if (skl_ddb_allocation_overlaps(entries, &cstate->wm.skl.ddb, i)) + if (skl_ddb_allocation_overlaps(dev_priv, + entries, + &cstate->wm.skl.ddb, + i)) continue; updated |= cmask; @@ -12299,7 +12247,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) struct drm_crtc_state *old_crtc_state, *new_crtc_state; struct drm_crtc *crtc; struct intel_crtc_state *intel_cstate; - bool hw_check = intel_state->modeset; u64 put_domains[I915_MAX_PIPES] = {}; int i; @@ -12315,7 +12262,6 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state) if (needs_modeset(new_crtc_state) || to_intel_crtc_state(new_crtc_state)->update_pipe) { - hw_check = true; put_domains[to_intel_crtc(crtc)->pipe] = modeset_get_crtc_power_domains(crtc, @@ -12517,21 +12463,10 @@ static int intel_atomic_commit(struct drm_device *dev, struct drm_i915_private *dev_priv = to_i915(dev); int ret = 0; - ret = drm_atomic_helper_setup_commit(state, nonblock); - if (ret) - return ret; - drm_atomic_state_get(state); i915_sw_fence_init(&intel_state->commit_ready, intel_atomic_commit_ready); - ret = intel_atomic_prepare_commit(dev, state); - if (ret) { - DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret); - i915_sw_fence_commit(&intel_state->commit_ready); - return ret; - } - /* * The intel_legacy_cursor_update() fast path takes care * of avoiding the vblank waits for simple cursor @@ -12540,19 +12475,37 @@ static int intel_atomic_commit(struct drm_device *dev, * updates happen during the correct frames. Gen9+ have * double buffered watermarks and so shouldn't need this. * - * Do this after drm_atomic_helper_setup_commit() and - * intel_atomic_prepare_commit() because we still want - * to skip the flip and fb cleanup waits. Although that - * does risk yanking the mapping from under the display - * engine. + * Unset state->legacy_cursor_update before the call to + * drm_atomic_helper_setup_commit() because otherwise + * drm_atomic_helper_wait_for_flip_done() is a noop and + * we get FIFO underruns because we didn't wait + * for vblank. * * FIXME doing watermarks and fb cleanup from a vblank worker * (assuming we had any) would solve these problems. */ - if (INTEL_GEN(dev_priv) < 9) - state->legacy_cursor_update = false; + if (INTEL_GEN(dev_priv) < 9 && state->legacy_cursor_update) { + struct intel_crtc_state *new_crtc_state; + struct intel_crtc *crtc; + int i; + + for_each_new_intel_crtc_in_state(intel_state, crtc, new_crtc_state, i) + if (new_crtc_state->wm.need_postvbl_update || + new_crtc_state->update_wm_post) + state->legacy_cursor_update = false; + } + + ret = intel_atomic_prepare_commit(dev, state); + if (ret) { + DRM_DEBUG_ATOMIC("Preparing state failed with %i\n", ret); + i915_sw_fence_commit(&intel_state->commit_ready); + return ret; + } + + ret = drm_atomic_helper_setup_commit(state, nonblock); + if (!ret) + ret = drm_atomic_helper_swap_state(state, true); - ret = drm_atomic_helper_swap_state(state, true); if (ret) { i915_sw_fence_commit(&intel_state->commit_ready); @@ -13231,8 +13184,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) num_formats = ARRAY_SIZE(skl_primary_formats); modifiers = skl_format_modifiers_ccs; - primary->update_plane = skylake_update_primary_plane; - primary->disable_plane = skylake_disable_primary_plane; + primary->update_plane = skl_update_plane; + primary->disable_plane = skl_disable_plane; } else if (INTEL_GEN(dev_priv) >= 9) { intel_primary_formats = skl_primary_formats; num_formats = ARRAY_SIZE(skl_primary_formats); @@ -13241,8 +13194,8 @@ intel_primary_plane_create(struct drm_i915_private *dev_priv, enum pipe pipe) else modifiers = skl_format_modifiers_noccs; - primary->update_plane = skylake_update_primary_plane; - primary->disable_plane = skylake_disable_primary_plane; + primary->update_plane = skl_update_plane; + primary->disable_plane = skl_disable_plane; } else if (INTEL_GEN(dev_priv) >= 4) { intel_primary_formats = i965_primary_formats; num_formats = ARRAY_SIZE(i965_primary_formats); @@ -13513,7 +13466,7 @@ int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_crtc *drmmode_crtc; struct intel_crtc *crtc; - drmmode_crtc = drm_crtc_find(dev, pipe_from_crtc_id->crtc_id); + drmmode_crtc = drm_crtc_find(dev, file, pipe_from_crtc_id->crtc_id); if (!drmmode_crtc) return -ENOENT; @@ -14220,7 +14173,7 @@ void intel_init_display_hooks(struct drm_i915_private *dev_priv) dev_priv->display.fdi_link_train = hsw_fdi_link_train; } - if (dev_priv->info.gen >= 9) + if (INTEL_GEN(dev_priv) >= 9) dev_priv->display.update_crtcs = skl_update_crtcs; else dev_priv->display.update_crtcs = intel_update_crtcs; @@ -14400,8 +14353,6 @@ void intel_modeset_init_hw(struct drm_device *dev) intel_update_cdclk(dev_priv); dev_priv->cdclk.logical = dev_priv->cdclk.actual = dev_priv->cdclk.hw; - - intel_init_clock_gating(dev_priv); } /* @@ -14751,10 +14702,10 @@ static struct intel_connector *intel_encoder_find_connector(struct intel_encoder } static bool has_pch_trancoder(struct drm_i915_private *dev_priv, - enum transcoder pch_transcoder) + enum pipe pch_transcoder) { return HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || - (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == TRANSCODER_A); + (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A); } static void intel_sanitize_crtc(struct intel_crtc *crtc, @@ -14837,7 +14788,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, * PCH transcoders B and C would prevent enabling the south * error interrupt (see cpt_can_enable_serr_int()). */ - if (has_pch_trancoder(dev_priv, (enum transcoder)crtc->pipe)) + if (has_pch_trancoder(dev_priv, crtc->pipe)) crtc->pch_fifo_underrun_disabled = true; } } @@ -15113,6 +15064,15 @@ intel_modeset_setup_hw_state(struct drm_device *dev, struct intel_encoder *encoder; int i; + if (IS_HASWELL(dev_priv)) { + /* + * WaRsPkgCStateDisplayPMReq:hsw + * System hang if this isn't done before disabling all planes! + */ + I915_WRITE(CHICKEN_PAR1_1, + I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); + } + intel_modeset_readout_hw_state(dev); /* HW state is read out, now we need to sanitize this mess. */ @@ -15194,6 +15154,7 @@ void intel_display_resume(struct drm_device *dev) if (!ret) ret = __intel_display_resume(dev, state, &ctx); + intel_enable_ipc(dev_priv); drm_modeset_drop_locks(&ctx); drm_modeset_acquire_fini(&ctx); @@ -15209,6 +15170,8 @@ void intel_modeset_gem_init(struct drm_device *dev) intel_init_gt_powersave(dev_priv); + intel_init_clock_gating(dev_priv); + intel_setup_overlay(dev_priv); } diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 6fce08209b4f..d11281004109 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -42,6 +42,7 @@ #include "i915_drv.h" #define DP_LINK_CHECK_TIMEOUT (10 * 1000) +#define DP_DPRX_ESI_LEN 14 /* Compliance test status bits */ #define INTEL_DP_RESOLUTION_SHIFT_MASK 0 @@ -136,32 +137,20 @@ static void vlv_steal_power_sequencer(struct drm_device *dev, enum pipe pipe); static void intel_dp_unset_edid(struct intel_dp *intel_dp); -static int intel_dp_num_rates(u8 link_bw_code) -{ - switch (link_bw_code) { - default: - WARN(1, "invalid max DP link bw val %x, using 1.62Gbps\n", - link_bw_code); - case DP_LINK_BW_1_62: - return 1; - case DP_LINK_BW_2_7: - return 2; - case DP_LINK_BW_5_4: - return 3; - } -} - /* update sink rates from dpcd */ static void intel_dp_set_sink_rates(struct intel_dp *intel_dp) { - int i, num_rates; + int i, max_rate; - num_rates = intel_dp_num_rates(intel_dp->dpcd[DP_MAX_LINK_RATE]); + max_rate = drm_dp_bw_code_to_link_rate(intel_dp->dpcd[DP_MAX_LINK_RATE]); - for (i = 0; i < num_rates; i++) + for (i = 0; i < ARRAY_SIZE(default_rates); i++) { + if (default_rates[i] > max_rate) + break; intel_dp->sink_rates[i] = default_rates[i]; + } - intel_dp->num_sink_rates = num_rates; + intel_dp->num_sink_rates = i; } /* Theoretical max between source and sink */ @@ -253,15 +242,15 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) } else if (IS_GEN9_BC(dev_priv)) { source_rates = skl_rates; size = ARRAY_SIZE(skl_rates); - } else { + } else if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) || + IS_BROADWELL(dev_priv)) { source_rates = default_rates; size = ARRAY_SIZE(default_rates); + } else { + source_rates = default_rates; + size = ARRAY_SIZE(default_rates) - 1; } - /* This depends on the fact that 5.4 is last value in the array */ - if (!intel_dp_source_supports_hbr2(intel_dp)) - size--; - intel_dp->source_rates = source_rates; intel_dp->num_source_rates = size; } @@ -1018,7 +1007,7 @@ static uint32_t g4x_get_aux_send_ctl(struct intel_dp *intel_dp, else precharge = 5; - if (IS_BROADWELL(dev_priv) && intel_dig_port->port == PORT_A) + if (IS_BROADWELL(dev_priv)) timeout = DP_AUX_CH_CTL_TIME_OUT_600us; else timeout = DP_AUX_CH_CTL_TIME_OUT_400us; @@ -1043,7 +1032,7 @@ static uint32_t skl_get_aux_send_ctl(struct intel_dp *intel_dp, DP_AUX_CH_CTL_DONE | (has_aux_irq ? DP_AUX_CH_CTL_INTERRUPT : 0) | DP_AUX_CH_CTL_TIME_OUT_ERROR | - DP_AUX_CH_CTL_TIME_OUT_1600us | + DP_AUX_CH_CTL_TIME_OUT_MAX | DP_AUX_CH_CTL_RECEIVE_ERROR | (send_bytes << DP_AUX_CH_CTL_MESSAGE_SIZE_SHIFT) | DP_AUX_CH_CTL_FW_SYNC_PULSE_SKL(32) | @@ -1481,14 +1470,9 @@ intel_dp_aux_init(struct intel_dp *intel_dp) bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp) { - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); + int max_rate = intel_dp->source_rates[intel_dp->num_source_rates - 1]; - if ((IS_HASWELL(dev_priv) && !IS_HSW_ULX(dev_priv)) || - IS_BROADWELL(dev_priv) || (INTEL_GEN(dev_priv) >= 9)) - return true; - else - return false; + return max_rate >= 540000; } static void @@ -1848,6 +1832,8 @@ found: if (!HAS_DDI(dev_priv)) intel_dp_set_clock(encoder, pipe_config); + intel_psr_compute_config(intel_dp, pipe_config); + return true; } @@ -2307,8 +2293,8 @@ static void edp_panel_off(struct intel_dp *intel_dp) I915_WRITE(pp_ctrl_reg, pp); POSTING_READ(pp_ctrl_reg); - intel_dp->panel_power_off_time = ktime_get_boottime(); wait_panel_off(intel_dp); + intel_dp->panel_power_off_time = ktime_get_boottime(); /* We got a reference when we enabled the VDD. */ intel_display_power_put(dev_priv, intel_dp->aux_power_domain); @@ -2692,24 +2678,46 @@ static void intel_disable_dp(struct intel_encoder *encoder, const struct drm_connector_state *old_conn_state) { struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); if (old_crtc_state->has_audio) intel_audio_codec_disable(encoder); - if (HAS_PSR(dev_priv) && !HAS_DDI(dev_priv)) - intel_psr_disable(intel_dp, old_crtc_state); - /* Make sure the panel is off before trying to change the mode. But also * ensure that we have vdd while we switch off the panel. */ intel_edp_panel_vdd_on(intel_dp); intel_edp_backlight_off(old_conn_state); intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); intel_edp_panel_off(intel_dp); +} + +static void g4x_disable_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + + intel_disable_dp(encoder, old_crtc_state, old_conn_state); /* disable the port before the pipe on g4x */ - if (INTEL_GEN(dev_priv) < 5) - intel_dp_link_down(intel_dp); + intel_dp_link_down(intel_dp); +} + +static void ilk_disable_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + intel_disable_dp(encoder, old_crtc_state, old_conn_state); +} + +static void vlv_disable_dp(struct intel_encoder *encoder, + const struct intel_crtc_state *old_crtc_state, + const struct drm_connector_state *old_conn_state) +{ + struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base); + + intel_psr_disable(intel_dp, old_crtc_state); + + intel_disable_dp(encoder, old_crtc_state, old_conn_state); } static void ilk_post_disable_dp(struct intel_encoder *encoder, @@ -3147,9 +3155,7 @@ intel_dp_voltage_max(struct intel_dp *intel_dp) struct drm_i915_private *dev_priv = to_i915(intel_dp_to_dev(intel_dp)); enum port port = dp_to_dig_port(intel_dp)->port; - if (IS_GEN9_LP(dev_priv)) - return DP_TRAIN_VOLTAGE_SWING_LEVEL_3; - else if (INTEL_GEN(dev_priv) >= 9) { + if (INTEL_GEN(dev_priv) >= 9) { struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; return intel_ddi_dp_voltage_max(encoder); } else if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) @@ -3826,7 +3832,7 @@ intel_dp_can_mst(struct intel_dp *intel_dp) { u8 mstm_cap; - if (!i915.enable_dp_mst) + if (!i915_modparams.enable_dp_mst) return false; if (!intel_dp->can_mst) @@ -3844,7 +3850,7 @@ intel_dp_can_mst(struct intel_dp *intel_dp) static void intel_dp_configure_mst(struct intel_dp *intel_dp) { - if (!i915.enable_dp_mst) + if (!i915_modparams.enable_dp_mst) return; if (!intel_dp->can_mst) @@ -3991,15 +3997,9 @@ intel_dp_get_sink_irq(struct intel_dp *intel_dp, u8 *sink_irq_vector) static bool intel_dp_get_sink_irq_esi(struct intel_dp *intel_dp, u8 *sink_irq_vector) { - int ret; - - ret = drm_dp_dpcd_read(&intel_dp->aux, - DP_SINK_COUNT_ESI, - sink_irq_vector, 14); - if (ret != 14) - return false; - - return true; + return drm_dp_dpcd_read(&intel_dp->aux, DP_SINK_COUNT_ESI, + sink_irq_vector, DP_DPRX_ESI_LEN) == + DP_DPRX_ESI_LEN; } static uint8_t intel_dp_autotest_link_training(struct intel_dp *intel_dp) @@ -4199,7 +4199,7 @@ intel_dp_check_mst_status(struct intel_dp *intel_dp) bool bret; if (intel_dp->is_mst) { - u8 esi[16] = { 0 }; + u8 esi[DP_DPRX_ESI_LEN] = { 0 }; int ret = 0; int retry; bool handled; @@ -4736,10 +4736,6 @@ intel_dp_long_pulse(struct intel_connector *intel_connector) if (intel_encoder->type != INTEL_OUTPUT_EDP) intel_encoder->type = INTEL_OUTPUT_DP; - DRM_DEBUG_KMS("Display Port TPS3 support: source %s, sink %s\n", - yesno(intel_dp_source_supports_hbr2(intel_dp)), - yesno(drm_dp_tps3_supported(intel_dp->dpcd))); - if (intel_dp->reset_link_params) { /* Initial max link lane count */ intel_dp->max_link_lane_count = intel_dp_max_common_lane_count(intel_dp); @@ -5273,7 +5269,7 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, * seems sufficient to avoid this problem. */ if (dev_priv->quirks & QUIRK_INCREASE_T12_DELAY) { - vbt.t11_t12 = max_t(u16, vbt.t11_t12, 900 * 10); + vbt.t11_t12 = max_t(u16, vbt.t11_t12, 1300 * 10); DRM_DEBUG_KMS("Increasing T12 panel delay as per the quirk to %d\n", vbt.t11_t12); } @@ -5467,11 +5463,6 @@ static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv, return; } - /* - * FIXME: This needs proper synchronization with psr state for some - * platforms that cannot have PSR and DRRS enabled at the same time. - */ - dig_port = dp_to_dig_port(intel_dp); encoder = &dig_port->base; intel_crtc = to_intel_crtc(encoder->base.crtc); @@ -5555,6 +5546,11 @@ void intel_edp_drrs_enable(struct intel_dp *intel_dp, return; } + if (dev_priv->psr.enabled) { + DRM_DEBUG_KMS("PSR enabled. Not enabling DRRS.\n"); + return; + } + mutex_lock(&dev_priv->drrs.mutex); if (WARN_ON(dev_priv->drrs.dp)) { DRM_ERROR("DRRS already enabled\n"); @@ -6144,7 +6140,6 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, goto err_encoder_init; intel_encoder->compute_config = intel_dp_compute_config; - intel_encoder->disable = intel_disable_dp; intel_encoder->get_hw_state = intel_dp_get_hw_state; intel_encoder->get_config = intel_dp_get_config; intel_encoder->suspend = intel_dp_encoder_suspend; @@ -6152,18 +6147,24 @@ bool intel_dp_init(struct drm_i915_private *dev_priv, intel_encoder->pre_pll_enable = chv_dp_pre_pll_enable; intel_encoder->pre_enable = chv_pre_enable_dp; intel_encoder->enable = vlv_enable_dp; + intel_encoder->disable = vlv_disable_dp; intel_encoder->post_disable = chv_post_disable_dp; intel_encoder->post_pll_disable = chv_dp_post_pll_disable; } else if (IS_VALLEYVIEW(dev_priv)) { intel_encoder->pre_pll_enable = vlv_dp_pre_pll_enable; intel_encoder->pre_enable = vlv_pre_enable_dp; intel_encoder->enable = vlv_enable_dp; + intel_encoder->disable = vlv_disable_dp; intel_encoder->post_disable = vlv_post_disable_dp; + } else if (INTEL_GEN(dev_priv) >= 5) { + intel_encoder->pre_enable = g4x_pre_enable_dp; + intel_encoder->enable = g4x_enable_dp; + intel_encoder->disable = ilk_disable_dp; + intel_encoder->post_disable = ilk_post_disable_dp; } else { intel_encoder->pre_enable = g4x_pre_enable_dp; intel_encoder->enable = g4x_enable_dp; - if (INTEL_GEN(dev_priv) >= 5) - intel_encoder->post_disable = ilk_post_disable_dp; + intel_encoder->disable = g4x_disable_dp; } intel_dig_port->port = port; diff --git a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c index d2830ba3162e..2bb2ceb9d463 100644 --- a/drivers/gpu/drm/i915/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/intel_dp_aux_backlight.c @@ -264,7 +264,7 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *intel_connector) { struct intel_panel *panel = &intel_connector->panel; - if (!i915.enable_dpcd_backlight) + if (!i915_modparams.enable_dpcd_backlight) return -ENODEV; if (!intel_dp_aux_display_control_capable(intel_connector)) diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 8e3aad0ea60b..772521440a9f 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -133,7 +133,7 @@ static void intel_mst_disable_dp(struct intel_encoder *encoder, to_intel_connector(old_conn_state->connector); int ret; - DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); + DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); drm_dp_mst_reset_vcpi_slots(&intel_dp->mst_mgr, connector->port); @@ -155,8 +155,6 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, struct intel_connector *connector = to_intel_connector(old_conn_state->connector); - DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); - /* this can fail */ drm_dp_check_act_status(&intel_dp->mst_mgr); /* and this can also fail */ @@ -164,15 +162,21 @@ static void intel_mst_post_disable_dp(struct intel_encoder *encoder, drm_dp_mst_deallocate_vcpi(&intel_dp->mst_mgr, connector->port); + /* + * Power down mst path before disabling the port, otherwise we end + * up getting interrupts from the sink upon detecting link loss. + */ + drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, + false); + intel_dp->active_mst_links--; intel_mst->connector = NULL; if (intel_dp->active_mst_links == 0) { intel_dig_port->base.post_disable(&intel_dig_port->base, NULL, NULL); - - intel_dp_sink_dpms(intel_dp, DRM_MODE_DPMS_OFF); } + DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); } static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, @@ -195,8 +199,9 @@ static void intel_mst_pre_enable_dp(struct intel_encoder *encoder, connector->encoder = encoder; intel_mst->connector = connector; - DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); + DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); + drm_dp_send_power_updown_phy(&intel_dp->mst_mgr, connector->port, true); if (intel_dp->active_mst_links == 0) intel_dig_port->base.pre_enable(&intel_dig_port->base, pipe_config, NULL); @@ -229,7 +234,7 @@ static void intel_mst_enable_dp(struct intel_encoder *encoder, enum port port = intel_dig_port->port; int ret; - DRM_DEBUG_KMS("%d\n", intel_dp->active_mst_links); + DRM_DEBUG_KMS("active links %d\n", intel_dp->active_mst_links); if (intel_wait_for_register(dev_priv, DP_TP_STATUS(port), @@ -449,32 +454,52 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo struct intel_dp *intel_dp = container_of(mgr, struct intel_dp, mst_mgr); struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); struct intel_connector *intel_connector; struct drm_connector *connector; - int i; + enum pipe pipe; + int ret; intel_connector = intel_connector_alloc(); if (!intel_connector) return NULL; connector = &intel_connector->base; - drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, DRM_MODE_CONNECTOR_DisplayPort); + ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs, + DRM_MODE_CONNECTOR_DisplayPort); + if (ret) { + intel_connector_free(intel_connector); + return NULL; + } + drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs); intel_connector->get_hw_state = intel_dp_mst_get_hw_state; intel_connector->mst_port = intel_dp; intel_connector->port = port; - for (i = PIPE_A; i <= PIPE_C; i++) { - drm_mode_connector_attach_encoder(&intel_connector->base, - &intel_dp->mst_encoders[i]->base.base); + for_each_pipe(dev_priv, pipe) { + struct drm_encoder *enc = + &intel_dp->mst_encoders[pipe]->base.base; + + ret = drm_mode_connector_attach_encoder(&intel_connector->base, + enc); + if (ret) + goto err; } drm_object_attach_property(&connector->base, dev->mode_config.path_property, 0); drm_object_attach_property(&connector->base, dev->mode_config.tile_property, 0); - drm_mode_connector_set_path_property(connector, pathprop); + ret = drm_mode_connector_set_path_property(connector, pathprop); + if (ret) + goto err; + return connector; + +err: + drm_connector_cleanup(connector); + return NULL; } static void intel_dp_register_mst_connector(struct drm_connector *connector) @@ -494,6 +519,7 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, struct intel_connector *intel_connector = to_intel_connector(connector); struct drm_i915_private *dev_priv = to_i915(connector->dev); + DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); drm_connector_unregister(connector); if (dev_priv->fbdev) @@ -505,7 +531,6 @@ static void intel_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr, drm_modeset_unlock(&connector->dev->mode_config.connection_mutex); drm_connector_unreference(connector); - DRM_DEBUG_KMS("\n"); } static void intel_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) @@ -564,11 +589,12 @@ intel_dp_create_fake_mst_encoder(struct intel_digital_port *intel_dig_port, enum static bool intel_dp_create_fake_mst_encoders(struct intel_digital_port *intel_dig_port) { - int i; struct intel_dp *intel_dp = &intel_dig_port->dp; + struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); + enum pipe pipe; - for (i = PIPE_A; i <= PIPE_C; i++) - intel_dp->mst_encoders[i] = intel_dp_create_fake_mst_encoder(intel_dig_port, i); + for_each_pipe(dev_priv, pipe) + intel_dp->mst_encoders[pipe] = intel_dp_create_fake_mst_encoder(intel_dig_port, pipe); return true; } diff --git a/drivers/gpu/drm/i915/intel_dpio_phy.c b/drivers/gpu/drm/i915/intel_dpio_phy.c index 09b670929786..de38d014ed39 100644 --- a/drivers/gpu/drm/i915/intel_dpio_phy.c +++ b/drivers/gpu/drm/i915/intel_dpio_phy.c @@ -208,12 +208,6 @@ static const struct bxt_ddi_phy_info glk_ddi_phy_info[] = { }, }; -static u32 bxt_phy_port_mask(const struct bxt_ddi_phy_info *phy_info) -{ - return (phy_info->dual_channel * BIT(phy_info->channel[DPIO_CH1].port)) | - BIT(phy_info->channel[DPIO_CH0].port); -} - static const struct bxt_ddi_phy_info * bxt_get_phy_list(struct drm_i915_private *dev_priv, int *count) { @@ -313,7 +307,6 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, enum dpio_phy phy) { const struct bxt_ddi_phy_info *phy_info; - enum port port; phy_info = bxt_get_phy_info(dev_priv, phy); @@ -335,19 +328,6 @@ bool bxt_ddi_phy_is_enabled(struct drm_i915_private *dev_priv, return false; } - for_each_port_masked(port, bxt_phy_port_mask(phy_info)) { - u32 tmp = I915_READ(BXT_PHY_CTL(port)); - - if (tmp & BXT_PHY_CMNLANE_POWERDOWN_ACK) { - DRM_DEBUG_DRIVER("DDI PHY %d powered, but common lane " - "for port %c powered down " - "(PHY_CTL %08x)\n", - phy, port_name(port), tmp); - - return false; - } - } - return true; } diff --git a/drivers/gpu/drm/i915/intel_dpll_mgr.c b/drivers/gpu/drm/i915/intel_dpll_mgr.c index a2a3d93d67bd..df808a94c511 100644 --- a/drivers/gpu/drm/i915/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/intel_dpll_mgr.c @@ -1996,7 +1996,7 @@ static void cnl_ddi_pll_enable(struct drm_i915_private *dev_priv, /* 3. Configure DPLL_CFGCR0 */ /* Avoid touch CFGCR1 if HDMI mode is not enabled */ - if (pll->state.hw_state.cfgcr0 & DPLL_CTRL1_HDMI_MODE(pll->id)) { + if (pll->state.hw_state.cfgcr0 & DPLL_CFGCR0_HDMI_MODE) { val = pll->state.hw_state.cfgcr1; I915_WRITE(CNL_DPLL_CFGCR1(pll->id), val); /* 4. Reab back to ensure writes completed */ diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 463ed152e6b1..47d022d48718 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -494,6 +494,8 @@ struct intel_crtc_scaler_state { /* drm_mode->private_flags */ #define I915_MODE_FLAG_INHERITED 1 +/* Flag to get scanline using frame time stamps */ +#define I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP (1<<1) struct intel_pipe_wm { struct intel_wm_level wm[5]; @@ -716,6 +718,9 @@ struct intel_crtc_state { struct intel_link_m_n dp_m2_n2; bool has_drrs; + bool has_psr; + bool has_psr2; + /* * Frequence the dpll for the port should run at. Differs from the * adjusted dotclock e.g. for DP or 12bpc hdmi mode. This is also @@ -798,18 +803,10 @@ struct intel_crtc { * some outputs connected to this crtc. */ bool active; - bool lowfreq_avail; u8 plane_ids_mask; unsigned long long enabled_power_domains; struct intel_overlay *overlay; - /* Display surface base address adjustement for pageflips. Note that on - * gen4+ this only adjusts up to a tile, offsets within a tile are - * handled in the hw itself (with the TILEOFF register). */ - u32 dspaddr_offset; - int adjusted_x; - int adjusted_y; - struct intel_crtc_state *config; /* global reset count when the last flip was submitted */ @@ -1064,7 +1061,7 @@ struct intel_digital_port { void (*write_infoframe)(struct drm_encoder *encoder, const struct intel_crtc_state *crtc_state, - enum hdmi_infoframe_type type, + unsigned int type, const void *frame, ssize_t len); void (*set_infoframes)(struct drm_encoder *encoder, bool enable, @@ -1241,7 +1238,7 @@ void gen6_disable_rps_interrupts(struct drm_i915_private *dev_priv); static inline u32 gen6_sanitize_rps_pm_mask(const struct drm_i915_private *i915, u32 mask) { - return mask & ~i915->rps.pm_intrmsk_mbz; + return mask & ~i915->gt_pm.rps.pm_intrmsk_mbz; } void intel_runtime_pm_disable_interrupts(struct drm_i915_private *dev_priv); @@ -1252,7 +1249,7 @@ static inline bool intel_irqs_enabled(struct drm_i915_private *dev_priv) * We only use drm_irq_uninstall() at unload and VT switch, so * this is the only thing we need to check. */ - return dev_priv->pm.irqs_enabled; + return dev_priv->runtime_pm.irqs_enabled; } int intel_get_crtc_scanline(struct intel_crtc *crtc); @@ -1358,11 +1355,13 @@ void intel_pps_unlock_regs_wa(struct drm_i915_private *dev_priv); void intel_encoder_destroy(struct drm_encoder *encoder); int intel_connector_init(struct intel_connector *); struct intel_connector *intel_connector_alloc(void); +void intel_connector_free(struct intel_connector *connector); bool intel_connector_get_hw_state(struct intel_connector *connector); void intel_connector_attach_encoder(struct intel_connector *connector, struct intel_encoder *encoder); -struct drm_display_mode *intel_crtc_mode_get(struct drm_device *dev, - struct drm_crtc *crtc); +struct drm_display_mode * +intel_encoder_current_mode(struct intel_encoder *encoder); + enum pipe intel_get_pipe_from_connector(struct intel_connector *connector); int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, struct drm_file *file_priv); @@ -1761,6 +1760,8 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, void intel_psr_init(struct drm_i915_private *dev_priv); void intel_psr_single_frame_update(struct drm_i915_private *dev_priv, unsigned frontbuffer_bits); +void intel_psr_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state); /* intel_runtime_pm.c */ int intel_power_domains_init(struct drm_i915_private *); @@ -1788,7 +1789,7 @@ void intel_display_power_put(struct drm_i915_private *dev_priv, static inline void assert_rpm_device_not_suspended(struct drm_i915_private *dev_priv) { - WARN_ONCE(dev_priv->pm.suspended, + WARN_ONCE(dev_priv->runtime_pm.suspended, "Device suspended during HW access\n"); } @@ -1796,7 +1797,7 @@ static inline void assert_rpm_wakelock_held(struct drm_i915_private *dev_priv) { assert_rpm_device_not_suspended(dev_priv); - WARN_ONCE(!atomic_read(&dev_priv->pm.wakeref_count), + WARN_ONCE(!atomic_read(&dev_priv->runtime_pm.wakeref_count), "RPM wakelock ref not held during HW access"); } @@ -1821,7 +1822,7 @@ assert_rpm_wakelock_held(struct drm_i915_private *dev_priv) static inline void disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv) { - atomic_inc(&dev_priv->pm.wakeref_count); + atomic_inc(&dev_priv->runtime_pm.wakeref_count); } /** @@ -1838,7 +1839,7 @@ disable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv) static inline void enable_rpm_wakeref_asserts(struct drm_i915_private *dev_priv) { - atomic_dec(&dev_priv->pm.wakeref_count); + atomic_dec(&dev_priv->runtime_pm.wakeref_count); } void intel_runtime_pm_get(struct drm_i915_private *dev_priv); @@ -1891,16 +1892,19 @@ int intel_enable_sagv(struct drm_i915_private *dev_priv); int intel_disable_sagv(struct drm_i915_private *dev_priv); bool skl_wm_level_equals(const struct skl_wm_level *l1, const struct skl_wm_level *l2); -bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry **entries, +bool skl_ddb_allocation_overlaps(struct drm_i915_private *dev_priv, + const struct skl_ddb_entry **entries, const struct skl_ddb_entry *ddb, int ignore); bool ilk_disable_lp_wm(struct drm_device *dev); int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6); int skl_check_pipe_max_pixel_rate(struct intel_crtc *intel_crtc, struct intel_crtc_state *cstate); -static inline int intel_enable_rc6(void) +void intel_init_ipc(struct drm_i915_private *dev_priv); +void intel_enable_ipc(struct drm_i915_private *dev_priv); +static inline int intel_rc6_enabled(void) { - return i915.enable_rc6; + return i915_modparams.enable_rc6; } /* intel_sdvo.c */ @@ -1917,6 +1921,10 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, struct drm_file *file_priv); void intel_pipe_update_start(const struct intel_crtc_state *new_crtc_state); void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state); +void skl_update_plane(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state); +void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc); /* intel_tv.c */ void intel_tv_init(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index fc25d7d2d942..83f15848098a 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -263,7 +263,7 @@ static int dpi_send_cmd(struct intel_dsi *intel_dsi, u32 cmd, bool hs, /* XXX: old code skips write if control unchanged */ if (cmd == I915_READ(MIPI_DPI_CONTROL(port))) - DRM_ERROR("Same special packet %02x twice in a row.\n", cmd); + DRM_DEBUG_KMS("Same special packet %02x twice in a row.\n", cmd); I915_WRITE(MIPI_DPI_CONTROL(port), cmd); @@ -330,6 +330,10 @@ static bool intel_dsi_compute_config(struct intel_encoder *encoder, adjusted_mode->flags = 0; if (IS_GEN9_LP(dev_priv)) { + /* Enable Frame time stamp based scanline reporting */ + adjusted_mode->private_flags |= + I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP; + /* Dual link goes to DSI transcoder A. */ if (intel_dsi->ports == BIT(PORT_C)) pipe_config->cpu_transcoder = TRANSCODER_DSI_C; @@ -786,14 +790,19 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config, const struct drm_connector_state *conn_state) { - struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dsi *intel_dsi = enc_to_intel_dsi(&encoder->base); + struct drm_crtc *crtc = pipe_config->base.crtc; + struct drm_i915_private *dev_priv = to_i915(crtc->dev); + struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + int pipe = intel_crtc->pipe; enum port port; u32 val; bool glk_cold_boot = false; DRM_DEBUG_KMS("\n"); + intel_set_cpu_fifo_underrun_reporting(dev_priv, pipe, true); + /* * The BIOS may leave the PLL in a wonky state where it doesn't * lock. It needs to be fully powered down to fix it. @@ -1102,6 +1111,10 @@ static void bxt_dsi_get_pipe_config(struct intel_encoder *encoder, pixel_format_from_register_bits(fmt)); bpp = pipe_config->pipe_bpp; + /* Enable Frame time stamo based scanline reporting */ + adjusted_mode->private_flags |= + I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP; + /* In terms of pixels */ adjusted_mode->crtc_hdisplay = I915_READ(BXT_MIPI_TRANS_HACTIVE(port)); @@ -1738,42 +1751,13 @@ void intel_dsi_init(struct drm_i915_private *dev_priv) else intel_encoder->crtc_mask = BIT(PIPE_B); - if (dev_priv->vbt.dsi.config->dual_link) { + if (dev_priv->vbt.dsi.config->dual_link) intel_dsi->ports = BIT(PORT_A) | BIT(PORT_C); - - switch (dev_priv->vbt.dsi.config->dl_dcs_backlight_ports) { - case DL_DCS_PORT_A: - intel_dsi->dcs_backlight_ports = BIT(PORT_A); - break; - case DL_DCS_PORT_C: - intel_dsi->dcs_backlight_ports = BIT(PORT_C); - break; - default: - case DL_DCS_PORT_A_AND_C: - intel_dsi->dcs_backlight_ports = BIT(PORT_A) | BIT(PORT_C); - break; - } - - switch (dev_priv->vbt.dsi.config->dl_dcs_cabc_ports) { - case DL_DCS_PORT_A: - intel_dsi->dcs_cabc_ports = BIT(PORT_A); - break; - case DL_DCS_PORT_C: - intel_dsi->dcs_cabc_ports = BIT(PORT_C); - break; - default: - case DL_DCS_PORT_A_AND_C: - intel_dsi->dcs_cabc_ports = BIT(PORT_A) | BIT(PORT_C); - break; - } - } else { + else intel_dsi->ports = BIT(port); - intel_dsi->dcs_backlight_ports = BIT(port); - intel_dsi->dcs_cabc_ports = BIT(port); - } - if (!dev_priv->vbt.dsi.config->cabc_supported) - intel_dsi->dcs_cabc_ports = 0; + intel_dsi->dcs_backlight_ports = dev_priv->vbt.dsi.bl_ports; + intel_dsi->dcs_cabc_ports = dev_priv->vbt.dsi.cabc_ports; /* Create a DSI host (and a device) for each port. */ for_each_dsi_port(port, intel_dsi->ports) { diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 5c562e1f56ae..53c9b763f4ce 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c @@ -379,32 +379,15 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = { * chip being on DVOB/C and having multiple pipes. */ static struct drm_display_mode * -intel_dvo_get_current_mode(struct drm_connector *connector) +intel_dvo_get_current_mode(struct intel_encoder *encoder) { - struct drm_device *dev = connector->dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_dvo *intel_dvo = intel_attached_dvo(connector); - uint32_t dvo_val = I915_READ(intel_dvo->dev.dvo_reg); - struct drm_display_mode *mode = NULL; + struct drm_display_mode *mode; - /* If the DVO port is active, that'll be the LVDS, so we can pull out - * its timings to get how the BIOS set up the panel. - */ - if (dvo_val & DVO_ENABLE) { - struct intel_crtc *crtc; - int pipe = (dvo_val & DVO_PIPE_B_SELECT) ? 1 : 0; - - crtc = intel_get_crtc_for_pipe(dev_priv, pipe); - if (crtc) { - mode = intel_crtc_mode_get(dev, &crtc->base); - if (mode) { - mode->type |= DRM_MODE_TYPE_PREFERRED; - if (dvo_val & DVO_HSYNC_ACTIVE_HIGH) - mode->flags |= DRM_MODE_FLAG_PHSYNC; - if (dvo_val & DVO_VSYNC_ACTIVE_HIGH) - mode->flags |= DRM_MODE_FLAG_PVSYNC; - } - } + mode = intel_encoder_current_mode(encoder); + if (mode) { + DRM_DEBUG_KMS("using current (BIOS) mode: "); + drm_mode_debug_printmodeline(mode); + mode->type |= DRM_MODE_TYPE_PREFERRED; } return mode; @@ -551,7 +534,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) * mode being output through DVO. */ intel_panel_init(&intel_connector->panel, - intel_dvo_get_current_mode(connector), + intel_dvo_get_current_mode(intel_encoder), NULL, NULL); intel_dvo->panel_wants_dither = true; } diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index b8e9a234af2d..ab5bf4e2e28e 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -22,7 +22,10 @@ * */ +#include <drm/drm_print.h> + #include "i915_drv.h" +#include "i915_vgpu.h" #include "intel_ringbuffer.h" #include "intel_lrc.h" @@ -39,6 +42,7 @@ #define GEN8_LR_CONTEXT_RENDER_SIZE (20 * PAGE_SIZE) #define GEN9_LR_CONTEXT_RENDER_SIZE (22 * PAGE_SIZE) +#define GEN10_LR_CONTEXT_RENDER_SIZE (18 * PAGE_SIZE) #define GEN8_LR_CONTEXT_OTHER_SIZE ( 2 * PAGE_SIZE) @@ -150,10 +154,11 @@ __intel_engine_context_size(struct drm_i915_private *dev_priv, u8 class) default: MISSING_CASE(INTEL_GEN(dev_priv)); case 10: + return GEN10_LR_CONTEXT_RENDER_SIZE; case 9: return GEN9_LR_CONTEXT_RENDER_SIZE; case 8: - return i915.enable_execlists ? + return i915_modparams.enable_execlists ? GEN8_LR_CONTEXT_RENDER_SIZE : GEN8_CXT_TOTAL_SIZE; case 7: @@ -301,7 +306,7 @@ int intel_engines_init(struct drm_i915_private *dev_priv) &intel_engine_classes[engine->class]; int (*init)(struct intel_engine_cs *engine); - if (i915.enable_execlists) + if (i915_modparams.enable_execlists) init = class_info->init_execlists; else init = class_info->init_legacy; @@ -380,6 +385,37 @@ static void intel_engine_init_timeline(struct intel_engine_cs *engine) engine->timeline = &engine->i915->gt.global_timeline.engine[engine->id]; } +static bool csb_force_mmio(struct drm_i915_private *i915) +{ + /* + * IOMMU adds unpredictable latency causing the CSB write (from the + * GPU into the HWSP) to only be visible some time after the interrupt + * (missed breadcrumb syndrome). + */ + if (intel_vtd_active()) + return true; + + /* Older GVT emulation depends upon intercepting CSB mmio */ + if (intel_vgpu_active(i915) && !intel_vgpu_has_hwsp_emulation(i915)) + return true; + + return false; +} + +static void intel_engine_init_execlist(struct intel_engine_cs *engine) +{ + struct intel_engine_execlists * const execlists = &engine->execlists; + + execlists->csb_use_mmio = csb_force_mmio(engine->i915); + + execlists->port_mask = 1; + BUILD_BUG_ON_NOT_POWER_OF_2(execlists_num_ports(execlists)); + GEM_BUG_ON(execlists_num_ports(execlists) > EXECLIST_MAX_PORTS); + + execlists->queue = RB_ROOT; + execlists->first = NULL; +} + /** * intel_engines_setup_common - setup engine state not requiring hw access * @engine: Engine to setup. @@ -391,8 +427,7 @@ static void intel_engine_init_timeline(struct intel_engine_cs *engine) */ void intel_engine_setup_common(struct intel_engine_cs *engine) { - engine->execlist_queue = RB_ROOT; - engine->execlist_first = NULL; + intel_engine_init_execlist(engine); intel_engine_init_timeline(engine); intel_engine_init_hangcheck(engine); @@ -442,6 +477,116 @@ static void intel_engine_cleanup_scratch(struct intel_engine_cs *engine) i915_vma_unpin_and_release(&engine->scratch); } +static void cleanup_phys_status_page(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + + if (!dev_priv->status_page_dmah) + return; + + drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); + engine->status_page.page_addr = NULL; +} + +static void cleanup_status_page(struct intel_engine_cs *engine) +{ + struct i915_vma *vma; + struct drm_i915_gem_object *obj; + + vma = fetch_and_zero(&engine->status_page.vma); + if (!vma) + return; + + obj = vma->obj; + + i915_vma_unpin(vma); + i915_vma_close(vma); + + i915_gem_object_unpin_map(obj); + __i915_gem_object_release_unless_active(obj); +} + +static int init_status_page(struct intel_engine_cs *engine) +{ + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + unsigned int flags; + void *vaddr; + int ret; + + obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); + if (IS_ERR(obj)) { + DRM_ERROR("Failed to allocate status page\n"); + return PTR_ERR(obj); + } + + ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); + if (ret) + goto err; + + vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL); + if (IS_ERR(vma)) { + ret = PTR_ERR(vma); + goto err; + } + + flags = PIN_GLOBAL; + if (!HAS_LLC(engine->i915)) + /* On g33, we cannot place HWS above 256MiB, so + * restrict its pinning to the low mappable arena. + * Though this restriction is not documented for + * gen4, gen5, or byt, they also behave similarly + * and hang if the HWS is placed at the top of the + * GTT. To generalise, it appears that all !llc + * platforms have issues with us placing the HWS + * above the mappable region (even though we never + * actually map it). + */ + flags |= PIN_MAPPABLE; + else + flags |= PIN_HIGH; + ret = i915_vma_pin(vma, 0, 4096, flags); + if (ret) + goto err; + + vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + goto err_unpin; + } + + engine->status_page.vma = vma; + engine->status_page.ggtt_offset = i915_ggtt_offset(vma); + engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE); + + DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", + engine->name, i915_ggtt_offset(vma)); + return 0; + +err_unpin: + i915_vma_unpin(vma); +err: + i915_gem_object_put(obj); + return ret; +} + +static int init_phys_status_page(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + + GEM_BUG_ON(engine->id != RCS); + + dev_priv->status_page_dmah = + drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); + if (!dev_priv->status_page_dmah) + return -ENOMEM; + + engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; + memset(engine->status_page.page_addr, 0, PAGE_SIZE); + + return 0; +} + /** * intel_engines_init_common - initialize cengine state which might require hw access * @engine: Engine to initialize. @@ -471,17 +616,44 @@ int intel_engine_init_common(struct intel_engine_cs *engine) if (IS_ERR(ring)) return PTR_ERR(ring); + /* + * Similarly the preempt context must always be available so that + * we can interrupt the engine at any time. + */ + if (INTEL_INFO(engine->i915)->has_logical_ring_preemption) { + ring = engine->context_pin(engine, + engine->i915->preempt_context); + if (IS_ERR(ring)) { + ret = PTR_ERR(ring); + goto err_unpin_kernel; + } + } + ret = intel_engine_init_breadcrumbs(engine); if (ret) - goto err_unpin; + goto err_unpin_preempt; ret = i915_gem_render_state_init(engine); if (ret) - goto err_unpin; + goto err_breadcrumbs; + + if (HWS_NEEDS_PHYSICAL(engine->i915)) + ret = init_phys_status_page(engine); + else + ret = init_status_page(engine); + if (ret) + goto err_rs_fini; return 0; -err_unpin: +err_rs_fini: + i915_gem_render_state_fini(engine); +err_breadcrumbs: + intel_engine_fini_breadcrumbs(engine); +err_unpin_preempt: + if (INTEL_INFO(engine->i915)->has_logical_ring_preemption) + engine->context_unpin(engine, engine->i915->preempt_context); +err_unpin_kernel: engine->context_unpin(engine, engine->i915->kernel_context); return ret; } @@ -497,11 +669,18 @@ void intel_engine_cleanup_common(struct intel_engine_cs *engine) { intel_engine_cleanup_scratch(engine); + if (HWS_NEEDS_PHYSICAL(engine->i915)) + cleanup_phys_status_page(engine); + else + cleanup_status_page(engine); + i915_gem_render_state_fini(engine); intel_engine_fini_breadcrumbs(engine); intel_engine_cleanup_cmd_parser(engine); i915_gem_batch_pool_fini(&engine->batch_pool); + if (INTEL_INFO(engine->i915)->has_logical_ring_preemption) + engine->context_unpin(engine, engine->i915->preempt_context); engine->context_unpin(engine, engine->i915->kernel_context); } @@ -672,11 +851,6 @@ static int wa_add(struct drm_i915_private *dev_priv, #define WA_SET_FIELD_MASKED(addr, mask, value) \ WA_REG(addr, mask, _MASKED_FIELD(mask, value)) -#define WA_SET_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) | (mask)) -#define WA_CLR_BIT(addr, mask) WA_REG(addr, mask, I915_READ(addr) & ~(mask)) - -#define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val) - static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, i915_reg_t reg) { @@ -687,8 +861,8 @@ static int wa_ring_whitelist_reg(struct intel_engine_cs *engine, if (WARN_ON(index >= RING_MAX_NONPRIV_SLOTS)) return -EINVAL; - WA_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), - i915_mmio_reg_offset(reg)); + I915_WRITE(RING_FORCE_TO_NONPRIV(engine->mmio_base, index), + i915_mmio_reg_offset(reg)); wa->hw_whitelist_count[engine->id]++; return 0; @@ -812,6 +986,23 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | ECOCHK_DIS_TLB); + if (HAS_LLC(dev_priv)) { + /* WaCompressedResourceSamplerPbeMediaNewHashMode:skl,kbl + * + * Must match Display Engine. See + * WaCompressedResourceDisplayNewHashMode. + */ + WA_SET_BIT_MASKED(COMMON_SLICE_CHICKEN2, + GEN9_PBE_COMPRESSED_HASH_SELECTION); + WA_SET_BIT_MASKED(GEN9_HALF_SLICE_CHICKEN7, + GEN9_SAMPLER_HASH_COMPRESSED_READ_ADDR); + + I915_WRITE(MMCD_MISC_CTRL, + I915_READ(MMCD_MISC_CTRL) | + MMCD_PCLA | + MMCD_HOTSPOT_EN); + } + /* WaClearFlowControlGpgpuContextSave:skl,bxt,kbl,glk,cfl */ /* WaDisablePartialInstShootdown:skl,bxt,kbl,glk,cfl */ WA_SET_BIT_MASKED(GEN8_ROW_CHICKEN, @@ -900,13 +1091,33 @@ static int gen9_init_workarounds(struct intel_engine_cs *engine) I915_WRITE(GEN8_L3SQCREG4, (I915_READ(GEN8_L3SQCREG4) | GEN8_LQSC_FLUSH_COHERENT_LINES)); + /* + * Supporting preemption with fine-granularity requires changes in the + * batch buffer programming. Since we can't break old userspace, we + * need to set our default preemption level to safe value. Userspace is + * still able to use more fine-grained preemption levels, since in + * WaEnablePreemptionGranularityControlByUMD we're whitelisting the + * per-ctx register. As such, WaDisable{3D,GPGPU}MidCmdPreemption are + * not real HW workarounds, but merely a way to start using preemption + * while maintaining old contract with userspace. + */ + + /* WaDisable3DMidCmdPreemption:skl,bxt,glk,cfl,[cnl] */ + WA_CLR_BIT_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL); + + /* WaDisableGPGPUMidCmdPreemption:skl,bxt,blk,cfl,[cnl] */ + WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK, + GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); + /* WaVFEStateAfterPipeControlwithMediaStateClear:skl,bxt,glk,cfl */ ret = wa_ring_whitelist_reg(engine, GEN9_CTX_PREEMPT_REG); if (ret) return ret; - /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl */ - ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); + /* WaEnablePreemptionGranularityControlByUMD:skl,bxt,kbl,cfl,[cnl] */ + I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, + _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); + ret = wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); if (ret) return ret; @@ -968,25 +1179,19 @@ static int skl_init_workarounds(struct intel_engine_cs *engine) if (ret) return ret; - /* - * Actual WA is to disable percontext preemption granularity control - * until D0 which is the default case so this is equivalent to - * !WaDisablePerCtxtPreemptionGranularityControl:skl - */ - I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, - _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); - /* WaEnableGapsTsvCreditFix:skl */ I915_WRITE(GEN8_GARBCNTL, (I915_READ(GEN8_GARBCNTL) | GEN9_GAPS_TSV_CREDIT_DISABLE)); /* WaDisableGafsUnitClkGating:skl */ - WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | + GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); /* WaInPlaceDecompressionHang:skl */ if (IS_SKL_REVID(dev_priv, SKL_REVID_H0, REVID_FOREVER)) - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); /* WaDisableLSQCROPERFforOCL:skl */ ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); @@ -1022,8 +1227,8 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine) /* WaDisablePooledEuLoadBalancingFix:bxt */ if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { - WA_SET_BIT_MASKED(FF_SLICE_CS_CHICKEN2, - GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE); + I915_WRITE(FF_SLICE_CS_CHICKEN2, + _MASKED_BIT_ENABLE(GEN9_POOLED_EU_LOAD_BALANCING_FIX_DISABLE)); } /* WaDisableSbeCacheDispatchPortSharing:bxt */ @@ -1048,9 +1253,12 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine) } /* WaProgramL3SqcReg1DefaultForPerf:bxt */ - if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) - I915_WRITE(GEN8_L3SQCREG1, L3_GENERAL_PRIO_CREDITS(62) | - L3_HIGH_PRIO_CREDITS(2)); + if (IS_BXT_REVID(dev_priv, BXT_REVID_B0, REVID_FOREVER)) { + u32 val = I915_READ(GEN8_L3SQCREG1); + val &= ~L3_PRIO_CREDITS_MASK; + val |= L3_GENERAL_PRIO_CREDITS(62) | L3_HIGH_PRIO_CREDITS(2); + I915_WRITE(GEN8_L3SQCREG1, val); + } /* WaToEnableHwFixForPushConstHWBug:bxt */ if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) @@ -1059,8 +1267,9 @@ static int bxt_init_workarounds(struct intel_engine_cs *engine) /* WaInPlaceDecompressionHang:bxt */ if (IS_BXT_REVID(dev_priv, BXT_REVID_C0, REVID_FOREVER)) - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); return 0; } @@ -1070,10 +1279,11 @@ static int cnl_init_workarounds(struct intel_engine_cs *engine) struct drm_i915_private *dev_priv = engine->i915; int ret; - /* WaDisableI2mCycleOnWRPort: cnl (pre-prod) */ + /* WaDisableI2mCycleOnWRPort:cnl (pre-prod) */ if (IS_CNL_REVID(dev_priv, CNL_REVID_B0, CNL_REVID_B0)) - WA_SET_BIT(GAMT_CHKN_BIT_REG, - GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT); + I915_WRITE(GAMT_CHKN_BIT_REG, + (I915_READ(GAMT_CHKN_BIT_REG) | + GAMT_CHKN_DISABLE_I2M_CYCLE_ON_WR_PORT)); /* WaForceContextSaveRestoreNonCoherent:cnl */ WA_SET_BIT_MASKED(CNL_HDC_CHICKEN0, @@ -1093,16 +1303,26 @@ static int cnl_init_workarounds(struct intel_engine_cs *engine) GEN8_CSC2_SBE_VUE_CACHE_CONSERVATIVE); /* WaInPlaceDecompressionHang:cnl */ - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); /* WaPushConstantDereferenceHoldDisable:cnl */ - WA_SET_BIT(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE); + WA_SET_BIT_MASKED(GEN7_ROW_CHICKEN2, PUSH_CONSTANT_DEREF_DISABLE); /* FtrEnableFastAnisoL1BankingFix: cnl */ WA_SET_BIT_MASKED(HALF_SLICE_CHICKEN3, CNL_FAST_ANISO_L1_BANKING_FIX); + /* WaDisable3DMidCmdPreemption:cnl */ + WA_CLR_BIT_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_3D_OBJECT_LEVEL); + + /* WaDisableGPGPUMidCmdPreemption:cnl */ + WA_SET_FIELD_MASKED(GEN8_CS_CHICKEN1, GEN9_PREEMPT_GPGPU_LEVEL_MASK, + GEN9_PREEMPT_GPGPU_COMMAND_LEVEL); + /* WaEnablePreemptionGranularityControlByUMD:cnl */ + I915_WRITE(GEN7_FF_SLICE_CS_CHICKEN1, + _MASKED_BIT_ENABLE(GEN9_FFSC_PERCTX_PREEMPT_CTRL)); ret= wa_ring_whitelist_reg(engine, GEN8_CS_CHICKEN1); if (ret) return ret; @@ -1125,8 +1345,9 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine) /* WaDisableDynamicCreditSharing:kbl */ if (IS_KBL_REVID(dev_priv, 0, KBL_REVID_B0)) - WA_SET_BIT(GAMT_CHKN_BIT_REG, - GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING); + I915_WRITE(GAMT_CHKN_BIT_REG, + (I915_READ(GAMT_CHKN_BIT_REG) | + GAMT_CHKN_DISABLE_DYNAMIC_CREDIT_SHARING)); /* WaDisableFenceDestinationToSLM:kbl (pre-prod) */ if (IS_KBL_REVID(dev_priv, KBL_REVID_A0, KBL_REVID_A0)) @@ -1139,7 +1360,8 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine) GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); /* WaDisableGafsUnitClkGating:kbl */ - WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | + GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); /* WaDisableSbeCacheDispatchPortSharing:kbl */ WA_SET_BIT_MASKED( @@ -1147,8 +1369,9 @@ static int kbl_init_workarounds(struct intel_engine_cs *engine) GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); /* WaInPlaceDecompressionHang:kbl */ - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); /* WaDisableLSQCROPERFforOCL:kbl */ ret = wa_ring_whitelist_reg(engine, GEN8_L3SQCREG4); @@ -1192,7 +1415,8 @@ static int cfl_init_workarounds(struct intel_engine_cs *engine) GEN8_SBE_DISABLE_REPLAY_BUF_OPTIMIZATION); /* WaDisableGafsUnitClkGating:cfl */ - WA_SET_BIT(GEN7_UCGCTL4, GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE); + I915_WRITE(GEN7_UCGCTL4, (I915_READ(GEN7_UCGCTL4) | + GEN8_EU_GAUNIT_CLOCK_GATE_DISABLE)); /* WaDisableSbeCacheDispatchPortSharing:cfl */ WA_SET_BIT_MASKED( @@ -1200,8 +1424,9 @@ static int cfl_init_workarounds(struct intel_engine_cs *engine) GEN7_SBE_SS_CACHE_DISPATCH_PORT_SHARING_DISABLE); /* WaInPlaceDecompressionHang:cfl */ - WA_SET_BIT(GEN9_GAMT_ECO_REG_RW_IA, - GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS); + I915_WRITE(GEN9_GAMT_ECO_REG_RW_IA, + (I915_READ(GEN9_GAMT_ECO_REG_RW_IA) | + GAMT_ECO_ENABLE_IN_PLACE_DECOMPRESS)); return 0; } @@ -1323,12 +1548,12 @@ bool intel_engine_is_idle(struct intel_engine_cs *engine) if (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) return false; - /* Both ports drained, no more ELSP submission? */ - if (port_request(&engine->execlist_port[0])) + /* Waiting to drain ELSP? */ + if (READ_ONCE(engine->execlists.active)) return false; /* ELSP is empty, but there are ready requests? */ - if (READ_ONCE(engine->execlist_first)) + if (READ_ONCE(engine->execlists.first)) return false; /* Ring stopped? */ @@ -1377,8 +1602,8 @@ void intel_engines_mark_idle(struct drm_i915_private *i915) for_each_engine(engine, i915, id) { intel_engine_disarm_breadcrumbs(engine); i915_gem_batch_pool_fini(&engine->batch_pool); - tasklet_kill(&engine->irq_tasklet); - engine->no_priolist = false; + tasklet_kill(&engine->execlists.irq_tasklet); + engine->execlists.no_priolist = false; } } @@ -1397,6 +1622,168 @@ bool intel_engine_can_store_dword(struct intel_engine_cs *engine) } } +static void print_request(struct drm_printer *m, + struct drm_i915_gem_request *rq, + const char *prefix) +{ + drm_printf(m, "%s%x%s [%x:%x] prio=%d @ %dms: %s\n", prefix, + rq->global_seqno, + i915_gem_request_completed(rq) ? "!" : "", + rq->ctx->hw_id, rq->fence.seqno, + rq->priotree.priority, + jiffies_to_msecs(jiffies - rq->emitted_jiffies), + rq->timeline->common->name); +} + +void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *m) +{ + struct intel_breadcrumbs * const b = &engine->breadcrumbs; + const struct intel_engine_execlists * const execlists = &engine->execlists; + struct i915_gpu_error * const error = &engine->i915->gpu_error; + struct drm_i915_private *dev_priv = engine->i915; + struct drm_i915_gem_request *rq; + struct rb_node *rb; + u64 addr; + + drm_printf(m, "%s\n", engine->name); + drm_printf(m, "\tcurrent seqno %x, last %x, hangcheck %x [%d ms], inflight %d\n", + intel_engine_get_seqno(engine), + intel_engine_last_submit(engine), + engine->hangcheck.seqno, + jiffies_to_msecs(jiffies - engine->hangcheck.action_timestamp), + engine->timeline->inflight_seqnos); + drm_printf(m, "\tReset count: %d\n", + i915_reset_engine_count(error, engine)); + + rcu_read_lock(); + + drm_printf(m, "\tRequests:\n"); + + rq = list_first_entry(&engine->timeline->requests, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->timeline->requests) + print_request(m, rq, "\t\tfirst "); + + rq = list_last_entry(&engine->timeline->requests, + struct drm_i915_gem_request, link); + if (&rq->link != &engine->timeline->requests) + print_request(m, rq, "\t\tlast "); + + rq = i915_gem_find_active_request(engine); + if (rq) { + print_request(m, rq, "\t\tactive "); + drm_printf(m, + "\t\t[head %04x, postfix %04x, tail %04x, batch 0x%08x_%08x]\n", + rq->head, rq->postfix, rq->tail, + rq->batch ? upper_32_bits(rq->batch->node.start) : ~0u, + rq->batch ? lower_32_bits(rq->batch->node.start) : ~0u); + } + + drm_printf(m, "\tRING_START: 0x%08x [0x%08x]\n", + I915_READ(RING_START(engine->mmio_base)), + rq ? i915_ggtt_offset(rq->ring->vma) : 0); + drm_printf(m, "\tRING_HEAD: 0x%08x [0x%08x]\n", + I915_READ(RING_HEAD(engine->mmio_base)) & HEAD_ADDR, + rq ? rq->ring->head : 0); + drm_printf(m, "\tRING_TAIL: 0x%08x [0x%08x]\n", + I915_READ(RING_TAIL(engine->mmio_base)) & TAIL_ADDR, + rq ? rq->ring->tail : 0); + drm_printf(m, "\tRING_CTL: 0x%08x [%s]\n", + I915_READ(RING_CTL(engine->mmio_base)), + I915_READ(RING_CTL(engine->mmio_base)) & (RING_WAIT | RING_WAIT_SEMAPHORE) ? "waiting" : ""); + + rcu_read_unlock(); + + addr = intel_engine_get_active_head(engine); + drm_printf(m, "\tACTHD: 0x%08x_%08x\n", + upper_32_bits(addr), lower_32_bits(addr)); + addr = intel_engine_get_last_batch_head(engine); + drm_printf(m, "\tBBADDR: 0x%08x_%08x\n", + upper_32_bits(addr), lower_32_bits(addr)); + + if (i915_modparams.enable_execlists) { + const u32 *hws = &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX]; + u32 ptr, read, write; + unsigned int idx; + + drm_printf(m, "\tExeclist status: 0x%08x %08x\n", + I915_READ(RING_EXECLIST_STATUS_LO(engine)), + I915_READ(RING_EXECLIST_STATUS_HI(engine))); + + ptr = I915_READ(RING_CONTEXT_STATUS_PTR(engine)); + read = GEN8_CSB_READ_PTR(ptr); + write = GEN8_CSB_WRITE_PTR(ptr); + drm_printf(m, "\tExeclist CSB read %d [%d cached], write %d [%d from hws], interrupt posted? %s\n", + read, execlists->csb_head, + write, + intel_read_status_page(engine, intel_hws_csb_write_index(engine->i915)), + yesno(test_bit(ENGINE_IRQ_EXECLIST, + &engine->irq_posted))); + if (read >= GEN8_CSB_ENTRIES) + read = 0; + if (write >= GEN8_CSB_ENTRIES) + write = 0; + if (read > write) + write += GEN8_CSB_ENTRIES; + while (read < write) { + idx = ++read % GEN8_CSB_ENTRIES; + drm_printf(m, "\tExeclist CSB[%d]: 0x%08x [0x%08x in hwsp], context: %d [%d in hwsp]\n", + idx, + I915_READ(RING_CONTEXT_STATUS_BUF_LO(engine, idx)), + hws[idx * 2], + I915_READ(RING_CONTEXT_STATUS_BUF_HI(engine, idx)), + hws[idx * 2 + 1]); + } + + rcu_read_lock(); + for (idx = 0; idx < execlists_num_ports(execlists); idx++) { + unsigned int count; + + rq = port_unpack(&execlists->port[idx], &count); + if (rq) { + drm_printf(m, "\t\tELSP[%d] count=%d, ", + idx, count); + print_request(m, rq, "rq: "); + } else { + drm_printf(m, "\t\tELSP[%d] idle\n", + idx); + } + } + drm_printf(m, "\t\tHW active? 0x%x\n", execlists->active); + rcu_read_unlock(); + } else if (INTEL_GEN(dev_priv) > 6) { + drm_printf(m, "\tPP_DIR_BASE: 0x%08x\n", + I915_READ(RING_PP_DIR_BASE(engine))); + drm_printf(m, "\tPP_DIR_BASE_READ: 0x%08x\n", + I915_READ(RING_PP_DIR_BASE_READ(engine))); + drm_printf(m, "\tPP_DIR_DCLV: 0x%08x\n", + I915_READ(RING_PP_DIR_DCLV(engine))); + } + + spin_lock_irq(&engine->timeline->lock); + list_for_each_entry(rq, &engine->timeline->requests, link) + print_request(m, rq, "\t\tE "); + for (rb = execlists->first; rb; rb = rb_next(rb)) { + struct i915_priolist *p = + rb_entry(rb, typeof(*p), node); + + list_for_each_entry(rq, &p->requests, priotree.link) + print_request(m, rq, "\t\tQ "); + } + spin_unlock_irq(&engine->timeline->lock); + + spin_lock_irq(&b->rb_lock); + for (rb = rb_first(&b->waiters); rb; rb = rb_next(rb)) { + struct intel_wait *w = rb_entry(rb, typeof(*w), node); + + drm_printf(m, "\t%s [%d] waiting for %x\n", + w->tsk->comm, w->tsk->pid, w->seqno); + } + spin_unlock_irq(&b->rb_lock); + + drm_printf(m, "\n"); +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_engine.c" #endif diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c index 58a772de6672..1a0f5e0c8d10 100644 --- a/drivers/gpu/drm/i915/intel_fbc.c +++ b/drivers/gpu/drm/i915/intel_fbc.c @@ -69,9 +69,9 @@ static inline bool no_fbc_on_multiple_pipes(struct drm_i915_private *dev_priv) * address we program because it starts at the real start of the buffer, so we * have to take this into consideration here. */ -static unsigned int get_crtc_fence_y_offset(struct intel_crtc *crtc) +static unsigned int get_crtc_fence_y_offset(struct intel_fbc *fbc) { - return crtc->base.y - crtc->adjusted_y; + return fbc->state_cache.plane.y - fbc->state_cache.plane.adjusted_y; } /* @@ -727,8 +727,8 @@ static bool intel_fbc_hw_tracking_covers_screen(struct intel_crtc *crtc) intel_fbc_get_plane_source_size(&fbc->state_cache, &effective_w, &effective_h); - effective_w += crtc->adjusted_x; - effective_h += crtc->adjusted_y; + effective_w += fbc->state_cache.plane.adjusted_x; + effective_h += fbc->state_cache.plane.adjusted_y; return effective_w <= max_w && effective_h <= max_h; } @@ -757,6 +757,9 @@ static void intel_fbc_update_state_cache(struct intel_crtc *crtc, cache->plane.src_w = drm_rect_width(&plane_state->base.src) >> 16; cache->plane.src_h = drm_rect_height(&plane_state->base.src) >> 16; cache->plane.visible = plane_state->base.visible; + cache->plane.adjusted_x = plane_state->main.x; + cache->plane.adjusted_y = plane_state->main.y; + cache->plane.y = plane_state->base.src.y1 >> 16; if (!cache->plane.visible) return; @@ -859,7 +862,7 @@ static bool intel_fbc_can_enable(struct drm_i915_private *dev_priv) return false; } - if (!i915.enable_fbc) { + if (!i915_modparams.enable_fbc) { fbc->no_fbc_reason = "disabled per module param or by default"; return false; } @@ -888,7 +891,7 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc, params->crtc.pipe = crtc->pipe; params->crtc.plane = crtc->plane; - params->crtc.fence_y_offset = get_crtc_fence_y_offset(crtc); + params->crtc.fence_y_offset = get_crtc_fence_y_offset(fbc); params->fb.format = cache->fb.format; params->fb.stride = cache->fb.stride; @@ -1310,8 +1313,8 @@ void intel_fbc_init_pipe_state(struct drm_i915_private *dev_priv) */ static int intel_sanitize_fbc_option(struct drm_i915_private *dev_priv) { - if (i915.enable_fbc >= 0) - return !!i915.enable_fbc; + if (i915_modparams.enable_fbc >= 0) + return !!i915_modparams.enable_fbc; if (!HAS_FBC(dev_priv)) return 0; @@ -1355,8 +1358,9 @@ void intel_fbc_init(struct drm_i915_private *dev_priv) if (need_fbc_vtd_wa(dev_priv)) mkwrite_device_info(dev_priv)->has_fbc = false; - i915.enable_fbc = intel_sanitize_fbc_option(dev_priv); - DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", i915.enable_fbc); + i915_modparams.enable_fbc = intel_sanitize_fbc_option(dev_priv); + DRM_DEBUG_KMS("Sanitized enable_fbc value: %d\n", + i915_modparams.enable_fbc); if (!HAS_FBC(dev_priv)) { fbc->no_fbc_reason = "unsupported by this chipset"; diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index f2bb8116227c..b8af35187d22 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -189,7 +189,7 @@ static int intelfb_create(struct drm_fb_helper *helper, " releasing it\n", intel_fb->base.width, intel_fb->base.height, sizes->fb_width, sizes->fb_height); - drm_framebuffer_unreference(&intel_fb->base); + drm_framebuffer_put(&intel_fb->base); intel_fb = ifbdev->fb = NULL; } if (!intel_fb || WARN_ON(!intel_fb->obj)) { @@ -627,7 +627,7 @@ static bool intel_fbdev_init_bios(struct drm_device *dev, ifbdev->preferred_bpp = fb->base.format->cpp[0] * 8; ifbdev->fb = fb; - drm_framebuffer_reference(&ifbdev->fb->base); + drm_framebuffer_get(&ifbdev->fb->base); /* Final pass to check if any active pipes don't have fbs */ for_each_crtc(dev, crtc) { diff --git a/drivers/gpu/drm/i915/intel_fifo_underrun.c b/drivers/gpu/drm/i915/intel_fifo_underrun.c index 04689600e337..77c123cc8817 100644 --- a/drivers/gpu/drm/i915/intel_fifo_underrun.c +++ b/drivers/gpu/drm/i915/intel_fifo_underrun.c @@ -88,14 +88,15 @@ static void i9xx_check_fifo_underruns(struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); i915_reg_t reg = PIPESTAT(crtc->pipe); - u32 pipestat = I915_READ(reg) & 0xffff0000; + u32 enable_mask; lockdep_assert_held(&dev_priv->irq_lock); - if ((pipestat & PIPE_FIFO_UNDERRUN_STATUS) == 0) + if ((I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS) == 0) return; - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); + enable_mask = i915_pipestat_enable_mask(dev_priv, crtc->pipe); + I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS); POSTING_READ(reg); trace_intel_cpu_fifo_underrun(dev_priv, crtc->pipe); @@ -108,15 +109,16 @@ static void i9xx_set_fifo_underrun_reporting(struct drm_device *dev, { struct drm_i915_private *dev_priv = to_i915(dev); i915_reg_t reg = PIPESTAT(pipe); - u32 pipestat = I915_READ(reg) & 0xffff0000; lockdep_assert_held(&dev_priv->irq_lock); if (enable) { - I915_WRITE(reg, pipestat | PIPE_FIFO_UNDERRUN_STATUS); + u32 enable_mask = i915_pipestat_enable_mask(dev_priv, pipe); + + I915_WRITE(reg, enable_mask | PIPE_FIFO_UNDERRUN_STATUS); POSTING_READ(reg); } else { - if (old && pipestat & PIPE_FIFO_UNDERRUN_STATUS) + if (old && I915_READ(reg) & PIPE_FIFO_UNDERRUN_STATUS) DRM_ERROR("pipe %c underrun\n", pipe_name(pipe)); } } diff --git a/drivers/gpu/drm/i915/intel_guc.c b/drivers/gpu/drm/i915/intel_guc.c new file mode 100644 index 000000000000..10037c0fdf95 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_guc.c @@ -0,0 +1,369 @@ +/* + * Copyright © 2014-2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION 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 "intel_guc.h" +#include "i915_drv.h" + +static void gen8_guc_raise_irq(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + + I915_WRITE(GUC_SEND_INTERRUPT, GUC_SEND_TRIGGER); +} + +static inline i915_reg_t guc_send_reg(struct intel_guc *guc, u32 i) +{ + GEM_BUG_ON(!guc->send_regs.base); + GEM_BUG_ON(!guc->send_regs.count); + GEM_BUG_ON(i >= guc->send_regs.count); + + return _MMIO(guc->send_regs.base + 4 * i); +} + +void intel_guc_init_send_regs(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + enum forcewake_domains fw_domains = 0; + unsigned int i; + + guc->send_regs.base = i915_mmio_reg_offset(SOFT_SCRATCH(0)); + guc->send_regs.count = SOFT_SCRATCH_COUNT - 1; + + for (i = 0; i < guc->send_regs.count; i++) { + fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, + guc_send_reg(guc, i), + FW_REG_READ | FW_REG_WRITE); + } + guc->send_regs.fw_domains = fw_domains; +} + +void intel_guc_init_early(struct intel_guc *guc) +{ + intel_guc_ct_init_early(&guc->ct); + + mutex_init(&guc->send_mutex); + guc->send = intel_guc_send_nop; + guc->notify = gen8_guc_raise_irq; +} + +static u32 get_gt_type(struct drm_i915_private *dev_priv) +{ + /* XXX: GT type based on PCI device ID? field seems unused by fw */ + return 0; +} + +static u32 get_core_family(struct drm_i915_private *dev_priv) +{ + u32 gen = INTEL_GEN(dev_priv); + + switch (gen) { + case 9: + return GUC_CORE_FAMILY_GEN9; + + default: + MISSING_CASE(gen); + return GUC_CORE_FAMILY_UNKNOWN; + } +} + +/* + * Initialise the GuC parameter block before starting the firmware + * transfer. These parameters are read by the firmware on startup + * and cannot be changed thereafter. + */ +void intel_guc_init_params(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + u32 params[GUC_CTL_MAX_DWORDS]; + int i; + + memset(params, 0, sizeof(params)); + + params[GUC_CTL_DEVICE_INFO] |= + (get_gt_type(dev_priv) << GUC_CTL_GT_TYPE_SHIFT) | + (get_core_family(dev_priv) << GUC_CTL_CORE_FAMILY_SHIFT); + + /* + * GuC ARAT increment is 10 ns. GuC default scheduler quantum is one + * second. This ARAR is calculated by: + * Scheduler-Quantum-in-ns / ARAT-increment-in-ns = 1000000000 / 10 + */ + params[GUC_CTL_ARAT_HIGH] = 0; + params[GUC_CTL_ARAT_LOW] = 100000000; + + params[GUC_CTL_WA] |= GUC_CTL_WA_UK_BY_DRIVER; + + params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER | + GUC_CTL_VCS2_ENABLED; + + params[GUC_CTL_LOG_PARAMS] = guc->log.flags; + + if (i915_modparams.guc_log_level >= 0) { + params[GUC_CTL_DEBUG] = + i915_modparams.guc_log_level << GUC_LOG_VERBOSITY_SHIFT; + } else { + params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED; + } + + /* If GuC submission is enabled, set up additional parameters here */ + if (i915_modparams.enable_guc_submission) { + u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; + u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool); + u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16; + + params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; + params[GUC_CTL_DEBUG] |= GUC_ADS_ENABLED; + + pgs >>= PAGE_SHIFT; + params[GUC_CTL_CTXINFO] = (pgs << GUC_CTL_BASE_ADDR_SHIFT) | + (ctx_in_16 << GUC_CTL_CTXNUM_IN16_SHIFT); + + params[GUC_CTL_FEATURE] |= GUC_CTL_KERNEL_SUBMISSIONS; + + /* Unmask this bit to enable the GuC's internal scheduler */ + params[GUC_CTL_FEATURE] &= ~GUC_CTL_DISABLE_SCHEDULER; + } + + /* + * All SOFT_SCRATCH registers are in FORCEWAKE_BLITTER domain and + * they are power context saved so it's ok to release forcewake + * when we are done here and take it again at xfer time. + */ + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_BLITTER); + + I915_WRITE(SOFT_SCRATCH(0), 0); + + for (i = 0; i < GUC_CTL_MAX_DWORDS; i++) + I915_WRITE(SOFT_SCRATCH(1 + i), params[i]); + + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_BLITTER); +} + +int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len) +{ + WARN(1, "Unexpected send: action=%#x\n", *action); + return -ENODEV; +} + +/* + * This function implements the MMIO based host to GuC interface. + */ +int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + u32 status; + int i; + int ret; + + GEM_BUG_ON(!len); + GEM_BUG_ON(len > guc->send_regs.count); + + /* If CT is available, we expect to use MMIO only during init/fini */ + GEM_BUG_ON(HAS_GUC_CT(dev_priv) && + *action != INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER && + *action != INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER); + + mutex_lock(&guc->send_mutex); + intel_uncore_forcewake_get(dev_priv, guc->send_regs.fw_domains); + + for (i = 0; i < len; i++) + I915_WRITE(guc_send_reg(guc, i), action[i]); + + POSTING_READ(guc_send_reg(guc, i - 1)); + + intel_guc_notify(guc); + + /* + * No GuC command should ever take longer than 10ms. + * Fast commands should still complete in 10us. + */ + ret = __intel_wait_for_register_fw(dev_priv, + guc_send_reg(guc, 0), + INTEL_GUC_RECV_MASK, + INTEL_GUC_RECV_MASK, + 10, 10, &status); + if (status != INTEL_GUC_STATUS_SUCCESS) { + /* + * Either the GuC explicitly returned an error (which + * we convert to -EIO here) or no response at all was + * received within the timeout limit (-ETIMEDOUT) + */ + if (ret != -ETIMEDOUT) + ret = -EIO; + + DRM_WARN("INTEL_GUC_SEND: Action 0x%X failed;" + " ret=%d status=0x%08X response=0x%08X\n", + action[0], ret, status, I915_READ(SOFT_SCRATCH(15))); + } + + intel_uncore_forcewake_put(dev_priv, guc->send_regs.fw_domains); + mutex_unlock(&guc->send_mutex); + + return ret; +} + +int intel_guc_sample_forcewake(struct intel_guc *guc) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + u32 action[2]; + + action[0] = INTEL_GUC_ACTION_SAMPLE_FORCEWAKE; + /* WaRsDisableCoarsePowerGating:skl,bxt */ + if (!intel_rc6_enabled() || + NEEDS_WaRsDisableCoarsePowerGating(dev_priv)) + action[1] = 0; + else + /* bit 0 and 1 are for Render and Media domain separately */ + action[1] = GUC_FORCEWAKE_RENDER | GUC_FORCEWAKE_MEDIA; + + return intel_guc_send(guc, action, ARRAY_SIZE(action)); +} + +/** + * intel_guc_auth_huc() - Send action to GuC to authenticate HuC ucode + * @guc: intel_guc structure + * @rsa_offset: rsa offset w.r.t ggtt base of huc vma + * + * Triggers a HuC firmware authentication request to the GuC via intel_guc_send + * INTEL_GUC_ACTION_AUTHENTICATE_HUC interface. This function is invoked by + * intel_huc_auth(). + * + * Return: non-zero code on error + */ +int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset) +{ + u32 action[] = { + INTEL_GUC_ACTION_AUTHENTICATE_HUC, + rsa_offset + }; + + return intel_guc_send(guc, action, ARRAY_SIZE(action)); +} + +/** + * intel_guc_suspend() - notify GuC entering suspend state + * @dev_priv: i915 device private + */ +int intel_guc_suspend(struct drm_i915_private *dev_priv) +{ + struct intel_guc *guc = &dev_priv->guc; + struct i915_gem_context *ctx; + u32 data[3]; + + if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) + return 0; + + gen9_disable_guc_interrupts(dev_priv); + + ctx = dev_priv->kernel_context; + + data[0] = INTEL_GUC_ACTION_ENTER_S_STATE; + /* any value greater than GUC_POWER_D0 */ + data[1] = GUC_POWER_D1; + /* first page is shared data with GuC */ + data[2] = guc_ggtt_offset(ctx->engine[RCS].state) + + LRC_GUCSHR_PN * PAGE_SIZE; + + return intel_guc_send(guc, data, ARRAY_SIZE(data)); +} + +/** + * intel_guc_resume() - notify GuC resuming from suspend state + * @dev_priv: i915 device private + */ +int intel_guc_resume(struct drm_i915_private *dev_priv) +{ + struct intel_guc *guc = &dev_priv->guc; + struct i915_gem_context *ctx; + u32 data[3]; + + if (guc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) + return 0; + + if (i915_modparams.guc_log_level >= 0) + gen9_enable_guc_interrupts(dev_priv); + + ctx = dev_priv->kernel_context; + + data[0] = INTEL_GUC_ACTION_EXIT_S_STATE; + data[1] = GUC_POWER_D0; + /* first page is shared data with GuC */ + data[2] = guc_ggtt_offset(ctx->engine[RCS].state) + + LRC_GUCSHR_PN * PAGE_SIZE; + + return intel_guc_send(guc, data, ARRAY_SIZE(data)); +} + +/** + * intel_guc_allocate_vma() - Allocate a GGTT VMA for GuC usage + * @guc: the guc + * @size: size of area to allocate (both virtual space and memory) + * + * This is a wrapper to create an object for use with the GuC. In order to + * use it inside the GuC, an object needs to be pinned lifetime, so we allocate + * both some backing storage and a range inside the Global GTT. We must pin + * it in the GGTT somewhere other than than [0, GUC_WOPCM_TOP) because that + * range is reserved inside GuC. + * + * Return: A i915_vma if successful, otherwise an ERR_PTR. + */ +struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size) +{ + struct drm_i915_private *dev_priv = guc_to_i915(guc); + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + int ret; + + obj = i915_gem_object_create(dev_priv, size); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + vma = i915_vma_instance(obj, &dev_priv->ggtt.base, NULL); + if (IS_ERR(vma)) + goto err; + + ret = i915_vma_pin(vma, 0, PAGE_SIZE, + PIN_GLOBAL | PIN_OFFSET_BIAS | GUC_WOPCM_TOP); + if (ret) { + vma = ERR_PTR(ret); + goto err; + } + + return vma; + +err: + i915_gem_object_put(obj); + return vma; +} + +u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv) +{ + u32 wopcm_size = GUC_WOPCM_TOP; + + /* On BXT, the top of WOPCM is reserved for RC6 context */ + if (IS_GEN9_LP(dev_priv)) + wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED; + + return wopcm_size; +} diff --git a/drivers/gpu/drm/i915/intel_guc.h b/drivers/gpu/drm/i915/intel_guc.h new file mode 100644 index 000000000000..418450b1ae27 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_guc.h @@ -0,0 +1,120 @@ +/* + * Copyright © 2014-2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _INTEL_GUC_H_ +#define _INTEL_GUC_H_ + +#include "intel_uncore.h" +#include "intel_guc_fw.h" +#include "intel_guc_fwif.h" +#include "intel_guc_ct.h" +#include "intel_guc_log.h" +#include "intel_uc_fw.h" +#include "i915_guc_reg.h" +#include "i915_vma.h" + +/* + * Top level structure of GuC. It handles firmware loading and manages client + * pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy + * ExecList submission. + */ +struct intel_guc { + struct intel_uc_fw fw; + struct intel_guc_log log; + struct intel_guc_ct ct; + + /* Log snapshot if GuC errors during load */ + struct drm_i915_gem_object *load_err_log; + + /* intel_guc_recv interrupt related state */ + bool interrupts_enabled; + + struct i915_vma *ads_vma; + struct i915_vma *stage_desc_pool; + void *stage_desc_pool_vaddr; + struct ida stage_ids; + + struct i915_guc_client *execbuf_client; + + DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS); + /* Cyclic counter mod pagesize */ + u32 db_cacheline; + + /* GuC's FW specific registers used in MMIO send */ + struct { + u32 base; + unsigned int count; + enum forcewake_domains fw_domains; + } send_regs; + + /* To serialize the intel_guc_send actions */ + struct mutex send_mutex; + + /* GuC's FW specific send function */ + int (*send)(struct intel_guc *guc, const u32 *data, u32 len); + + /* GuC's FW specific notify function */ + void (*notify)(struct intel_guc *guc); +}; + +static +inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) +{ + return guc->send(guc, action, len); +} + +static inline void intel_guc_notify(struct intel_guc *guc) +{ + guc->notify(guc); +} + +/* + * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP), + * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is + * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects + * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM. + */ +static inline u32 guc_ggtt_offset(struct i915_vma *vma) +{ + u32 offset = i915_ggtt_offset(vma); + + GEM_BUG_ON(offset < GUC_WOPCM_TOP); + GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP)); + + return offset; +} + +void intel_guc_init_early(struct intel_guc *guc); +void intel_guc_init_send_regs(struct intel_guc *guc); +void intel_guc_init_params(struct intel_guc *guc); +int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len); +int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); +int intel_guc_sample_forcewake(struct intel_guc *guc); +int intel_guc_auth_huc(struct intel_guc *guc, u32 rsa_offset); +int intel_guc_suspend(struct drm_i915_private *dev_priv); +int intel_guc_resume(struct drm_i915_private *dev_priv); +struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); +u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv); + +#endif diff --git a/drivers/gpu/drm/i915/intel_guc_loader.c b/drivers/gpu/drm/i915/intel_guc_fw.c index 8b0ae7fce7f2..ef67a36354c5 100644 --- a/drivers/gpu/drm/i915/intel_guc_loader.c +++ b/drivers/gpu/drm/i915/intel_guc_fw.c @@ -26,31 +26,9 @@ * Dave Gordon <david.s.gordon@intel.com> * Alex Dai <yu.dai@intel.com> */ -#include "i915_drv.h" -#include "intel_uc.h" -/** - * DOC: GuC-specific firmware loader - * - * intel_guc: - * Top level structure of guc. It handles firmware loading and manages client - * pool and doorbells. intel_guc owns a i915_guc_client to replace the legacy - * ExecList submission. - * - * Firmware versioning: - * The firmware build process will generate a version header file with major and - * minor version defined. The versions are built into CSS header of firmware. - * i915 kernel driver set the minimal firmware version required per platform. - * The firmware installation package will install (symbolic link) proper version - * of firmware. - * - * GuC address space: - * GuC does not allow any gfx GGTT address that falls into range [0, WOPCM_TOP), - * which is reserved for Boot ROM, SRAM and WOPCM. Currently this top address is - * 512K. In order to exclude 0-512K address space from GGTT, all gfx objects - * used by GuC is pinned with PIN_OFFSET_BIAS along with size of WOPCM. - * - */ +#include "intel_guc_fw.h" +#include "i915_drv.h" #define SKL_FW_MAJOR 6 #define SKL_FW_MINOR 1 @@ -78,88 +56,45 @@ MODULE_FIRMWARE(I915_KBL_GUC_UCODE); #define I915_GLK_GUC_UCODE GUC_FW_PATH(glk, GLK_FW_MAJOR, GLK_FW_MINOR) - -static u32 get_gttype(struct drm_i915_private *dev_priv) -{ - /* XXX: GT type based on PCI device ID? field seems unused by fw */ - return 0; -} - -static u32 get_core_family(struct drm_i915_private *dev_priv) -{ - u32 gen = INTEL_GEN(dev_priv); - - switch (gen) { - case 9: - return GUC_CORE_FAMILY_GEN9; - - default: - MISSING_CASE(gen); - return GUC_CORE_FAMILY_UNKNOWN; - } -} - -/* - * Initialise the GuC parameter block before starting the firmware - * transfer. These parameters are read by the firmware on startup - * and cannot be changed thereafter. +/** + * intel_guc_fw_select() - selects GuC firmware for uploading + * + * @guc: intel_guc struct + * + * Return: zero when we know firmware, non-zero in other case */ -static void guc_params_init(struct drm_i915_private *dev_priv) +int intel_guc_fw_select(struct intel_guc *guc) { - struct intel_guc *guc = &dev_priv->guc; - u32 params[GUC_CTL_MAX_DWORDS]; - int i; - - memset(¶ms, 0, sizeof(params)); - - params[GUC_CTL_DEVICE_INFO] |= - (get_gttype(dev_priv) << GUC_CTL_GTTYPE_SHIFT) | - (get_core_family(dev_priv) << GUC_CTL_COREFAMILY_SHIFT); - - /* - * GuC ARAT increment is 10 ns. GuC default scheduler quantum is one - * second. This ARAR is calculated by: - * Scheduler-Quantum-in-ns / ARAT-increment-in-ns = 1000000000 / 10 - */ - params[GUC_CTL_ARAT_HIGH] = 0; - params[GUC_CTL_ARAT_LOW] = 100000000; - - params[GUC_CTL_WA] |= GUC_CTL_WA_UK_BY_DRIVER; - - params[GUC_CTL_FEATURE] |= GUC_CTL_DISABLE_SCHEDULER | - GUC_CTL_VCS2_ENABLED; - - params[GUC_CTL_LOG_PARAMS] = guc->log.flags; - - if (i915.guc_log_level >= 0) { - params[GUC_CTL_DEBUG] = - i915.guc_log_level << GUC_LOG_VERBOSITY_SHIFT; - } else - params[GUC_CTL_DEBUG] = GUC_LOG_DISABLED; - - /* If GuC submission is enabled, set up additional parameters here */ - if (i915.enable_guc_submission) { - u32 ads = guc_ggtt_offset(guc->ads_vma) >> PAGE_SHIFT; - u32 pgs = guc_ggtt_offset(dev_priv->guc.stage_desc_pool); - u32 ctx_in_16 = GUC_MAX_STAGE_DESCRIPTORS / 16; - - params[GUC_CTL_DEBUG] |= ads << GUC_ADS_ADDR_SHIFT; - params[GUC_CTL_DEBUG] |= GUC_ADS_ENABLED; - - pgs >>= PAGE_SHIFT; - params[GUC_CTL_CTXINFO] = (pgs << GUC_CTL_BASE_ADDR_SHIFT) | - (ctx_in_16 << GUC_CTL_CTXNUM_IN16_SHIFT); + struct drm_i915_private *dev_priv = guc_to_i915(guc); - params[GUC_CTL_FEATURE] |= GUC_CTL_KERNEL_SUBMISSIONS; + intel_uc_fw_init(&guc->fw, INTEL_UC_FW_TYPE_GUC); - /* Unmask this bit to enable the GuC's internal scheduler */ - params[GUC_CTL_FEATURE] &= ~GUC_CTL_DISABLE_SCHEDULER; + if (i915_modparams.guc_firmware_path) { + guc->fw.path = i915_modparams.guc_firmware_path; + guc->fw.major_ver_wanted = 0; + guc->fw.minor_ver_wanted = 0; + } else if (IS_SKYLAKE(dev_priv)) { + guc->fw.path = I915_SKL_GUC_UCODE; + guc->fw.major_ver_wanted = SKL_FW_MAJOR; + guc->fw.minor_ver_wanted = SKL_FW_MINOR; + } else if (IS_BROXTON(dev_priv)) { + guc->fw.path = I915_BXT_GUC_UCODE; + guc->fw.major_ver_wanted = BXT_FW_MAJOR; + guc->fw.minor_ver_wanted = BXT_FW_MINOR; + } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { + guc->fw.path = I915_KBL_GUC_UCODE; + guc->fw.major_ver_wanted = KBL_FW_MAJOR; + guc->fw.minor_ver_wanted = KBL_FW_MINOR; + } else if (IS_GEMINILAKE(dev_priv)) { + guc->fw.path = I915_GLK_GUC_UCODE; + guc->fw.major_ver_wanted = GLK_FW_MAJOR; + guc->fw.minor_ver_wanted = GLK_FW_MINOR; + } else { + DRM_ERROR("No GuC firmware known for platform with GuC!\n"); + return -ENOENT; } - I915_WRITE(SOFT_SCRATCH(0), 0); - - for (i = 0; i < GUC_CTL_MAX_DWORDS; i++) - I915_WRITE(SOFT_SCRATCH(1 + i), params[i]); + return 0; } /* @@ -250,38 +185,16 @@ static int guc_ucode_xfer_dma(struct drm_i915_private *dev_priv, return ret; } -u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv) -{ - u32 wopcm_size = GUC_WOPCM_TOP; - - /* On BXT, the top of WOPCM is reserved for RC6 context */ - if (IS_GEN9_LP(dev_priv)) - wopcm_size -= BXT_GUC_WOPCM_RC6_RESERVED; - - return wopcm_size; -} - /* * Load the GuC firmware blob into the MinuteIA. */ -static int guc_ucode_xfer(struct drm_i915_private *dev_priv) +static int guc_ucode_xfer(struct intel_uc_fw *guc_fw, struct i915_vma *vma) { - struct intel_uc_fw *guc_fw = &dev_priv->guc.fw; - struct i915_vma *vma; + struct intel_guc *guc = container_of(guc_fw, struct intel_guc, fw); + struct drm_i915_private *dev_priv = guc_to_i915(guc); int ret; - ret = i915_gem_object_set_to_gtt_domain(guc_fw->obj, false); - if (ret) { - DRM_DEBUG_DRIVER("set-domain failed %d\n", ret); - return ret; - } - - vma = i915_gem_object_ggtt_pin(guc_fw->obj, NULL, 0, 0, - PIN_OFFSET_BIAS | GUC_WOPCM_TOP); - if (IS_ERR(vma)) { - DRM_DEBUG_DRIVER("pin failed %d\n", (int)PTR_ERR(vma)); - return PTR_ERR(vma); - } + GEM_BUG_ON(guc_fw->type != INTEL_UC_FW_TYPE_GUC); intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); @@ -312,23 +225,15 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) I915_WRITE(GUC_ARAT_C6DIS, 0x1FF); } - guc_params_init(dev_priv); - ret = guc_ucode_xfer_dma(dev_priv, vma); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); - /* - * We keep the object pages for reuse during resume. But we can unpin it - * now that DMA has completed, so it doesn't continue to take up space. - */ - i915_vma_unpin(vma); - return ret; } /** - * intel_guc_init_hw() - finish preparing the GuC for activity + * intel_guc_fw_upload() - finish preparing the GuC for activity * @guc: intel_guc structure * * Called during driver loading and also after a GPU reset. @@ -340,80 +245,7 @@ static int guc_ucode_xfer(struct drm_i915_private *dev_priv) * * Return: non-zero code on error */ -int intel_guc_init_hw(struct intel_guc *guc) +int intel_guc_fw_upload(struct intel_guc *guc) { - struct drm_i915_private *dev_priv = guc_to_i915(guc); - const char *fw_path = guc->fw.path; - int ret; - - DRM_DEBUG_DRIVER("GuC fw status: path %s, fetch %s, load %s\n", - fw_path, - intel_uc_fw_status_repr(guc->fw.fetch_status), - intel_uc_fw_status_repr(guc->fw.load_status)); - - if (guc->fw.fetch_status != INTEL_UC_FIRMWARE_SUCCESS) - return -EIO; - - guc->fw.load_status = INTEL_UC_FIRMWARE_PENDING; - - DRM_DEBUG_DRIVER("GuC fw status: fetch %s, load %s\n", - intel_uc_fw_status_repr(guc->fw.fetch_status), - intel_uc_fw_status_repr(guc->fw.load_status)); - - ret = guc_ucode_xfer(dev_priv); - - if (ret) - return -EAGAIN; - - guc->fw.load_status = INTEL_UC_FIRMWARE_SUCCESS; - - DRM_INFO("GuC %s (firmware %s [version %u.%u])\n", - i915.enable_guc_submission ? "submission enabled" : "loaded", - guc->fw.path, - guc->fw.major_ver_found, guc->fw.minor_ver_found); - - return 0; -} - -/** - * intel_guc_select_fw() - selects GuC firmware for loading - * @guc: intel_guc struct - * - * Return: zero when we know firmware, non-zero in other case - */ -int intel_guc_select_fw(struct intel_guc *guc) -{ - struct drm_i915_private *dev_priv = guc_to_i915(guc); - - guc->fw.path = NULL; - guc->fw.fetch_status = INTEL_UC_FIRMWARE_NONE; - guc->fw.load_status = INTEL_UC_FIRMWARE_NONE; - guc->fw.type = INTEL_UC_FW_TYPE_GUC; - - if (i915.guc_firmware_path) { - guc->fw.path = i915.guc_firmware_path; - guc->fw.major_ver_wanted = 0; - guc->fw.minor_ver_wanted = 0; - } else if (IS_SKYLAKE(dev_priv)) { - guc->fw.path = I915_SKL_GUC_UCODE; - guc->fw.major_ver_wanted = SKL_FW_MAJOR; - guc->fw.minor_ver_wanted = SKL_FW_MINOR; - } else if (IS_BROXTON(dev_priv)) { - guc->fw.path = I915_BXT_GUC_UCODE; - guc->fw.major_ver_wanted = BXT_FW_MAJOR; - guc->fw.minor_ver_wanted = BXT_FW_MINOR; - } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { - guc->fw.path = I915_KBL_GUC_UCODE; - guc->fw.major_ver_wanted = KBL_FW_MAJOR; - guc->fw.minor_ver_wanted = KBL_FW_MINOR; - } else if (IS_GEMINILAKE(dev_priv)) { - guc->fw.path = I915_GLK_GUC_UCODE; - guc->fw.major_ver_wanted = GLK_FW_MAJOR; - guc->fw.minor_ver_wanted = GLK_FW_MINOR; - } else { - DRM_ERROR("No GuC firmware known for platform with GuC!\n"); - return -ENOENT; - } - - return 0; + return intel_uc_fw_upload(&guc->fw, guc_ucode_xfer); } diff --git a/drivers/gpu/drm/i915/intel_guc_fw.h b/drivers/gpu/drm/i915/intel_guc_fw.h new file mode 100644 index 000000000000..023f5baa9dd6 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_guc_fw.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _INTEL_GUC_FW_H_ +#define _INTEL_GUC_FW_H_ + +struct intel_guc; + +int intel_guc_fw_select(struct intel_guc *guc); +int intel_guc_fw_upload(struct intel_guc *guc); + +#endif diff --git a/drivers/gpu/drm/i915/intel_guc_fwif.h b/drivers/gpu/drm/i915/intel_guc_fwif.h index 5fa286074811..80c507435458 100644 --- a/drivers/gpu/drm/i915/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/intel_guc_fwif.h @@ -56,10 +56,6 @@ #define WQ_LEN_SHIFT 16 #define WQ_NO_WCFLUSH_WAIT (1 << 27) #define WQ_PRESENT_WORKLOAD (1 << 28) -#define WQ_WORKLOAD_SHIFT 29 -#define WQ_WORKLOAD_GENERAL (0 << WQ_WORKLOAD_SHIFT) -#define WQ_WORKLOAD_GPGPU (1 << WQ_WORKLOAD_SHIFT) -#define WQ_WORKLOAD_TOUCH (2 << WQ_WORKLOAD_SHIFT) #define WQ_RING_TAIL_SHIFT 20 #define WQ_RING_TAIL_MAX 0x7FF /* 2^11 QWords */ @@ -86,8 +82,8 @@ #define GUC_CTL_ARAT_LOW 2 #define GUC_CTL_DEVICE_INFO 3 -#define GUC_CTL_GTTYPE_SHIFT 0 -#define GUC_CTL_COREFAMILY_SHIFT 7 +#define GUC_CTL_GT_TYPE_SHIFT 0 +#define GUC_CTL_CORE_FAMILY_SHIFT 7 #define GUC_CTL_LOG_PARAMS 4 #define GUC_LOG_VALID (1 << 0) @@ -182,49 +178,49 @@ */ struct uc_css_header { - uint32_t module_type; + u32 module_type; /* header_size includes all non-uCode bits, including css_header, rsa * key, modulus key and exponent data. */ - uint32_t header_size_dw; - uint32_t header_version; - uint32_t module_id; - uint32_t module_vendor; + u32 header_size_dw; + u32 header_version; + u32 module_id; + u32 module_vendor; union { struct { - uint8_t day; - uint8_t month; - uint16_t year; + u8 day; + u8 month; + u16 year; }; - uint32_t date; + u32 date; }; - uint32_t size_dw; /* uCode plus header_size_dw */ - uint32_t key_size_dw; - uint32_t modulus_size_dw; - uint32_t exponent_size_dw; + u32 size_dw; /* uCode plus header_size_dw */ + u32 key_size_dw; + u32 modulus_size_dw; + u32 exponent_size_dw; union { struct { - uint8_t hour; - uint8_t min; - uint16_t sec; + u8 hour; + u8 min; + u16 sec; }; - uint32_t time; + u32 time; }; char username[8]; char buildnumber[12]; union { struct { - uint32_t branch_client_version; - uint32_t sw_version; + u32 branch_client_version; + u32 sw_version; } guc; struct { - uint32_t sw_version; - uint32_t reserved; + u32 sw_version; + u32 reserved; } huc; }; - uint32_t prod_preprod_fw; - uint32_t reserved[12]; - uint32_t header_info; + u32 prod_preprod_fw; + u32 reserved[12]; + u32 header_info; } __packed; struct guc_doorbell_info { @@ -388,7 +384,11 @@ struct guc_ct_buffer_desc { /* Preempt to idle on quantum expiry */ #define POLICY_PREEMPT_TO_IDLE (1<<1) -#define POLICY_MAX_NUM_WI 15 +#define POLICY_MAX_NUM_WI 15 +#define POLICY_DEFAULT_DPC_PROMOTE_TIME_US 500000 +#define POLICY_DEFAULT_EXECUTION_QUANTUM_US 1000000 +#define POLICY_DEFAULT_PREEMPTION_TIME_US 500000 +#define POLICY_DEFAULT_FAULT_TIME_US 250000 struct guc_policy { /* Time for one workload to execute. (in micro seconds) */ diff --git a/drivers/gpu/drm/i915/intel_guc_log.c b/drivers/gpu/drm/i915/intel_guc_log.c index 16d3b8719cab..76d3eb1e4614 100644 --- a/drivers/gpu/drm/i915/intel_guc_log.c +++ b/drivers/gpu/drm/i915/intel_guc_log.c @@ -21,8 +21,11 @@ * IN THE SOFTWARE. * */ + #include <linux/debugfs.h> #include <linux/relay.h> + +#include "intel_guc_log.h" #include "i915_drv.h" static void guc_log_capture_logs(struct intel_guc *guc); @@ -144,7 +147,7 @@ static int guc_log_relay_file_create(struct intel_guc *guc) struct dentry *log_dir; int ret; - if (i915.guc_log_level < 0) + if (i915_modparams.guc_log_level < 0) return 0; /* For now create the log file in /sys/kernel/debug/dri/0 dir */ @@ -480,7 +483,7 @@ err_runtime: guc_log_runtime_destroy(guc); err: /* logging will remain off */ - i915.guc_log_level = -1; + i915_modparams.guc_log_level = -1; return ret; } @@ -502,7 +505,8 @@ static void guc_flush_logs(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); - if (!i915.enable_guc_submission || (i915.guc_log_level < 0)) + if (!i915_modparams.enable_guc_submission || + (i915_modparams.guc_log_level < 0)) return; /* First disable the interrupts, will be renabled afterwards */ @@ -524,13 +528,14 @@ int intel_guc_log_create(struct intel_guc *guc) { struct i915_vma *vma; unsigned long offset; - uint32_t size, flags; + u32 flags; + u32 size; int ret; GEM_BUG_ON(guc->log.vma); - if (i915.guc_log_level > GUC_LOG_VERBOSITY_MAX) - i915.guc_log_level = GUC_LOG_VERBOSITY_MAX; + if (i915_modparams.guc_log_level > GUC_LOG_VERBOSITY_MAX) + i915_modparams.guc_log_level = GUC_LOG_VERBOSITY_MAX; /* The first page is to save log buffer state. Allocate one * extra page for others in case for overlap */ @@ -555,7 +560,7 @@ int intel_guc_log_create(struct intel_guc *guc) guc->log.vma = vma; - if (i915.guc_log_level >= 0) { + if (i915_modparams.guc_log_level >= 0) { ret = guc_log_runtime_create(guc); if (ret < 0) goto err_vma; @@ -576,7 +581,7 @@ err_vma: i915_vma_unpin_and_release(&guc->log.vma); err: /* logging will be off */ - i915.guc_log_level = -1; + i915_modparams.guc_log_level = -1; return ret; } @@ -600,7 +605,7 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) return -EINVAL; /* This combination doesn't make sense & won't have any effect */ - if (!log_param.logging_enabled && (i915.guc_log_level < 0)) + if (!log_param.logging_enabled && (i915_modparams.guc_log_level < 0)) return 0; ret = guc_log_control(guc, log_param.value); @@ -610,7 +615,7 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) } if (log_param.logging_enabled) { - i915.guc_log_level = log_param.verbosity; + i915_modparams.guc_log_level = log_param.verbosity; /* If log_level was set as -1 at boot time, then the relay channel file * wouldn't have been created by now and interrupts also would not have @@ -633,7 +638,7 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) guc_flush_logs(guc); /* As logging is disabled, update log level to reflect that */ - i915.guc_log_level = -1; + i915_modparams.guc_log_level = -1; } return ret; @@ -641,7 +646,8 @@ int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val) void i915_guc_log_register(struct drm_i915_private *dev_priv) { - if (!i915.enable_guc_submission || i915.guc_log_level < 0) + if (!i915_modparams.enable_guc_submission || + (i915_modparams.guc_log_level < 0)) return; mutex_lock(&dev_priv->drm.struct_mutex); @@ -651,7 +657,7 @@ void i915_guc_log_register(struct drm_i915_private *dev_priv) void i915_guc_log_unregister(struct drm_i915_private *dev_priv) { - if (!i915.enable_guc_submission) + if (!i915_modparams.enable_guc_submission) return; mutex_lock(&dev_priv->drm.struct_mutex); diff --git a/drivers/gpu/drm/i915/intel_guc_log.h b/drivers/gpu/drm/i915/intel_guc_log.h new file mode 100644 index 000000000000..f512cf79339b --- /dev/null +++ b/drivers/gpu/drm/i915/intel_guc_log.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2014-2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _INTEL_GUC_LOG_H_ +#define _INTEL_GUC_LOG_H_ + +#include <linux/workqueue.h> + +#include "intel_guc_fwif.h" + +struct drm_i915_private; +struct intel_guc; + +struct intel_guc_log { + u32 flags; + struct i915_vma *vma; + /* The runtime stuff gets created only when GuC logging gets enabled */ + struct { + void *buf_addr; + struct workqueue_struct *flush_wq; + struct work_struct flush_work; + struct rchan *relay_chan; + } runtime; + /* logging related stats */ + u32 capture_miss_count; + u32 flush_interrupt_count; + u32 prev_overflow_count[GUC_MAX_LOG_BUFFER]; + u32 total_overflow_count[GUC_MAX_LOG_BUFFER]; + u32 flush_count[GUC_MAX_LOG_BUFFER]; +}; + +int intel_guc_log_create(struct intel_guc *guc); +void intel_guc_log_destroy(struct intel_guc *guc); +int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val); +void i915_guc_log_register(struct drm_i915_private *dev_priv); +void i915_guc_log_unregister(struct drm_i915_private *dev_priv); + +#endif diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c index c17ed0e62b67..b4a7f31f0214 100644 --- a/drivers/gpu/drm/i915/intel_gvt.c +++ b/drivers/gpu/drm/i915/intel_gvt.c @@ -58,7 +58,7 @@ static bool is_supported_device(struct drm_i915_private *dev_priv) */ void intel_gvt_sanitize_options(struct drm_i915_private *dev_priv) { - if (!i915.enable_gvt) + if (!i915_modparams.enable_gvt) return; if (intel_vgpu_active(dev_priv)) { @@ -73,7 +73,7 @@ void intel_gvt_sanitize_options(struct drm_i915_private *dev_priv) return; bail: - i915.enable_gvt = 0; + i915_modparams.enable_gvt = 0; } /** @@ -90,17 +90,17 @@ int intel_gvt_init(struct drm_i915_private *dev_priv) { int ret; - if (!i915.enable_gvt) { + if (!i915_modparams.enable_gvt) { DRM_DEBUG_DRIVER("GVT-g is disabled by kernel params\n"); return 0; } - if (!i915.enable_execlists) { + if (!i915_modparams.enable_execlists) { DRM_ERROR("i915 GVT-g loading failed due to disabled execlists mode\n"); return -EIO; } - if (i915.enable_guc_submission) { + if (i915_modparams.enable_guc_submission) { DRM_ERROR("i915 GVT-g loading failed due to Graphics virtualization is not yet supported with GuC submission\n"); return -EIO; } @@ -123,7 +123,7 @@ int intel_gvt_init(struct drm_i915_private *dev_priv) return 0; bail: - i915.enable_gvt = 0; + i915_modparams.enable_gvt = 0; return 0; } diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index d9d87d96fb69..12ac270a5f93 100644 --- a/drivers/gpu/drm/i915/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/intel_hangcheck.c @@ -428,7 +428,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work) unsigned int hung = 0, stuck = 0; int busy_count = 0; - if (!i915.enable_hangcheck) + if (!i915_modparams.enable_hangcheck) return; if (!READ_ONCE(dev_priv->gt.awake)) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index e6f8f30ce7bd..5132dc814788 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -70,7 +70,7 @@ static struct intel_hdmi *intel_attached_hdmi(struct drm_connector *connector) return enc_to_intel_hdmi(&intel_attached_encoder(connector)->base); } -static u32 g4x_infoframe_index(enum hdmi_infoframe_type type) +static u32 g4x_infoframe_index(unsigned int type) { switch (type) { case HDMI_INFOFRAME_TYPE_AVI: @@ -85,7 +85,7 @@ static u32 g4x_infoframe_index(enum hdmi_infoframe_type type) } } -static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type) +static u32 g4x_infoframe_enable(unsigned int type) { switch (type) { case HDMI_INFOFRAME_TYPE_AVI: @@ -100,9 +100,11 @@ static u32 g4x_infoframe_enable(enum hdmi_infoframe_type type) } } -static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type) +static u32 hsw_infoframe_enable(unsigned int type) { switch (type) { + case DP_SDP_VSC: + return VIDEO_DIP_ENABLE_VSC_HSW; case HDMI_INFOFRAME_TYPE_AVI: return VIDEO_DIP_ENABLE_AVI_HSW; case HDMI_INFOFRAME_TYPE_SPD: @@ -118,10 +120,12 @@ static u32 hsw_infoframe_enable(enum hdmi_infoframe_type type) static i915_reg_t hsw_dip_data_reg(struct drm_i915_private *dev_priv, enum transcoder cpu_transcoder, - enum hdmi_infoframe_type type, + unsigned int type, int i) { switch (type) { + case DP_SDP_VSC: + return HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_AVI: return HSW_TVIDEO_DIP_AVI_DATA(cpu_transcoder, i); case HDMI_INFOFRAME_TYPE_SPD: @@ -136,7 +140,7 @@ hsw_dip_data_reg(struct drm_i915_private *dev_priv, static void g4x_write_infoframe(struct drm_encoder *encoder, const struct intel_crtc_state *crtc_state, - enum hdmi_infoframe_type type, + unsigned int type, const void *frame, ssize_t len) { const uint32_t *data = frame; @@ -191,7 +195,7 @@ static bool g4x_infoframe_enabled(struct drm_encoder *encoder, static void ibx_write_infoframe(struct drm_encoder *encoder, const struct intel_crtc_state *crtc_state, - enum hdmi_infoframe_type type, + unsigned int type, const void *frame, ssize_t len) { const uint32_t *data = frame; @@ -251,7 +255,7 @@ static bool ibx_infoframe_enabled(struct drm_encoder *encoder, static void cpt_write_infoframe(struct drm_encoder *encoder, const struct intel_crtc_state *crtc_state, - enum hdmi_infoframe_type type, + unsigned int type, const void *frame, ssize_t len) { const uint32_t *data = frame; @@ -309,7 +313,7 @@ static bool cpt_infoframe_enabled(struct drm_encoder *encoder, static void vlv_write_infoframe(struct drm_encoder *encoder, const struct intel_crtc_state *crtc_state, - enum hdmi_infoframe_type type, + unsigned int type, const void *frame, ssize_t len) { const uint32_t *data = frame; @@ -368,7 +372,7 @@ static bool vlv_infoframe_enabled(struct drm_encoder *encoder, static void hsw_write_infoframe(struct drm_encoder *encoder, const struct intel_crtc_state *crtc_state, - enum hdmi_infoframe_type type, + unsigned int type, const void *frame, ssize_t len) { const uint32_t *data = frame; @@ -377,6 +381,8 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); i915_reg_t data_reg; + int data_size = type == DP_SDP_VSC ? + VIDEO_DIP_VSC_DATA_SIZE : VIDEO_DIP_DATA_SIZE; int i; u32 val = I915_READ(ctl_reg); @@ -392,7 +398,7 @@ static void hsw_write_infoframe(struct drm_encoder *encoder, data++; } /* Write every possible data byte to force correct ECC calculation. */ - for (; i < VIDEO_DIP_DATA_SIZE; i += 4) + for (; i < data_size; i += 4) I915_WRITE(hsw_dip_data_reg(dev_priv, cpu_transcoder, type, i >> 2), 0); mmiowb(); diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 6145fa0d6773..c8a48cbc2b7d 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c @@ -21,9 +21,11 @@ * IN THE SOFTWARE. * */ -#include <linux/firmware.h> + +#include <linux/types.h> + +#include "intel_huc.h" #include "i915_drv.h" -#include "intel_uc.h" /** * DOC: HuC Firmware @@ -76,6 +78,42 @@ MODULE_FIRMWARE(I915_KBL_HUC_UCODE); GLK_HUC_FW_MINOR, GLK_BLD_NUM) /** + * intel_huc_select_fw() - selects HuC firmware for loading + * @huc: intel_huc struct + */ +void intel_huc_select_fw(struct intel_huc *huc) +{ + struct drm_i915_private *dev_priv = huc_to_i915(huc); + + intel_uc_fw_init(&huc->fw, INTEL_UC_FW_TYPE_HUC); + + if (i915_modparams.huc_firmware_path) { + huc->fw.path = i915_modparams.huc_firmware_path; + huc->fw.major_ver_wanted = 0; + huc->fw.minor_ver_wanted = 0; + } else if (IS_SKYLAKE(dev_priv)) { + huc->fw.path = I915_SKL_HUC_UCODE; + huc->fw.major_ver_wanted = SKL_HUC_FW_MAJOR; + huc->fw.minor_ver_wanted = SKL_HUC_FW_MINOR; + } else if (IS_BROXTON(dev_priv)) { + huc->fw.path = I915_BXT_HUC_UCODE; + huc->fw.major_ver_wanted = BXT_HUC_FW_MAJOR; + huc->fw.minor_ver_wanted = BXT_HUC_FW_MINOR; + } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { + huc->fw.path = I915_KBL_HUC_UCODE; + huc->fw.major_ver_wanted = KBL_HUC_FW_MAJOR; + huc->fw.minor_ver_wanted = KBL_HUC_FW_MINOR; + } else if (IS_GEMINILAKE(dev_priv)) { + huc->fw.path = I915_GLK_HUC_UCODE; + huc->fw.major_ver_wanted = GLK_HUC_FW_MAJOR; + huc->fw.minor_ver_wanted = GLK_HUC_FW_MINOR; + } else { + DRM_ERROR("No HuC firmware known for platform with HuC!\n"); + return; + } +} + +/** * huc_ucode_xfer() - DMA's the firmware * @dev_priv: the drm_i915_private device * @@ -83,26 +121,15 @@ MODULE_FIRMWARE(I915_KBL_HUC_UCODE); * * Return: 0 on success, non-zero on failure */ -static int huc_ucode_xfer(struct drm_i915_private *dev_priv) +static int huc_ucode_xfer(struct intel_uc_fw *huc_fw, struct i915_vma *vma) { - struct intel_uc_fw *huc_fw = &dev_priv->huc.fw; - struct i915_vma *vma; + struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw); + struct drm_i915_private *dev_priv = huc_to_i915(huc); unsigned long offset = 0; u32 size; int ret; - ret = i915_gem_object_set_to_gtt_domain(huc_fw->obj, false); - if (ret) { - DRM_DEBUG_DRIVER("set-domain failed %d\n", ret); - return ret; - } - - vma = i915_gem_object_ggtt_pin(huc_fw->obj, NULL, 0, 0, - PIN_OFFSET_BIAS | GUC_WOPCM_TOP); - if (IS_ERR(vma)) { - DRM_DEBUG_DRIVER("pin failed %d\n", (int)PTR_ERR(vma)); - return PTR_ERR(vma); - } + GEM_BUG_ON(huc_fw->type != INTEL_UC_FW_TYPE_HUC); intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); @@ -133,55 +160,10 @@ static int huc_ucode_xfer(struct drm_i915_private *dev_priv) intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); - /* - * We keep the object pages for reuse during resume. But we can unpin it - * now that DMA has completed, so it doesn't continue to take up space. - */ - i915_vma_unpin(vma); - return ret; } /** - * intel_huc_select_fw() - selects HuC firmware for loading - * @huc: intel_huc struct - */ -void intel_huc_select_fw(struct intel_huc *huc) -{ - struct drm_i915_private *dev_priv = huc_to_i915(huc); - - huc->fw.path = NULL; - huc->fw.fetch_status = INTEL_UC_FIRMWARE_NONE; - huc->fw.load_status = INTEL_UC_FIRMWARE_NONE; - huc->fw.type = INTEL_UC_FW_TYPE_HUC; - - if (i915.huc_firmware_path) { - huc->fw.path = i915.huc_firmware_path; - huc->fw.major_ver_wanted = 0; - huc->fw.minor_ver_wanted = 0; - } else if (IS_SKYLAKE(dev_priv)) { - huc->fw.path = I915_SKL_HUC_UCODE; - huc->fw.major_ver_wanted = SKL_HUC_FW_MAJOR; - huc->fw.minor_ver_wanted = SKL_HUC_FW_MINOR; - } else if (IS_BROXTON(dev_priv)) { - huc->fw.path = I915_BXT_HUC_UCODE; - huc->fw.major_ver_wanted = BXT_HUC_FW_MAJOR; - huc->fw.minor_ver_wanted = BXT_HUC_FW_MINOR; - } else if (IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) { - huc->fw.path = I915_KBL_HUC_UCODE; - huc->fw.major_ver_wanted = KBL_HUC_FW_MAJOR; - huc->fw.minor_ver_wanted = KBL_HUC_FW_MINOR; - } else if (IS_GEMINILAKE(dev_priv)) { - huc->fw.path = I915_GLK_HUC_UCODE; - huc->fw.major_ver_wanted = GLK_HUC_FW_MAJOR; - huc->fw.minor_ver_wanted = GLK_HUC_FW_MINOR; - } else { - DRM_ERROR("No HuC firmware known for platform with HuC!\n"); - return; - } -} - -/** * intel_huc_init_hw() - load HuC uCode to device * @huc: intel_huc structure * @@ -195,49 +177,26 @@ void intel_huc_select_fw(struct intel_huc *huc) */ void intel_huc_init_hw(struct intel_huc *huc) { - struct drm_i915_private *dev_priv = huc_to_i915(huc); - int err; - - DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n", - huc->fw.path, - intel_uc_fw_status_repr(huc->fw.fetch_status), - intel_uc_fw_status_repr(huc->fw.load_status)); - - if (huc->fw.fetch_status != INTEL_UC_FIRMWARE_SUCCESS) - return; - - huc->fw.load_status = INTEL_UC_FIRMWARE_PENDING; - - err = huc_ucode_xfer(dev_priv); - - huc->fw.load_status = err ? - INTEL_UC_FIRMWARE_FAIL : INTEL_UC_FIRMWARE_SUCCESS; - - DRM_DEBUG_DRIVER("%s fw status: fetch %s, load %s\n", - huc->fw.path, - intel_uc_fw_status_repr(huc->fw.fetch_status), - intel_uc_fw_status_repr(huc->fw.load_status)); - - if (huc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) - DRM_ERROR("Failed to complete HuC uCode load with ret %d\n", err); - - return; + intel_uc_fw_upload(&huc->fw, huc_ucode_xfer); } /** - * intel_guc_auth_huc() - authenticate ucode - * @dev_priv: the drm_i915_device + * intel_huc_auth() - Authenticate HuC uCode + * @huc: intel_huc structure + * + * Called after HuC and GuC firmware loading during intel_uc_init_hw(). * - * Triggers a HuC fw authentication request to the GuC via intel_guc_action_ - * authenticate_huc interface. + * This function pins HuC firmware image object into GGTT. + * Then it invokes GuC action to authenticate passing the offset to RSA + * signature through intel_guc_auth_huc(). It then waits for 50ms for + * firmware verification ACK and unpins the object. */ -void intel_guc_auth_huc(struct drm_i915_private *dev_priv) +void intel_huc_auth(struct intel_huc *huc) { - struct intel_guc *guc = &dev_priv->guc; - struct intel_huc *huc = &dev_priv->huc; + struct drm_i915_private *i915 = huc_to_i915(huc); + struct intel_guc *guc = &i915->guc; struct i915_vma *vma; int ret; - u32 data[2]; if (huc->fw.load_status != INTEL_UC_FIRMWARE_SUCCESS) return; @@ -250,23 +209,19 @@ void intel_guc_auth_huc(struct drm_i915_private *dev_priv) return; } - /* Specify auth action and where public signature is. */ - data[0] = INTEL_GUC_ACTION_AUTHENTICATE_HUC; - data[1] = guc_ggtt_offset(vma) + huc->fw.rsa_offset; - - ret = intel_guc_send(guc, data, ARRAY_SIZE(data)); + ret = intel_guc_auth_huc(guc, + guc_ggtt_offset(vma) + huc->fw.rsa_offset); if (ret) { DRM_ERROR("HuC: GuC did not ack Auth request %d\n", ret); goto out; } /* Check authentication status, it should be done by now */ - ret = intel_wait_for_register(dev_priv, - HUC_STATUS2, - HUC_FW_VERIFIED, - HUC_FW_VERIFIED, - 50); - + ret = intel_wait_for_register(i915, + HUC_STATUS2, + HUC_FW_VERIFIED, + HUC_FW_VERIFIED, + 50); if (ret) { DRM_ERROR("HuC: Authentication failed %d\n", ret); goto out; @@ -275,4 +230,3 @@ void intel_guc_auth_huc(struct drm_i915_private *dev_priv) out: i915_vma_unpin(vma); } - diff --git a/drivers/gpu/drm/i915/intel_huc.h b/drivers/gpu/drm/i915/intel_huc.h new file mode 100644 index 000000000000..aaa38b9e5817 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_huc.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2014-2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _INTEL_HUC_H_ +#define _INTEL_HUC_H_ + +#include "intel_uc_fw.h" + +struct intel_huc { + /* Generic uC firmware management */ + struct intel_uc_fw fw; + + /* HuC-specific additions */ +}; + +void intel_huc_select_fw(struct intel_huc *huc); +void intel_huc_init_hw(struct intel_huc *huc); +void intel_huc_auth(struct intel_huc *huc); + +#endif diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index d89e1b8e1cc5..d36e25607435 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -208,8 +208,9 @@ /* Typical size of the average request (2 pipecontrols and a MI_BB) */ #define EXECLISTS_REQUEST_SIZE 64 /* bytes */ - #define WA_TAIL_DWORDS 2 +#define WA_TAIL_BYTES (sizeof(u32) * WA_TAIL_DWORDS) +#define PREEMPT_ID 0x1 static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, struct intel_engine_cs *engine); @@ -243,8 +244,7 @@ int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv, int enabl return 0; if (HAS_LOGICAL_RING_CONTEXTS(dev_priv) && - USES_PPGTT(dev_priv) && - i915.use_mmio_flip >= 0) + USES_PPGTT(dev_priv)) return 1; return 0; @@ -279,17 +279,110 @@ intel_lr_context_descriptor_update(struct i915_gem_context *ctx, BUILD_BUG_ON(MAX_CONTEXT_HW_ID > (1<<GEN8_CTX_ID_WIDTH)); desc = ctx->desc_template; /* bits 0-11 */ - desc |= i915_ggtt_offset(ce->state) + LRC_PPHWSP_PN * PAGE_SIZE; + desc |= i915_ggtt_offset(ce->state) + LRC_HEADER_PAGES * PAGE_SIZE; /* bits 12-31 */ desc |= (u64)ctx->hw_id << GEN8_CTX_ID_SHIFT; /* bits 32-52 */ ce->lrc_desc = desc; } -uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx, - struct intel_engine_cs *engine) +static struct i915_priolist * +lookup_priolist(struct intel_engine_cs *engine, + struct i915_priotree *pt, + int prio) +{ + struct intel_engine_execlists * const execlists = &engine->execlists; + struct i915_priolist *p; + struct rb_node **parent, *rb; + bool first = true; + + if (unlikely(execlists->no_priolist)) + prio = I915_PRIORITY_NORMAL; + +find_priolist: + /* most positive priority is scheduled first, equal priorities fifo */ + rb = NULL; + parent = &execlists->queue.rb_node; + while (*parent) { + rb = *parent; + p = rb_entry(rb, typeof(*p), node); + if (prio > p->priority) { + parent = &rb->rb_left; + } else if (prio < p->priority) { + parent = &rb->rb_right; + first = false; + } else { + return p; + } + } + + if (prio == I915_PRIORITY_NORMAL) { + p = &execlists->default_priolist; + } else { + p = kmem_cache_alloc(engine->i915->priorities, GFP_ATOMIC); + /* Convert an allocation failure to a priority bump */ + if (unlikely(!p)) { + prio = I915_PRIORITY_NORMAL; /* recurses just once */ + + /* To maintain ordering with all rendering, after an + * allocation failure we have to disable all scheduling. + * Requests will then be executed in fifo, and schedule + * will ensure that dependencies are emitted in fifo. + * There will be still some reordering with existing + * requests, so if userspace lied about their + * dependencies that reordering may be visible. + */ + execlists->no_priolist = true; + goto find_priolist; + } + } + + p->priority = prio; + INIT_LIST_HEAD(&p->requests); + rb_link_node(&p->node, rb, parent); + rb_insert_color(&p->node, &execlists->queue); + + if (first) + execlists->first = &p->node; + + return ptr_pack_bits(p, first, 1); +} + +static void unwind_wa_tail(struct drm_i915_gem_request *rq) { - return ctx->engine[engine->id].lrc_desc; + rq->tail = intel_ring_wrap(rq->ring, rq->wa_tail - WA_TAIL_BYTES); + assert_ring_tail_valid(rq->ring, rq->tail); +} + +static void unwind_incomplete_requests(struct intel_engine_cs *engine) +{ + struct drm_i915_gem_request *rq, *rn; + struct i915_priolist *uninitialized_var(p); + int last_prio = I915_PRIORITY_INVALID; + + lockdep_assert_held(&engine->timeline->lock); + + list_for_each_entry_safe_reverse(rq, rn, + &engine->timeline->requests, + link) { + if (i915_gem_request_completed(rq)) + return; + + __i915_gem_request_unsubmit(rq); + unwind_wa_tail(rq); + + GEM_BUG_ON(rq->priotree.priority == I915_PRIORITY_INVALID); + if (rq->priotree.priority != last_prio) { + p = lookup_priolist(engine, + &rq->priotree, + rq->priotree.priority); + p = ptr_mask_bits(p, 1); + + last_prio = rq->priotree.priority; + } + + list_add(&rq->priotree.link, &p->requests); + } } static inline void @@ -336,14 +429,20 @@ static u64 execlists_update_context(struct drm_i915_gem_request *rq) return ce->lrc_desc; } +static inline void elsp_write(u64 desc, u32 __iomem *elsp) +{ + writel(upper_32_bits(desc), elsp); + writel(lower_32_bits(desc), elsp); +} + static void execlists_submit_ports(struct intel_engine_cs *engine) { - struct execlist_port *port = engine->execlist_port; + struct execlist_port *port = engine->execlists.port; u32 __iomem *elsp = engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); unsigned int n; - for (n = ARRAY_SIZE(engine->execlist_port); n--; ) { + for (n = execlists_num_ports(&engine->execlists); n--; ) { struct drm_i915_gem_request *rq; unsigned int count; u64 desc; @@ -361,8 +460,7 @@ static void execlists_submit_ports(struct intel_engine_cs *engine) desc = 0; } - writel(upper_32_bits(desc), elsp); - writel(lower_32_bits(desc), elsp); + elsp_write(desc, elsp); } } @@ -395,25 +493,43 @@ static void port_assign(struct execlist_port *port, port_set(port, port_pack(i915_gem_request_get(rq), port_count(port))); } +static void inject_preempt_context(struct intel_engine_cs *engine) +{ + struct intel_context *ce = + &engine->i915->preempt_context->engine[engine->id]; + u32 __iomem *elsp = + engine->i915->regs + i915_mmio_reg_offset(RING_ELSP(engine)); + unsigned int n; + + GEM_BUG_ON(engine->i915->preempt_context->hw_id != PREEMPT_ID); + GEM_BUG_ON(!IS_ALIGNED(ce->ring->size, WA_TAIL_BYTES)); + + memset(ce->ring->vaddr + ce->ring->tail, 0, WA_TAIL_BYTES); + ce->ring->tail += WA_TAIL_BYTES; + ce->ring->tail &= (ce->ring->size - 1); + ce->lrc_reg_state[CTX_RING_TAIL+1] = ce->ring->tail; + + for (n = execlists_num_ports(&engine->execlists); --n; ) + elsp_write(0, elsp); + + elsp_write(ce->lrc_desc, elsp); +} + +static bool can_preempt(struct intel_engine_cs *engine) +{ + return INTEL_INFO(engine->i915)->has_logical_ring_preemption; +} + static void execlists_dequeue(struct intel_engine_cs *engine) { - struct drm_i915_gem_request *last; - struct execlist_port *port = engine->execlist_port; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port *port = execlists->port; + const struct execlist_port * const last_port = + &execlists->port[execlists->port_mask]; + struct drm_i915_gem_request *last = port_request(port); struct rb_node *rb; bool submit = false; - last = port_request(port); - if (last) - /* WaIdleLiteRestore:bdw,skl - * Apply the wa NOOPs to prevent ring:HEAD == req:TAIL - * as we resubmit the request. See gen8_emit_breadcrumb() - * for where we prepare the padding after the end of the - * request. - */ - last->tail = last->wa_tail; - - GEM_BUG_ON(port_isset(&port[1])); - /* Hardware submission is through 2 ports. Conceptually each port * has a (RING_START, RING_HEAD, RING_TAIL) tuple. RING_START is * static for a context, and unique to each, so we only execute @@ -436,9 +552,68 @@ static void execlists_dequeue(struct intel_engine_cs *engine) */ spin_lock_irq(&engine->timeline->lock); - rb = engine->execlist_first; - GEM_BUG_ON(rb_first(&engine->execlist_queue) != rb); - while (rb) { + rb = execlists->first; + GEM_BUG_ON(rb_first(&execlists->queue) != rb); + if (!rb) + goto unlock; + + if (last) { + /* + * Don't resubmit or switch until all outstanding + * preemptions (lite-restore) are seen. Then we + * know the next preemption status we see corresponds + * to this ELSP update. + */ + if (port_count(&port[0]) > 1) + goto unlock; + + if (can_preempt(engine) && + rb_entry(rb, struct i915_priolist, node)->priority > + max(last->priotree.priority, 0)) { + /* + * Switch to our empty preempt context so + * the state of the GPU is known (idle). + */ + inject_preempt_context(engine); + execlists_set_active(execlists, + EXECLISTS_ACTIVE_PREEMPT); + goto unlock; + } else { + /* + * In theory, we could coalesce more requests onto + * the second port (the first port is active, with + * no preemptions pending). However, that means we + * then have to deal with the possible lite-restore + * of the second port (as we submit the ELSP, there + * may be a context-switch) but also we may complete + * the resubmission before the context-switch. Ergo, + * coalescing onto the second port will cause a + * preemption event, but we cannot predict whether + * that will affect port[0] or port[1]. + * + * If the second port is already active, we can wait + * until the next context-switch before contemplating + * new requests. The GPU will be busy and we should be + * able to resubmit the new ELSP before it idles, + * avoiding pipeline bubbles (momentary pauses where + * the driver is unable to keep up the supply of new + * work). + */ + if (port_count(&port[1])) + goto unlock; + + /* WaIdleLiteRestore:bdw,skl + * Apply the wa NOOPs to prevent + * ring:HEAD == req:TAIL as we resubmit the + * request. See gen8_emit_breadcrumb() for + * where we prepare the padding after the + * end of the request. + */ + last->tail = last->wa_tail; + } + } + + do { struct i915_priolist *p = rb_entry(rb, typeof(*p), node); struct drm_i915_gem_request *rq, *rn; @@ -460,7 +635,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) * combine this request with the last, then we * are done. */ - if (port != engine->execlist_port) { + if (port == last_port) { __list_del_many(&p->requests, &rq->priotree.link); goto done; @@ -485,38 +660,108 @@ static void execlists_dequeue(struct intel_engine_cs *engine) if (submit) port_assign(port, last); port++; + + GEM_BUG_ON(port_isset(port)); } INIT_LIST_HEAD(&rq->priotree.link); - rq->priotree.priority = INT_MAX; - __i915_gem_request_submit(rq); - trace_i915_gem_request_in(rq, port_index(port, engine)); + trace_i915_gem_request_in(rq, port_index(port, execlists)); last = rq; submit = true; } rb = rb_next(rb); - rb_erase(&p->node, &engine->execlist_queue); + rb_erase(&p->node, &execlists->queue); INIT_LIST_HEAD(&p->requests); if (p->priority != I915_PRIORITY_NORMAL) kmem_cache_free(engine->i915->priorities, p); - } + } while (rb); done: - engine->execlist_first = rb; + execlists->first = rb; if (submit) port_assign(port, last); +unlock: spin_unlock_irq(&engine->timeline->lock); - if (submit) + if (submit) { + execlists_set_active(execlists, EXECLISTS_ACTIVE_USER); execlists_submit_ports(engine); + } } -static bool execlists_elsp_ready(const struct intel_engine_cs *engine) +static void +execlist_cancel_port_requests(struct intel_engine_execlists *execlists) { - const struct execlist_port *port = engine->execlist_port; + struct execlist_port *port = execlists->port; + unsigned int num_ports = execlists_num_ports(execlists); - return port_count(&port[0]) + port_count(&port[1]) < 2; + while (num_ports-- && port_isset(port)) { + struct drm_i915_gem_request *rq = port_request(port); + + GEM_BUG_ON(!execlists->active); + execlists_context_status_change(rq, INTEL_CONTEXT_SCHEDULE_PREEMPTED); + i915_gem_request_put(rq); + + memset(port, 0, sizeof(*port)); + port++; + } +} + +static void execlists_cancel_requests(struct intel_engine_cs *engine) +{ + struct intel_engine_execlists * const execlists = &engine->execlists; + struct drm_i915_gem_request *rq, *rn; + struct rb_node *rb; + unsigned long flags; + + spin_lock_irqsave(&engine->timeline->lock, flags); + + /* Cancel the requests on the HW and clear the ELSP tracker. */ + execlist_cancel_port_requests(execlists); + + /* Mark all executing requests as skipped. */ + list_for_each_entry(rq, &engine->timeline->requests, link) { + GEM_BUG_ON(!rq->global_seqno); + if (!i915_gem_request_completed(rq)) + dma_fence_set_error(&rq->fence, -EIO); + } + + /* Flush the queued requests to the timeline list (for retiring). */ + rb = execlists->first; + while (rb) { + struct i915_priolist *p = rb_entry(rb, typeof(*p), node); + + list_for_each_entry_safe(rq, rn, &p->requests, priotree.link) { + INIT_LIST_HEAD(&rq->priotree.link); + + dma_fence_set_error(&rq->fence, -EIO); + __i915_gem_request_submit(rq); + } + + rb = rb_next(rb); + rb_erase(&p->node, &execlists->queue); + INIT_LIST_HEAD(&p->requests); + if (p->priority != I915_PRIORITY_NORMAL) + kmem_cache_free(engine->i915->priorities, p); + } + + /* Remaining _unready_ requests will be nop'ed when submitted */ + + + execlists->queue = RB_ROOT; + execlists->first = NULL; + GEM_BUG_ON(port_isset(execlists->port)); + + /* + * The port is checked prior to scheduling a tasklet, but + * just in case we have suspended the tasklet to do the + * wedging make sure that when it wakes, it decides there + * is no work to do by clearing the irq_posted bit. + */ + clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); + + spin_unlock_irqrestore(&engine->timeline->lock, flags); } /* @@ -525,8 +770,9 @@ static bool execlists_elsp_ready(const struct intel_engine_cs *engine) */ static void intel_lrc_irq_handler(unsigned long data) { - struct intel_engine_cs *engine = (struct intel_engine_cs *)data; - struct execlist_port *port = engine->execlist_port; + struct intel_engine_cs * const engine = (struct intel_engine_cs *)data; + struct intel_engine_execlists * const execlists = &engine->execlists; + struct execlist_port * const port = execlists->port; struct drm_i915_private *dev_priv = engine->i915; /* We can skip acquiring intel_runtime_pm_get() here as it was taken @@ -538,19 +784,24 @@ static void intel_lrc_irq_handler(unsigned long data) */ GEM_BUG_ON(!dev_priv->gt.awake); - intel_uncore_forcewake_get(dev_priv, engine->fw_domains); + intel_uncore_forcewake_get(dev_priv, execlists->fw_domains); /* Prefer doing test_and_clear_bit() as a two stage operation to avoid * imposing the cost of a locked atomic transaction when submitting a * new request (outside of the context-switch interrupt). */ while (test_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted)) { - u32 __iomem *csb_mmio = - dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine)); - u32 __iomem *buf = - dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0)); + /* The HWSP contains a (cacheable) mirror of the CSB */ + const u32 *buf = + &engine->status_page.page_addr[I915_HWS_CSB_BUF0_INDEX]; unsigned int head, tail; + if (unlikely(execlists->csb_use_mmio)) { + buf = (u32 * __force) + (dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_BUF_LO(engine, 0))); + execlists->csb_head = -1; /* force mmio read of CSB ptrs */ + } + /* The write will be ordered by the uncached read (itself * a memory barrier), so we do not need another in the form * of a locked instruction. The race between the interrupt @@ -562,9 +813,20 @@ static void intel_lrc_irq_handler(unsigned long data) * is set and we do a new loop. */ __clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); - head = readl(csb_mmio); - tail = GEN8_CSB_WRITE_PTR(head); - head = GEN8_CSB_READ_PTR(head); + if (unlikely(execlists->csb_head == -1)) { /* following a reset */ + head = readl(dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine))); + tail = GEN8_CSB_WRITE_PTR(head); + head = GEN8_CSB_READ_PTR(head); + execlists->csb_head = head; + } else { + const int write_idx = + intel_hws_csb_write_index(dev_priv) - + I915_HWS_CSB_BUF0_INDEX; + + head = execlists->csb_head; + tail = READ_ONCE(buf[write_idx]); + } + while (head != tail) { struct drm_i915_gem_request *rq; unsigned int status; @@ -590,13 +852,35 @@ static void intel_lrc_irq_handler(unsigned long data) * status notifier. */ - status = readl(buf + 2 * head); + status = READ_ONCE(buf[2 * head]); /* maybe mmio! */ if (!(status & GEN8_CTX_STATUS_COMPLETED_MASK)) continue; + if (status & GEN8_CTX_STATUS_ACTIVE_IDLE && + buf[2*head + 1] == PREEMPT_ID) { + execlist_cancel_port_requests(execlists); + + spin_lock_irq(&engine->timeline->lock); + unwind_incomplete_requests(engine); + spin_unlock_irq(&engine->timeline->lock); + + GEM_BUG_ON(!execlists_is_active(execlists, + EXECLISTS_ACTIVE_PREEMPT)); + execlists_clear_active(execlists, + EXECLISTS_ACTIVE_PREEMPT); + continue; + } + + if (status & GEN8_CTX_STATUS_PREEMPTED && + execlists_is_active(execlists, + EXECLISTS_ACTIVE_PREEMPT)) + continue; + + GEM_BUG_ON(!execlists_is_active(execlists, + EXECLISTS_ACTIVE_USER)); + /* Check the context/desc id for this event matches */ - GEM_DEBUG_BUG_ON(readl(buf + 2 * head + 1) != - port->context_id); + GEM_DEBUG_BUG_ON(buf[2 * head + 1] != port->context_id); rq = port_unpack(port, &count); GEM_BUG_ON(count == 0); @@ -608,8 +892,7 @@ static void intel_lrc_irq_handler(unsigned long data) trace_i915_gem_request_out(rq); i915_gem_request_put(rq); - port[0] = port[1]; - memset(&port[1], 0, sizeof(port[1])); + execlists_port_complete(execlists, port); } else { port_set(port, port_pack(rq, count)); } @@ -617,80 +900,33 @@ static void intel_lrc_irq_handler(unsigned long data) /* After the final element, the hw should be idle */ GEM_BUG_ON(port_count(port) == 0 && !(status & GEN8_CTX_STATUS_ACTIVE_IDLE)); + if (port_count(port) == 0) + execlists_clear_active(execlists, + EXECLISTS_ACTIVE_USER); } - writel(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, head << 8), - csb_mmio); + if (head != execlists->csb_head) { + execlists->csb_head = head; + writel(_MASKED_FIELD(GEN8_CSB_READ_PTR_MASK, head << 8), + dev_priv->regs + i915_mmio_reg_offset(RING_CONTEXT_STATUS_PTR(engine))); + } } - if (execlists_elsp_ready(engine)) + if (!execlists_is_active(execlists, EXECLISTS_ACTIVE_PREEMPT)) execlists_dequeue(engine); - intel_uncore_forcewake_put(dev_priv, engine->fw_domains); + intel_uncore_forcewake_put(dev_priv, execlists->fw_domains); } -static bool -insert_request(struct intel_engine_cs *engine, - struct i915_priotree *pt, - int prio) +static void insert_request(struct intel_engine_cs *engine, + struct i915_priotree *pt, + int prio) { - struct i915_priolist *p; - struct rb_node **parent, *rb; - bool first = true; - - if (unlikely(engine->no_priolist)) - prio = I915_PRIORITY_NORMAL; - -find_priolist: - /* most positive priority is scheduled first, equal priorities fifo */ - rb = NULL; - parent = &engine->execlist_queue.rb_node; - while (*parent) { - rb = *parent; - p = rb_entry(rb, typeof(*p), node); - if (prio > p->priority) { - parent = &rb->rb_left; - } else if (prio < p->priority) { - parent = &rb->rb_right; - first = false; - } else { - list_add_tail(&pt->link, &p->requests); - return false; - } - } - - if (prio == I915_PRIORITY_NORMAL) { - p = &engine->default_priolist; - } else { - p = kmem_cache_alloc(engine->i915->priorities, GFP_ATOMIC); - /* Convert an allocation failure to a priority bump */ - if (unlikely(!p)) { - prio = I915_PRIORITY_NORMAL; /* recurses just once */ - - /* To maintain ordering with all rendering, after an - * allocation failure we have to disable all scheduling. - * Requests will then be executed in fifo, and schedule - * will ensure that dependencies are emitted in fifo. - * There will be still some reordering with existing - * requests, so if userspace lied about their - * dependencies that reordering may be visible. - */ - engine->no_priolist = true; - goto find_priolist; - } - } + struct i915_priolist *p = lookup_priolist(engine, pt, prio); - p->priority = prio; - rb_link_node(&p->node, rb, parent); - rb_insert_color(&p->node, &engine->execlist_queue); - - INIT_LIST_HEAD(&p->requests); - list_add_tail(&pt->link, &p->requests); - - if (first) - engine->execlist_first = &p->node; - - return first; + list_add_tail(&pt->link, &ptr_mask_bits(p, 1)->requests); + if (ptr_unmask_bits(p, 1)) + tasklet_hi_schedule(&engine->execlists.irq_tasklet); } static void execlists_submit_request(struct drm_i915_gem_request *request) @@ -701,24 +937,23 @@ static void execlists_submit_request(struct drm_i915_gem_request *request) /* Will be called from irq-context when using foreign fences. */ spin_lock_irqsave(&engine->timeline->lock, flags); - if (insert_request(engine, - &request->priotree, - request->priotree.priority)) { - if (execlists_elsp_ready(engine)) - tasklet_hi_schedule(&engine->irq_tasklet); - } + insert_request(engine, &request->priotree, request->priotree.priority); - GEM_BUG_ON(!engine->execlist_first); + GEM_BUG_ON(!engine->execlists.first); GEM_BUG_ON(list_empty(&request->priotree.link)); spin_unlock_irqrestore(&engine->timeline->lock, flags); } +static struct drm_i915_gem_request *pt_to_request(struct i915_priotree *pt) +{ + return container_of(pt, struct drm_i915_gem_request, priotree); +} + static struct intel_engine_cs * pt_lock_engine(struct i915_priotree *pt, struct intel_engine_cs *locked) { - struct intel_engine_cs *engine = - container_of(pt, struct drm_i915_gem_request, priotree)->engine; + struct intel_engine_cs *engine = pt_to_request(pt)->engine; GEM_BUG_ON(!locked); @@ -737,6 +972,8 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio) struct i915_dependency stack; LIST_HEAD(dfs); + GEM_BUG_ON(prio == I915_PRIORITY_INVALID); + if (prio <= READ_ONCE(request->priotree.priority)) return; @@ -772,6 +1009,9 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio) * engines. */ list_for_each_entry(p, &pt->signalers_list, signal_link) { + if (i915_gem_request_completed(pt_to_request(p->signaler))) + continue; + GEM_BUG_ON(p->signaler->priority < pt->priority); if (prio > READ_ONCE(p->signaler->priority)) list_move_tail(&p->dfs_link, &dfs); @@ -785,7 +1025,7 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio) * execlists_submit_request()), we can set our own priority and skip * acquiring the engine locks. */ - if (request->priotree.priority == INT_MIN) { + if (request->priotree.priority == I915_PRIORITY_INVALID) { GEM_BUG_ON(!list_empty(&request->priotree.link)); request->priotree.priority = prio; if (stack.dfs_link.next == stack.dfs_link.prev) @@ -815,8 +1055,6 @@ static void execlists_schedule(struct drm_i915_gem_request *request, int prio) } spin_unlock_irq(&engine->timeline->lock); - - /* XXX Do we need to preempt to make room for us and our deps? */ } static struct intel_ring * @@ -866,6 +1104,7 @@ execlists_context_pin(struct intel_engine_cs *engine, i915_ggtt_offset(ce->ring->vma); ce->state->obj->mm.dirty = true; + ce->state->obj->pin_global++; i915_gem_context_get(ctx); out: @@ -893,6 +1132,7 @@ static void execlists_context_unpin(struct intel_engine_cs *engine, intel_ring_unpin(ce->ring); + ce->state->obj->pin_global--; i915_gem_object_unpin_map(ce->state->obj); i915_vma_unpin(ce->state); @@ -914,27 +1154,14 @@ static int execlists_request_alloc(struct drm_i915_gem_request *request) */ request->reserved_space += EXECLISTS_REQUEST_SIZE; - if (i915.enable_guc_submission) { - /* - * Check that the GuC has space for the request before - * going any further, as the i915_add_request() call - * later on mustn't fail ... - */ - ret = i915_guc_wq_reserve(request); - if (ret) - goto err; - } - cs = intel_ring_begin(request, 0); - if (IS_ERR(cs)) { - ret = PTR_ERR(cs); - goto err_unreserve; - } + if (IS_ERR(cs)) + return PTR_ERR(cs); if (!ce->initialised) { ret = engine->init_context(request); if (ret) - goto err_unreserve; + return ret; ce->initialised = true; } @@ -948,12 +1175,6 @@ static int execlists_request_alloc(struct drm_i915_gem_request *request) request->reserved_space -= EXECLISTS_REQUEST_SIZE; return 0; - -err_unreserve: - if (i915.enable_guc_submission) - i915_guc_wq_unreserve(request); -err: - return ret; } /* @@ -1031,6 +1252,8 @@ static u32 *gen8_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) i915_ggtt_offset(engine->scratch) + 2 * CACHELINE_BYTES); + *batch++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; + /* Pad to end of cacheline */ while ((unsigned long)batch % CACHELINE_BYTES) *batch++ = MI_NOOP; @@ -1044,26 +1267,10 @@ static u32 *gen8_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) return batch; } -/* - * This batch is started immediately after indirect_ctx batch. Since we ensure - * that indirect_ctx ends on a cacheline this batch is aligned automatically. - * - * The number of DWORDS written are returned using this field. - * - * This batch is terminated with MI_BATCH_BUFFER_END and so we need not add padding - * to align it with cacheline as padding after MI_BATCH_BUFFER_END is redundant. - */ -static u32 *gen8_init_perctx_bb(struct intel_engine_cs *engine, u32 *batch) -{ - /* WaDisableCtxRestoreArbitration:bdw,chv */ - *batch++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; - *batch++ = MI_BATCH_BUFFER_END; - - return batch; -} - static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) { + *batch++ = MI_ARB_ON_OFF | MI_ARB_DISABLE; + /* WaFlushCoherentL3CacheLinesAtContextSwitch:skl,bxt,glk */ batch = gen8_emit_flush_coherentl3_wa(engine, batch); @@ -1109,6 +1316,8 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) *batch++ = 0; } + *batch++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; + /* Pad to end of cacheline */ while ((unsigned long)batch % CACHELINE_BYTES) *batch++ = MI_NOOP; @@ -1116,13 +1325,6 @@ static u32 *gen9_init_indirectctx_bb(struct intel_engine_cs *engine, u32 *batch) return batch; } -static u32 *gen9_init_perctx_bb(struct intel_engine_cs *engine, u32 *batch) -{ - *batch++ = MI_BATCH_BUFFER_END; - - return batch; -} - #define CTX_WA_BB_OBJ_SIZE (PAGE_SIZE) static int lrc_setup_wa_ctx(struct intel_engine_cs *engine) @@ -1179,11 +1381,11 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine) return 0; case 9: wa_bb_fn[0] = gen9_init_indirectctx_bb; - wa_bb_fn[1] = gen9_init_perctx_bb; + wa_bb_fn[1] = NULL; break; case 8: wa_bb_fn[0] = gen8_init_indirectctx_bb; - wa_bb_fn[1] = gen8_init_perctx_bb; + wa_bb_fn[1] = NULL; break; default: MISSING_CASE(INTEL_GEN(engine->i915)); @@ -1210,7 +1412,8 @@ static int intel_init_workaround_bb(struct intel_engine_cs *engine) ret = -EINVAL; break; } - batch_ptr = wa_bb_fn[i](engine, batch_ptr); + if (wa_bb_fn[i]) + batch_ptr = wa_bb_fn[i](engine, batch_ptr); wa_bb[i]->size = batch_ptr - (batch + wa_bb[i]->offset); } @@ -1234,9 +1437,7 @@ static u8 gtiir[] = { static int gen8_init_common_ring(struct intel_engine_cs *engine) { struct drm_i915_private *dev_priv = engine->i915; - struct execlist_port *port = engine->execlist_port; - unsigned int n; - bool submit; + struct intel_engine_execlists * const execlists = &engine->execlists; int ret; ret = intel_mocs_init_engine(engine); @@ -1269,24 +1470,12 @@ static int gen8_init_common_ring(struct intel_engine_cs *engine) I915_WRITE(GEN8_GT_IIR(gtiir[engine->id]), GT_CONTEXT_SWITCH_INTERRUPT << engine->irq_shift); clear_bit(ENGINE_IRQ_EXECLIST, &engine->irq_posted); + execlists->csb_head = -1; + execlists->active = 0; /* After a GPU reset, we may have requests to replay */ - submit = false; - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) { - if (!port_isset(&port[n])) - break; - - DRM_DEBUG_DRIVER("Restarting %s:%d from 0x%x\n", - engine->name, n, - port_request(&port[n])->global_seqno); - - /* Discard the current inflight count */ - port_set(&port[n], port_request(&port[n])); - submit = true; - } - - if (submit && !i915.enable_guc_submission) - execlists_submit_ports(engine); + if (!i915_modparams.enable_guc_submission && execlists->first) + tasklet_schedule(&execlists->irq_tasklet); return 0; } @@ -1327,9 +1516,11 @@ static int gen9_init_render_ring(struct intel_engine_cs *engine) static void reset_common_ring(struct intel_engine_cs *engine, struct drm_i915_gem_request *request) { - struct execlist_port *port = engine->execlist_port; + struct intel_engine_execlists * const execlists = &engine->execlists; struct intel_context *ce; - unsigned int n; + unsigned long flags; + + spin_lock_irqsave(&engine->timeline->lock, flags); /* * Catch up with any missed context-switch interrupts. @@ -1340,20 +1531,12 @@ static void reset_common_ring(struct intel_engine_cs *engine, * guessing the missed context-switch events by looking at what * requests were completed. */ - if (!request) { - for (n = 0; n < ARRAY_SIZE(engine->execlist_port); n++) - i915_gem_request_put(port_request(&port[n])); - memset(engine->execlist_port, 0, sizeof(engine->execlist_port)); - return; - } + execlist_cancel_port_requests(execlists); - if (request->ctx != port_request(port)->ctx) { - i915_gem_request_put(port_request(port)); - port[0] = port[1]; - memset(&port[1], 0, sizeof(port[1])); - } + /* Push back any incomplete requests for replay after the reset. */ + unwind_incomplete_requests(engine); - GEM_BUG_ON(request->ctx != port_request(port)->ctx); + spin_unlock_irqrestore(&engine->timeline->lock, flags); /* If the request was innocent, we leave the request in the ELSP * and will try to replay it on restarting. The context image may @@ -1365,7 +1548,7 @@ static void reset_common_ring(struct intel_engine_cs *engine, * and have to at least restore the RING register in the context * image back to the expected values to skip over the guilty request. */ - if (request->fence.error != -EIO) + if (!request || request->fence.error != -EIO) return; /* We want a simple context + ring to execute the breadcrumb update. @@ -1388,10 +1571,7 @@ static void reset_common_ring(struct intel_engine_cs *engine, intel_ring_update_space(request->ring); /* Reset WaIdleLiteRestore:bdw,skl as well */ - request->tail = - intel_ring_wrap(request->ring, - request->wa_tail - WA_TAIL_DWORDS*sizeof(u32)); - assert_ring_tail_valid(request->ring, request->tail); + unwind_wa_tail(request); } static int intel_logical_ring_emit_pdps(struct drm_i915_gem_request *req) @@ -1450,13 +1630,31 @@ static int gen8_emit_bb_start(struct drm_i915_gem_request *req, if (IS_ERR(cs)) return PTR_ERR(cs); + /* + * WaDisableCtxRestoreArbitration:bdw,chv + * + * We don't need to perform MI_ARB_ENABLE as often as we do (in + * particular all the gen that do not need the w/a at all!), if we + * took care to make sure that on every switch into this context + * (both ordinary and for preemption) that arbitrartion was enabled + * we would be fine. However, there doesn't seem to be a downside to + * being paranoid and making sure it is set before each batch and + * every context-switch. + * + * Note that if we fail to enable arbitration before the request + * is complete, then we do not see the context-switch interrupt and + * the engine hangs (with RING_HEAD == RING_TAIL). + * + * That satisfies both the GPGPU w/a and our heavy-handed paranoia. + */ + *cs++ = MI_ARB_ON_OFF | MI_ARB_ENABLE; + /* FIXME(BDW): Address space and security selectors. */ *cs++ = MI_BATCH_BUFFER_START_GEN8 | (flags & I915_DISPATCH_SECURE ? 0 : BIT(8)) | (flags & I915_DISPATCH_RS ? MI_BATCH_RESOURCE_STREAMER : 0); *cs++ = lower_32_bits(offset); *cs++ = upper_32_bits(offset); - *cs++ = MI_NOOP; intel_ring_advance(req, cs); return 0; @@ -1585,7 +1783,8 @@ static int gen8_emit_flush_render(struct drm_i915_gem_request *request, */ static void gen8_emit_wa_tail(struct drm_i915_gem_request *request, u32 *cs) { - *cs++ = MI_NOOP; + /* Ensure there's always at least one preemption point per-request. */ + *cs++ = MI_ARB_CHECK; *cs++ = MI_NOOP; request->wa_tail = intel_ring_offset(request, cs); } @@ -1606,7 +1805,6 @@ static void gen8_emit_breadcrumb(struct drm_i915_gem_request *request, u32 *cs) gen8_emit_wa_tail(request, cs); } - static const int gen8_emit_breadcrumb_sz = 6 + WA_TAIL_DWORDS; static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, @@ -1634,7 +1832,6 @@ static void gen8_emit_breadcrumb_render(struct drm_i915_gem_request *request, gen8_emit_wa_tail(request, cs); } - static const int gen8_emit_breadcrumb_render_sz = 8 + WA_TAIL_DWORDS; static int gen8_init_rcs_context(struct drm_i915_gem_request *req) @@ -1668,8 +1865,8 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) * Tasklet cannot be active at this point due intel_mark_active/idle * so this is just for documentation. */ - if (WARN_ON(test_bit(TASKLET_STATE_SCHED, &engine->irq_tasklet.state))) - tasklet_kill(&engine->irq_tasklet); + if (WARN_ON(test_bit(TASKLET_STATE_SCHED, &engine->execlists.irq_tasklet.state))) + tasklet_kill(&engine->execlists.irq_tasklet); dev_priv = engine->i915; @@ -1680,11 +1877,6 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) if (engine->cleanup) engine->cleanup(engine); - if (engine->status_page.vma) { - i915_gem_object_unpin_map(engine->status_page.vma->obj); - engine->status_page.vma = NULL; - } - intel_engine_cleanup_common(engine); lrc_destroy_wa_ctx(engine); @@ -1696,8 +1888,9 @@ void intel_logical_ring_cleanup(struct intel_engine_cs *engine) static void execlists_set_default_submission(struct intel_engine_cs *engine) { engine->submit_request = execlists_submit_request; + engine->cancel_requests = execlists_cancel_requests; engine->schedule = execlists_schedule; - engine->irq_tasklet.func = intel_lrc_irq_handler; + engine->execlists.irq_tasklet.func = intel_lrc_irq_handler; } static void @@ -1731,24 +1924,6 @@ logical_ring_default_irqs(struct intel_engine_cs *engine) engine->irq_keep_mask = GT_CONTEXT_SWITCH_INTERRUPT << shift; } -static int -lrc_setup_hws(struct intel_engine_cs *engine, struct i915_vma *vma) -{ - const int hws_offset = LRC_PPHWSP_PN * PAGE_SIZE; - void *hws; - - /* The HWSP is part of the default context object in LRC mode. */ - hws = i915_gem_object_pin_map(vma->obj, I915_MAP_WB); - if (IS_ERR(hws)) - return PTR_ERR(hws); - - engine->status_page.page_addr = hws + hws_offset; - engine->status_page.ggtt_offset = i915_ggtt_offset(vma) + hws_offset; - engine->status_page.vma = vma; - - return 0; -} - static void logical_ring_setup(struct intel_engine_cs *engine) { @@ -1772,32 +1947,23 @@ logical_ring_setup(struct intel_engine_cs *engine) RING_CONTEXT_STATUS_BUF_BASE(engine), FW_REG_READ); - engine->fw_domains = fw_domains; + engine->execlists.fw_domains = fw_domains; - tasklet_init(&engine->irq_tasklet, + tasklet_init(&engine->execlists.irq_tasklet, intel_lrc_irq_handler, (unsigned long)engine); logical_ring_default_vfuncs(engine); logical_ring_default_irqs(engine); } -static int -logical_ring_init(struct intel_engine_cs *engine) +static int logical_ring_init(struct intel_engine_cs *engine) { - struct i915_gem_context *dctx = engine->i915->kernel_context; int ret; ret = intel_engine_init_common(engine); if (ret) goto error; - /* And setup the hardware status page. */ - ret = lrc_setup_hws(engine, dctx->engine[engine->id].state); - if (ret) { - DRM_ERROR("Failed to set up hws %s: %d\n", engine->name, ret); - goto error; - } - return 0; error: @@ -1955,13 +2121,12 @@ static void execlists_init_reg_state(u32 *regs, CTX_REG(regs, CTX_SECOND_BB_HEAD_L, RING_SBBADDR(base), 0); CTX_REG(regs, CTX_SECOND_BB_STATE, RING_SBBSTATE(base), 0); if (rcs) { - CTX_REG(regs, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(base), 0); + struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx; + CTX_REG(regs, CTX_RCS_INDIRECT_CTX, RING_INDIRECT_CTX(base), 0); CTX_REG(regs, CTX_RCS_INDIRECT_CTX_OFFSET, RING_INDIRECT_CTX_OFFSET(base), 0); - - if (engine->wa_ctx.vma) { - struct i915_ctx_workarounds *wa_ctx = &engine->wa_ctx; + if (wa_ctx->indirect_ctx.size) { u32 ggtt_offset = i915_ggtt_offset(wa_ctx->vma); regs[CTX_RCS_INDIRECT_CTX + 1] = @@ -1970,6 +2135,11 @@ static void execlists_init_reg_state(u32 *regs, regs[CTX_RCS_INDIRECT_CTX_OFFSET + 1] = intel_lr_indirect_ctx_offset(engine) << 6; + } + + CTX_REG(regs, CTX_BB_PER_CTX_PTR, RING_BB_PER_CTX_PTR(base), 0); + if (wa_ctx->per_ctx.size) { + u32 ggtt_offset = i915_ggtt_offset(wa_ctx->vma); regs[CTX_BB_PER_CTX_PTR + 1] = (ggtt_offset + wa_ctx->per_ctx.offset) | 0x01; @@ -2054,8 +2224,11 @@ static int execlists_context_deferred_alloc(struct i915_gem_context *ctx, context_size = round_up(engine->context_size, I915_GTT_PAGE_SIZE); - /* One extra page as the sharing data between driver and GuC */ - context_size += PAGE_SIZE * LRC_PPHWSP_PN; + /* + * Before the actual start of the context image, we insert a few pages + * for our own use and for sharing with the GuC. + */ + context_size += LRC_HEADER_PAGES * PAGE_SIZE; ctx_obj = i915_gem_object_create(ctx->i915, context_size); if (IS_ERR(ctx_obj)) { diff --git a/drivers/gpu/drm/i915/intel_lrc.h b/drivers/gpu/drm/i915/intel_lrc.h index 57ef5833c427..689fde1a63a9 100644 --- a/drivers/gpu/drm/i915/intel_lrc.h +++ b/drivers/gpu/drm/i915/intel_lrc.h @@ -25,6 +25,7 @@ #define _INTEL_LRC_H_ #include "intel_ringbuffer.h" +#include "i915_gem_context.h" #define GEN8_LR_CONTEXT_ALIGN I915_GTT_MIN_ALIGNMENT @@ -60,6 +61,7 @@ enum { INTEL_CONTEXT_SCHEDULE_IN = 0, INTEL_CONTEXT_SCHEDULE_OUT, + INTEL_CONTEXT_SCHEDULE_PREEMPTED, }; /* Logical Rings */ @@ -69,17 +71,42 @@ int logical_xcs_ring_init(struct intel_engine_cs *engine); /* Logical Ring Contexts */ -/* One extra page is added before LRC for GuC as shared data */ +/* + * We allocate a header at the start of the context image for our own + * use, therefore the actual location of the logical state is offset + * from the start of the VMA. The layout is + * + * | [guc] | [hwsp] [logical state] | + * |<- our header ->|<- context image ->| + * + */ +/* The first page is used for sharing data with the GuC */ #define LRC_GUCSHR_PN (0) -#define LRC_PPHWSP_PN (LRC_GUCSHR_PN + 1) -#define LRC_STATE_PN (LRC_PPHWSP_PN + 1) +#define LRC_GUCSHR_SZ (1) +/* At the start of the context image is its per-process HWS page */ +#define LRC_PPHWSP_PN (LRC_GUCSHR_PN + LRC_GUCSHR_SZ) +#define LRC_PPHWSP_SZ (1) +/* Finally we have the logical state for the context */ +#define LRC_STATE_PN (LRC_PPHWSP_PN + LRC_PPHWSP_SZ) + +/* + * Currently we include the PPHWSP in __intel_engine_context_size() so + * the size of the header is synonymous with the start of the PPHWSP. + */ +#define LRC_HEADER_PAGES LRC_PPHWSP_PN struct drm_i915_private; struct i915_gem_context; void intel_lr_context_resume(struct drm_i915_private *dev_priv); -uint64_t intel_lr_context_descriptor(struct i915_gem_context *ctx, - struct intel_engine_cs *engine); + +static inline uint64_t +intel_lr_context_descriptor(struct i915_gem_context *ctx, + struct intel_engine_cs *engine) +{ + return ctx->engine[engine->id].lrc_desc; +} + /* Execlists */ int intel_sanitize_enable_execlists(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/intel_lspcon.c b/drivers/gpu/drm/i915/intel_lspcon.c index beb9baaf2f2e..dcbc786479f9 100644 --- a/drivers/gpu/drm/i915/intel_lspcon.c +++ b/drivers/gpu/drm/i915/intel_lspcon.c @@ -56,7 +56,7 @@ static enum drm_lspcon_mode lspcon_get_current_mode(struct intel_lspcon *lspcon) struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc; if (drm_lspcon_get_mode(adapter, ¤t_mode)) { - DRM_ERROR("Error reading LSPCON mode\n"); + DRM_DEBUG_KMS("Error reading LSPCON mode\n"); return DRM_LSPCON_MODE_INVALID; } return current_mode; @@ -68,16 +68,15 @@ static enum drm_lspcon_mode lspcon_wait_mode(struct intel_lspcon *lspcon, enum drm_lspcon_mode current_mode; current_mode = lspcon_get_current_mode(lspcon); - if (current_mode == mode || current_mode == DRM_LSPCON_MODE_INVALID) + if (current_mode == mode) goto out; DRM_DEBUG_KMS("Waiting for LSPCON mode %s to settle\n", lspcon_mode_name(mode)); - wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode || - current_mode == DRM_LSPCON_MODE_INVALID, 100); + wait_for((current_mode = lspcon_get_current_mode(lspcon)) == mode, 100); if (current_mode != mode) - DRM_DEBUG_KMS("LSPCON mode hasn't settled\n"); + DRM_ERROR("LSPCON mode hasn't settled\n"); out: DRM_DEBUG_KMS("Current LSPCON mode %s\n", @@ -133,6 +132,7 @@ static bool lspcon_wake_native_aux_ch(struct intel_lspcon *lspcon) static bool lspcon_probe(struct intel_lspcon *lspcon) { + int retry; enum drm_dp_dual_mode_type adaptor_type; struct i2c_adapter *adapter = &lspcon_to_intel_dp(lspcon)->aux.ddc; enum drm_lspcon_mode expected_mode; @@ -141,10 +141,18 @@ static bool lspcon_probe(struct intel_lspcon *lspcon) DRM_LSPCON_MODE_PCON : DRM_LSPCON_MODE_LS; /* Lets probe the adaptor and check its type */ - adaptor_type = drm_dp_dual_mode_detect(adapter); + for (retry = 0; retry < 6; retry++) { + if (retry) + usleep_range(500, 1000); + + adaptor_type = drm_dp_dual_mode_detect(adapter); + if (adaptor_type == DRM_DP_DUAL_MODE_LSPCON) + break; + } + if (adaptor_type != DRM_DP_DUAL_MODE_LSPCON) { DRM_DEBUG_KMS("No LSPCON detected, found %s\n", - drm_dp_get_dual_mode_type_name(adaptor_type)); + drm_dp_get_dual_mode_type_name(adaptor_type)); return false; } diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index a9813aea89d8..38572d65e46e 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -880,8 +880,8 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) struct drm_i915_private *dev_priv = to_i915(dev); /* use the module option value if specified */ - if (i915.lvds_channel_mode > 0) - return i915.lvds_channel_mode == 2; + if (i915_modparams.lvds_channel_mode > 0) + return i915_modparams.lvds_channel_mode == 2; /* single channel LVDS is limited to 112 MHz */ if (lvds_encoder->attached_connector->base.panel.fixed_mode->clock @@ -939,10 +939,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) struct drm_display_mode *fixed_mode = NULL; struct drm_display_mode *downclock_mode = NULL; struct edid *edid; - struct intel_crtc *crtc; i915_reg_t lvds_reg; u32 lvds; - int pipe; u8 pin; u32 allowed_scalers; @@ -1113,22 +1111,11 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) * on. If so, assume that whatever is currently programmed is the * correct mode. */ - - /* Ironlake: FIXME if still fail, not try pipe mode now */ - if (HAS_PCH_SPLIT(dev_priv)) - goto failed; - - pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; - crtc = intel_get_crtc_for_pipe(dev_priv, pipe); - - if (crtc && (lvds & LVDS_PORT_EN)) { - fixed_mode = intel_crtc_mode_get(dev, &crtc->base); - if (fixed_mode) { - DRM_DEBUG_KMS("using current (BIOS) mode: "); - drm_mode_debug_printmodeline(fixed_mode); - fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - goto out; - } + fixed_mode = intel_encoder_current_mode(intel_encoder); + if (fixed_mode) { + DRM_DEBUG_KMS("using current (BIOS) mode: "); + drm_mode_debug_printmodeline(fixed_mode); + fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; } /* If we still don't have a mode after all that, give up. */ diff --git a/drivers/gpu/drm/i915/intel_modes.c b/drivers/gpu/drm/i915/intel_modes.c index b39846613e3c..4e43f873c889 100644 --- a/drivers/gpu/drm/i915/intel_modes.c +++ b/drivers/gpu/drm/i915/intel_modes.c @@ -30,6 +30,21 @@ #include "intel_drv.h" #include "i915_drv.h" +static void intel_connector_update_eld_conn_type(struct drm_connector *connector) +{ + u8 conn_type; + + if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort || + connector->connector_type == DRM_MODE_CONNECTOR_eDP) { + conn_type = DRM_ELD_CONN_TYPE_DP; + } else { + conn_type = DRM_ELD_CONN_TYPE_HDMI; + } + + connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] &= ~DRM_ELD_CONN_TYPE_MASK; + connector->eld[DRM_ELD_SAD_COUNT_CONN_TYPE] |= conn_type; +} + /** * intel_connector_update_modes - update connector from edid * @connector: DRM connector device to use @@ -43,6 +58,8 @@ int intel_connector_update_modes(struct drm_connector *connector, drm_mode_connector_update_edid_property(connector, edid); ret = drm_add_edid_modes(connector, edid); + intel_connector_update_eld_conn_type(connector); + return ret; } diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c index 98154efcb2f4..1d946240e55f 100644 --- a/drivers/gpu/drm/i915/intel_opregion.c +++ b/drivers/gpu/drm/i915/intel_opregion.c @@ -921,7 +921,7 @@ static int intel_load_vbt_firmware(struct drm_i915_private *dev_priv) { struct intel_opregion *opregion = &dev_priv->opregion; const struct firmware *fw = NULL; - const char *name = i915.vbt_firmware; + const char *name = i915_modparams.vbt_firmware; int ret; if (!name || !*name) diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c index aace22e7ccac..1b397b41cb4f 100644 --- a/drivers/gpu/drm/i915/intel_overlay.c +++ b/drivers/gpu/drm/i915/intel_overlay.c @@ -1134,7 +1134,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, if (!params) return -ENOMEM; - drmmode_crtc = drm_crtc_find(dev, put_image_rec->crtc_id); + drmmode_crtc = drm_crtc_find(dev, file_priv, put_image_rec->crtc_id); if (!drmmode_crtc) { ret = -ENOENT; goto out_free; diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 3b1c5d783ee7..adc51e452e3e 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -379,13 +379,13 @@ enum drm_connector_status intel_panel_detect(struct drm_i915_private *dev_priv) { /* Assume that the BIOS does not lie through the OpRegion... */ - if (!i915.panel_ignore_lid && dev_priv->opregion.lid_state) { + if (!i915_modparams.panel_ignore_lid && dev_priv->opregion.lid_state) { return *dev_priv->opregion.lid_state & 0x1 ? connector_status_connected : connector_status_disconnected; } - switch (i915.panel_ignore_lid) { + switch (i915_modparams.panel_ignore_lid) { case -2: return connector_status_connected; case -1: @@ -465,10 +465,10 @@ static u32 intel_panel_compute_brightness(struct intel_connector *connector, WARN_ON(panel->backlight.max == 0); - if (i915.invert_brightness < 0) + if (i915_modparams.invert_brightness < 0) return val; - if (i915.invert_brightness > 0 || + if (i915_modparams.invert_brightness > 0 || dev_priv->quirks & QUIRK_INVERT_BRIGHTNESS) { return panel->backlight.max - val + panel->backlight.min; } diff --git a/drivers/gpu/drm/i915/intel_pipe_crc.c b/drivers/gpu/drm/i915/intel_pipe_crc.c index 96043a51c1bf..899839f2f7c6 100644 --- a/drivers/gpu/drm/i915/intel_pipe_crc.c +++ b/drivers/gpu/drm/i915/intel_pipe_crc.c @@ -206,11 +206,11 @@ static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) static int display_crc_ctl_show(struct seq_file *m, void *data) { struct drm_i915_private *dev_priv = m->private; - int i; + enum pipe pipe; - for (i = 0; i < I915_MAX_PIPES; i++) - seq_printf(m, "%c %s\n", pipe_name(i), - pipe_crc_source_name(dev_priv->pipe_crc[i].source)); + for_each_pipe(dev_priv, pipe) + seq_printf(m, "%c %s\n", pipe_name(pipe), + pipe_crc_source_name(dev_priv->pipe_crc[pipe].source)); return 0; } @@ -775,11 +775,12 @@ display_crc_ctl_parse_object(const char *buf, enum intel_pipe_crc_object *o) return -EINVAL; } -static int display_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe) +static int display_crc_ctl_parse_pipe(struct drm_i915_private *dev_priv, + const char *buf, enum pipe *pipe) { const char name = buf[0]; - if (name < 'A' || name >= pipe_name(I915_MAX_PIPES)) + if (name < 'A' || name >= pipe_name(INTEL_INFO(dev_priv)->num_pipes)) return -EINVAL; *pipe = name - 'A'; @@ -828,7 +829,7 @@ static int display_crc_ctl_parse(struct drm_i915_private *dev_priv, return -EINVAL; } - if (display_crc_ctl_parse_pipe(words[1], &pipe) < 0) { + if (display_crc_ctl_parse_pipe(dev_priv, words[1], &pipe) < 0) { DRM_DEBUG_DRIVER("unknown pipe %s\n", words[1]); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 0201816a4229..aa12a44e9a76 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -58,24 +58,23 @@ static void gen9_init_clock_gating(struct drm_i915_private *dev_priv) { + if (HAS_LLC(dev_priv)) { + /* + * WaCompressedResourceDisplayNewHashMode:skl,kbl + * Display WA#0390: skl,kbl + * + * Must match Sampler, Pixel Back End, and Media. See + * WaCompressedResourceSamplerPbeMediaNewHashMode. + */ + I915_WRITE(CHICKEN_PAR1_1, + I915_READ(CHICKEN_PAR1_1) | + SKL_DE_COMPRESSED_HASH_MODE); + } + /* See Bspec note for PSR2_CTL bit 31, Wa#828:skl,bxt,kbl,cfl */ I915_WRITE(CHICKEN_PAR1_1, I915_READ(CHICKEN_PAR1_1) | SKL_EDP_PSR_FIX_RDWRAP); - /* - * Display WA#0390: skl,bxt,kbl,glk - * - * Must match Sampler, Pixel Back End, and Media - * (0xE194 bit 8, 0x7014 bit 13, 0x4DDC bits 27 and 31). - * - * Including bits outside the page in the hash would - * require 2 (or 4?) MiB alignment of resources. Just - * assume the defaul hashing mode which only uses bits - * within the page. - */ - I915_WRITE(CHICKEN_PAR1_1, - I915_READ(CHICKEN_PAR1_1) & ~SKL_RC_HASH_OUTSIDE); - I915_WRITE(GEN8_CONFIG0, I915_READ(GEN8_CONFIG0) | GEN9_DEFAULT_FIXES); @@ -323,7 +322,7 @@ static void chv_set_memory_dvfs(struct drm_i915_private *dev_priv, bool enable) { u32 val; - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); val = vlv_punit_read(dev_priv, PUNIT_REG_DDR_SETUP2); if (enable) @@ -338,14 +337,14 @@ static void chv_set_memory_dvfs(struct drm_i915_private *dev_priv, bool enable) FORCE_DDR_FREQ_REQ_ACK) == 0, 3)) DRM_ERROR("timed out waiting for Punit DDR DVFS request\n"); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable) { u32 val; - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); if (enable) @@ -354,7 +353,7 @@ static void chv_set_memory_pm5(struct drm_i915_private *dev_priv, bool enable) val &= ~DSP_MAXFIFO_PM5_ENABLE; vlv_punit_write(dev_priv, PUNIT_REG_DSPFREQ, val); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } #define FW_WM(value, plane) \ @@ -2791,11 +2790,11 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv, /* read the first set of memory latencies[0:3] */ val = 0; /* data0 to be programmed to 0 for first set */ - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); ret = sandybridge_pcode_read(dev_priv, GEN9_PCODE_READ_MEM_LATENCY, &val); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); if (ret) { DRM_ERROR("SKL Mailbox read error = %d\n", ret); @@ -2812,11 +2811,11 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv, /* read the second set of memory latencies[4:7] */ val = 1; /* data0 to be programmed to 1 for second set */ - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); ret = sandybridge_pcode_read(dev_priv, GEN9_PCODE_READ_MEM_LATENCY, &val); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); if (ret) { DRM_ERROR("SKL Mailbox read error = %d\n", ret); return; @@ -3134,7 +3133,11 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev, struct intel_crtc_state *newstate) { struct intel_pipe_wm *a = &newstate->wm.ilk.intermediate; - struct intel_pipe_wm *b = &intel_crtc->wm.active.ilk; + struct intel_atomic_state *intel_state = + to_intel_atomic_state(newstate->base.state); + const struct intel_crtc_state *oldstate = + intel_atomic_get_old_crtc_state(intel_state, intel_crtc); + const struct intel_pipe_wm *b = &oldstate->wm.ilk.optimal; int level, max_level = ilk_wm_max_level(to_i915(dev)); /* @@ -3143,6 +3146,9 @@ static int ilk_compute_intermediate_wm(struct drm_device *dev, * and after the vblank. */ *a = newstate->wm.ilk.optimal; + if (!newstate->base.active || drm_atomic_crtc_needs_modeset(&newstate->base)) + return 0; + a->pipe_enabled |= b->pipe_enabled; a->sprites_enabled |= b->sprites_enabled; a->sprites_scaled |= b->sprites_scaled; @@ -3609,13 +3615,13 @@ intel_enable_sagv(struct drm_i915_private *dev_priv) return 0; DRM_DEBUG_KMS("Enabling the SAGV\n"); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); ret = sandybridge_pcode_write(dev_priv, GEN9_PCODE_SAGV_CONTROL, GEN9_SAGV_ENABLE); /* We don't need to wait for the SAGV when enabling */ - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); /* * Some skl systems, pre-release machines in particular, @@ -3646,14 +3652,14 @@ intel_disable_sagv(struct drm_i915_private *dev_priv) return 0; DRM_DEBUG_KMS("Disabling the SAGV\n"); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); /* bspec says to keep retrying for at least 1 ms */ ret = skl_pcode_request(dev_priv, GEN9_PCODE_SAGV_CONTROL, GEN9_SAGV_DISABLE, GEN9_SAGV_IS_DISABLED, GEN9_SAGV_IS_DISABLED, 1); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); /* * Some skl systems, pre-release machines in particular, @@ -4376,134 +4382,147 @@ skl_adjusted_plane_pixel_rate(const struct intel_crtc_state *cstate, downscale_amount); } -static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, - struct intel_crtc_state *cstate, - const struct intel_plane_state *intel_pstate, - uint16_t ddb_allocation, - int level, - uint16_t *out_blocks, /* out */ - uint8_t *out_lines, /* out */ - bool *enabled /* out */) +static int +skl_compute_plane_wm_params(const struct drm_i915_private *dev_priv, + struct intel_crtc_state *cstate, + const struct intel_plane_state *intel_pstate, + struct skl_wm_params *wp) { struct intel_plane *plane = to_intel_plane(intel_pstate->base.plane); const struct drm_plane_state *pstate = &intel_pstate->base; const struct drm_framebuffer *fb = pstate->fb; - uint32_t latency = dev_priv->wm.skl_latency[level]; - uint_fixed_16_16_t method1, method2; - uint_fixed_16_16_t plane_blocks_per_line; - uint_fixed_16_16_t selected_result; uint32_t interm_pbpl; - uint32_t plane_bytes_per_line; - uint32_t res_blocks, res_lines; - uint8_t cpp; - uint32_t width = 0; - uint32_t plane_pixel_rate; - uint_fixed_16_16_t y_tile_minimum; - uint32_t y_min_scanlines; struct intel_atomic_state *state = to_intel_atomic_state(cstate->base.state); bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state); - bool y_tiled, x_tiled; - if (latency == 0 || - !intel_wm_plane_visible(cstate, intel_pstate)) { - *enabled = false; + if (!intel_wm_plane_visible(cstate, intel_pstate)) return 0; - } - - y_tiled = fb->modifier == I915_FORMAT_MOD_Y_TILED || - fb->modifier == I915_FORMAT_MOD_Yf_TILED || - fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || - fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; - x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED; - /* Display WA #1141: kbl,cfl */ - if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv)) && - dev_priv->ipc_enabled) - latency += 4; - - if (apply_memory_bw_wa && x_tiled) - latency += 15; + wp->y_tiled = fb->modifier == I915_FORMAT_MOD_Y_TILED || + fb->modifier == I915_FORMAT_MOD_Yf_TILED || + fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || + fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; + wp->x_tiled = fb->modifier == I915_FORMAT_MOD_X_TILED; + wp->rc_surface = fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || + fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS; if (plane->id == PLANE_CURSOR) { - width = intel_pstate->base.crtc_w; + wp->width = intel_pstate->base.crtc_w; } else { /* * Src coordinates are already rotated by 270 degrees for * the 90/270 degree plane rotation cases (to match the * GTT mapping), hence no need to account for rotation here. */ - width = drm_rect_width(&intel_pstate->base.src) >> 16; + wp->width = drm_rect_width(&intel_pstate->base.src) >> 16; } - cpp = (fb->format->format == DRM_FORMAT_NV12) ? fb->format->cpp[1] : - fb->format->cpp[0]; - plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, intel_pstate); + wp->cpp = (fb->format->format == DRM_FORMAT_NV12) ? fb->format->cpp[1] : + fb->format->cpp[0]; + wp->plane_pixel_rate = skl_adjusted_plane_pixel_rate(cstate, + intel_pstate); if (drm_rotation_90_or_270(pstate->rotation)) { - switch (cpp) { + switch (wp->cpp) { case 1: - y_min_scanlines = 16; + wp->y_min_scanlines = 16; break; case 2: - y_min_scanlines = 8; + wp->y_min_scanlines = 8; break; case 4: - y_min_scanlines = 4; + wp->y_min_scanlines = 4; break; default: - MISSING_CASE(cpp); + MISSING_CASE(wp->cpp); return -EINVAL; } } else { - y_min_scanlines = 4; + wp->y_min_scanlines = 4; } if (apply_memory_bw_wa) - y_min_scanlines *= 2; + wp->y_min_scanlines *= 2; - plane_bytes_per_line = width * cpp; - if (y_tiled) { - interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line * - y_min_scanlines, 512); + wp->plane_bytes_per_line = wp->width * wp->cpp; + if (wp->y_tiled) { + interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line * + wp->y_min_scanlines, 512); if (INTEL_GEN(dev_priv) >= 10) interm_pbpl++; - plane_blocks_per_line = div_fixed16(interm_pbpl, - y_min_scanlines); - } else if (x_tiled && INTEL_GEN(dev_priv) == 9) { - interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line, 512); - plane_blocks_per_line = u32_to_fixed16(interm_pbpl); + wp->plane_blocks_per_line = div_fixed16(interm_pbpl, + wp->y_min_scanlines); + } else if (wp->x_tiled && IS_GEN9(dev_priv)) { + interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line, 512); + wp->plane_blocks_per_line = u32_to_fixed16(interm_pbpl); } else { - interm_pbpl = DIV_ROUND_UP(plane_bytes_per_line, 512) + 1; - plane_blocks_per_line = u32_to_fixed16(interm_pbpl); + interm_pbpl = DIV_ROUND_UP(wp->plane_bytes_per_line, 512) + 1; + wp->plane_blocks_per_line = u32_to_fixed16(interm_pbpl); } - method1 = skl_wm_method1(dev_priv, plane_pixel_rate, cpp, latency); - method2 = skl_wm_method2(plane_pixel_rate, + wp->y_tile_minimum = mul_u32_fixed16(wp->y_min_scanlines, + wp->plane_blocks_per_line); + wp->linetime_us = fixed16_to_u32_round_up( + intel_get_linetime_us(cstate)); + + return 0; +} + +static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, + struct intel_crtc_state *cstate, + const struct intel_plane_state *intel_pstate, + uint16_t ddb_allocation, + int level, + const struct skl_wm_params *wp, + uint16_t *out_blocks, /* out */ + uint8_t *out_lines, /* out */ + bool *enabled /* out */) +{ + const struct drm_plane_state *pstate = &intel_pstate->base; + uint32_t latency = dev_priv->wm.skl_latency[level]; + uint_fixed_16_16_t method1, method2; + uint_fixed_16_16_t selected_result; + uint32_t res_blocks, res_lines; + struct intel_atomic_state *state = + to_intel_atomic_state(cstate->base.state); + bool apply_memory_bw_wa = skl_needs_memory_bw_wa(state); + + if (latency == 0 || + !intel_wm_plane_visible(cstate, intel_pstate)) { + *enabled = false; + return 0; + } + + /* Display WA #1141: kbl,cfl */ + if ((IS_KABYLAKE(dev_priv) || IS_COFFEELAKE(dev_priv) || + IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_B0)) && + dev_priv->ipc_enabled) + latency += 4; + + if (apply_memory_bw_wa && wp->x_tiled) + latency += 15; + + method1 = skl_wm_method1(dev_priv, wp->plane_pixel_rate, + wp->cpp, latency); + method2 = skl_wm_method2(wp->plane_pixel_rate, cstate->base.adjusted_mode.crtc_htotal, latency, - plane_blocks_per_line); - - y_tile_minimum = mul_u32_fixed16(y_min_scanlines, - plane_blocks_per_line); + wp->plane_blocks_per_line); - if (y_tiled) { - selected_result = max_fixed16(method2, y_tile_minimum); + if (wp->y_tiled) { + selected_result = max_fixed16(method2, wp->y_tile_minimum); } else { - uint32_t linetime_us; - - linetime_us = fixed16_to_u32_round_up( - intel_get_linetime_us(cstate)); - if ((cpp * cstate->base.adjusted_mode.crtc_htotal / 512 < 1) && - (plane_bytes_per_line / 512 < 1)) + if ((wp->cpp * cstate->base.adjusted_mode.crtc_htotal / + 512 < 1) && (wp->plane_bytes_per_line / 512 < 1)) selected_result = method2; else if (ddb_allocation >= - fixed16_to_u32_round_up(plane_blocks_per_line)) + fixed16_to_u32_round_up(wp->plane_blocks_per_line)) selected_result = min_fixed16(method1, method2); - else if (latency >= linetime_us) + else if (latency >= wp->linetime_us) selected_result = min_fixed16(method1, method2); else selected_result = method1; @@ -4511,19 +4530,18 @@ static int skl_compute_plane_wm(const struct drm_i915_private *dev_priv, res_blocks = fixed16_to_u32_round_up(selected_result) + 1; res_lines = div_round_up_fixed16(selected_result, - plane_blocks_per_line); + wp->plane_blocks_per_line); /* Display WA #1125: skl,bxt,kbl,glk */ - if (level == 0 && - (fb->modifier == I915_FORMAT_MOD_Y_TILED_CCS || - fb->modifier == I915_FORMAT_MOD_Yf_TILED_CCS)) - res_blocks += fixed16_to_u32_round_up(y_tile_minimum); + if (level == 0 && wp->rc_surface) + res_blocks += fixed16_to_u32_round_up(wp->y_tile_minimum); /* Display WA #1126: skl,bxt,kbl,glk */ if (level >= 1 && level <= 7) { - if (y_tiled) { - res_blocks += fixed16_to_u32_round_up(y_tile_minimum); - res_lines += y_min_scanlines; + if (wp->y_tiled) { + res_blocks += fixed16_to_u32_round_up( + wp->y_tile_minimum); + res_lines += wp->y_min_scanlines; } else { res_blocks++; } @@ -4561,6 +4579,7 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, struct skl_ddb_allocation *ddb, struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate, + const struct skl_wm_params *wm_params, struct skl_plane_wm *wm) { struct intel_crtc *intel_crtc = to_intel_crtc(cstate->base.crtc); @@ -4584,6 +4603,7 @@ skl_compute_wm_levels(const struct drm_i915_private *dev_priv, intel_pstate, ddb_blocks, level, + wm_params, &result->plane_res_b, &result->plane_res_l, &result->plane_en); @@ -4609,20 +4629,65 @@ skl_compute_linetime_wm(struct intel_crtc_state *cstate) linetime_wm = fixed16_to_u32_round_up(mul_u32_fixed16(8, linetime_us)); - /* Display WA #1135: bxt. */ - if (IS_BROXTON(dev_priv) && dev_priv->ipc_enabled) - linetime_wm = DIV_ROUND_UP(linetime_wm, 2); + /* Display WA #1135: bxt:ALL GLK:ALL */ + if ((IS_BROXTON(dev_priv) || IS_GEMINILAKE(dev_priv)) && + dev_priv->ipc_enabled) + linetime_wm /= 2; return linetime_wm; } static void skl_compute_transition_wm(struct intel_crtc_state *cstate, + struct skl_wm_params *wp, + struct skl_wm_level *wm_l0, + uint16_t ddb_allocation, struct skl_wm_level *trans_wm /* out */) { + struct drm_device *dev = cstate->base.crtc->dev; + const struct drm_i915_private *dev_priv = to_i915(dev); + uint16_t trans_min, trans_y_tile_min; + const uint16_t trans_amount = 10; /* This is configurable amount */ + uint16_t trans_offset_b, res_blocks; + if (!cstate->base.active) + goto exit; + + /* Transition WM are not recommended by HW team for GEN9 */ + if (INTEL_GEN(dev_priv) <= 9) + goto exit; + + /* Transition WM don't make any sense if ipc is disabled */ + if (!dev_priv->ipc_enabled) + goto exit; + + if (INTEL_GEN(dev_priv) >= 10) + trans_min = 4; + + trans_offset_b = trans_min + trans_amount; + + if (wp->y_tiled) { + trans_y_tile_min = (uint16_t) mul_round_up_u32_fixed16(2, + wp->y_tile_minimum); + res_blocks = max(wm_l0->plane_res_b, trans_y_tile_min) + + trans_offset_b; + } else { + res_blocks = wm_l0->plane_res_b + trans_offset_b; + + /* WA BUG:1938466 add one block for non y-tile planes */ + if (IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_A0)) + res_blocks += 1; + + } + + res_blocks += 1; + + if (res_blocks < ddb_allocation) { + trans_wm->plane_res_b = res_blocks; + trans_wm->plane_en = true; return; + } - /* Until we know more, just disable transition WMs */ +exit: trans_wm->plane_en = false; } @@ -4648,14 +4713,25 @@ static int skl_build_pipe_wm(struct intel_crtc_state *cstate, const struct intel_plane_state *intel_pstate = to_intel_plane_state(pstate); enum plane_id plane_id = to_intel_plane(plane)->id; + struct skl_wm_params wm_params; + enum pipe pipe = to_intel_crtc(cstate->base.crtc)->pipe; + uint16_t ddb_blocks; wm = &pipe_wm->planes[plane_id]; + ddb_blocks = skl_ddb_entry_size(&ddb->plane[pipe][plane_id]); + memset(&wm_params, 0, sizeof(struct skl_wm_params)); + + ret = skl_compute_plane_wm_params(dev_priv, cstate, + intel_pstate, &wm_params); + if (ret) + return ret; ret = skl_compute_wm_levels(dev_priv, ddb, cstate, - intel_pstate, wm); + intel_pstate, &wm_params, wm); if (ret) return ret; - skl_compute_transition_wm(cstate, &wm->trans_wm); + skl_compute_transition_wm(cstate, &wm_params, &wm->wm[0], + ddb_blocks, &wm->trans_wm); } pipe_wm->linetime = skl_compute_linetime_wm(cstate); @@ -4751,16 +4827,18 @@ static inline bool skl_ddb_entries_overlap(const struct skl_ddb_entry *a, return a->start < b->end && b->start < a->end; } -bool skl_ddb_allocation_overlaps(const struct skl_ddb_entry **entries, +bool skl_ddb_allocation_overlaps(struct drm_i915_private *dev_priv, + const struct skl_ddb_entry **entries, const struct skl_ddb_entry *ddb, int ignore) { - int i; + enum pipe pipe; - for (i = 0; i < I915_MAX_PIPES; i++) - if (i != ignore && entries[i] && - skl_ddb_entries_overlap(ddb, entries[i])) + for_each_pipe(dev_priv, pipe) { + if (pipe != ignore && entries[pipe] && + skl_ddb_entries_overlap(ddb, entries[pipe])) return true; + } return false; } @@ -5550,7 +5628,7 @@ void vlv_wm_get_hw_state(struct drm_device *dev) wm->level = VLV_WM_LEVEL_PM2; if (IS_CHERRYVIEW(dev_priv)) { - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); val = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ); if (val & DSP_MAXFIFO_PM5_ENABLE) @@ -5580,7 +5658,7 @@ void vlv_wm_get_hw_state(struct drm_device *dev) wm->level = VLV_WM_LEVEL_DDR_DVFS; } - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } for_each_intel_crtc(dev, crtc) { @@ -5684,12 +5762,30 @@ void vlv_wm_sanitize(struct drm_i915_private *dev_priv) mutex_unlock(&dev_priv->wm.wm_mutex); } +/* + * FIXME should probably kill this and improve + * the real watermark readout/sanitation instead + */ +static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv) +{ + I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN); + I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN); + I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN); + + /* + * Don't touch WM1S_LP_EN here. + * Doing so could cause underruns. + */ +} + void ilk_wm_get_hw_state(struct drm_device *dev) { struct drm_i915_private *dev_priv = to_i915(dev); struct ilk_wm_values *hw = &dev_priv->wm.hw; struct drm_crtc *crtc; + ilk_init_lp_watermarks(dev_priv); + for_each_crtc(dev, crtc) ilk_pipe_wm_get_hw_state(crtc); @@ -5754,6 +5850,36 @@ void intel_update_watermarks(struct intel_crtc *crtc) dev_priv->display.update_wm(crtc); } +void intel_enable_ipc(struct drm_i915_private *dev_priv) +{ + u32 val; + + /* Display WA #0477 WaDisableIPC: skl */ + if (IS_SKYLAKE(dev_priv)) { + dev_priv->ipc_enabled = false; + return; + } + + val = I915_READ(DISP_ARB_CTL2); + + if (dev_priv->ipc_enabled) + val |= DISP_IPC_ENABLE; + else + val &= ~DISP_IPC_ENABLE; + + I915_WRITE(DISP_ARB_CTL2, val); +} + +void intel_init_ipc(struct drm_i915_private *dev_priv) +{ + dev_priv->ipc_enabled = false; + if (!HAS_IPC(dev_priv)) + return; + + dev_priv->ipc_enabled = true; + intel_enable_ipc(dev_priv); +} + /* * Lock protecting IPS related data structures */ @@ -5887,6 +6013,7 @@ static void ironlake_disable_drps(struct drm_i915_private *dev_priv) */ static u32 intel_rps_limits(struct drm_i915_private *dev_priv, u8 val) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 limits; /* Only set the down limit when we've reached the lowest level to avoid @@ -5896,13 +6023,13 @@ static u32 intel_rps_limits(struct drm_i915_private *dev_priv, u8 val) * frequency, if the down threshold expires in that window we will not * receive a down interrupt. */ if (INTEL_GEN(dev_priv) >= 9) { - limits = (dev_priv->rps.max_freq_softlimit) << 23; - if (val <= dev_priv->rps.min_freq_softlimit) - limits |= (dev_priv->rps.min_freq_softlimit) << 14; + limits = (rps->max_freq_softlimit) << 23; + if (val <= rps->min_freq_softlimit) + limits |= (rps->min_freq_softlimit) << 14; } else { - limits = dev_priv->rps.max_freq_softlimit << 24; - if (val <= dev_priv->rps.min_freq_softlimit) - limits |= dev_priv->rps.min_freq_softlimit << 16; + limits = rps->max_freq_softlimit << 24; + if (val <= rps->min_freq_softlimit) + limits |= rps->min_freq_softlimit << 16; } return limits; @@ -5910,39 +6037,40 @@ static u32 intel_rps_limits(struct drm_i915_private *dev_priv, u8 val) static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; int new_power; u32 threshold_up = 0, threshold_down = 0; /* in % */ u32 ei_up = 0, ei_down = 0; - new_power = dev_priv->rps.power; - switch (dev_priv->rps.power) { + new_power = rps->power; + switch (rps->power) { case LOW_POWER: - if (val > dev_priv->rps.efficient_freq + 1 && - val > dev_priv->rps.cur_freq) + if (val > rps->efficient_freq + 1 && + val > rps->cur_freq) new_power = BETWEEN; break; case BETWEEN: - if (val <= dev_priv->rps.efficient_freq && - val < dev_priv->rps.cur_freq) + if (val <= rps->efficient_freq && + val < rps->cur_freq) new_power = LOW_POWER; - else if (val >= dev_priv->rps.rp0_freq && - val > dev_priv->rps.cur_freq) + else if (val >= rps->rp0_freq && + val > rps->cur_freq) new_power = HIGH_POWER; break; case HIGH_POWER: - if (val < (dev_priv->rps.rp1_freq + dev_priv->rps.rp0_freq) >> 1 && - val < dev_priv->rps.cur_freq) + if (val < (rps->rp1_freq + rps->rp0_freq) >> 1 && + val < rps->cur_freq) new_power = BETWEEN; break; } /* Max/min bins are special */ - if (val <= dev_priv->rps.min_freq_softlimit) + if (val <= rps->min_freq_softlimit) new_power = LOW_POWER; - if (val >= dev_priv->rps.max_freq_softlimit) + if (val >= rps->max_freq_softlimit) new_power = HIGH_POWER; - if (new_power == dev_priv->rps.power) + if (new_power == rps->power) return; /* Note the units here are not exactly 1us, but 1280ns. */ @@ -6005,20 +6133,21 @@ static void gen6_set_rps_thresholds(struct drm_i915_private *dev_priv, u8 val) GEN6_RP_DOWN_IDLE_AVG); skip_hw_write: - dev_priv->rps.power = new_power; - dev_priv->rps.up_threshold = threshold_up; - dev_priv->rps.down_threshold = threshold_down; - dev_priv->rps.last_adj = 0; + rps->power = new_power; + rps->up_threshold = threshold_up; + rps->down_threshold = threshold_down; + rps->last_adj = 0; } static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 mask = 0; /* We use UP_EI_EXPIRED interupts for both up/down in manual mode */ - if (val > dev_priv->rps.min_freq_softlimit) + if (val > rps->min_freq_softlimit) mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_DOWN_THRESHOLD | GEN6_PM_RP_DOWN_TIMEOUT; - if (val < dev_priv->rps.max_freq_softlimit) + if (val < rps->max_freq_softlimit) mask |= GEN6_PM_RP_UP_EI_EXPIRED | GEN6_PM_RP_UP_THRESHOLD; mask &= dev_priv->pm_rps_events; @@ -6031,10 +6160,12 @@ static u32 gen6_rps_pm_mask(struct drm_i915_private *dev_priv, u8 val) * update the GEN6_RP_INTERRUPT_LIMITS register accordingly. */ static int gen6_set_rps(struct drm_i915_private *dev_priv, u8 val) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + /* min/max delay may still have been modified so be sure to * write the limits value. */ - if (val != dev_priv->rps.cur_freq) { + if (val != rps->cur_freq) { gen6_set_rps_thresholds(dev_priv, val); if (INTEL_GEN(dev_priv) >= 9) @@ -6056,7 +6187,7 @@ static int gen6_set_rps(struct drm_i915_private *dev_priv, u8 val) I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, intel_rps_limits(dev_priv, val)); I915_WRITE(GEN6_PMINTRMSK, gen6_rps_pm_mask(dev_priv, val)); - dev_priv->rps.cur_freq = val; + rps->cur_freq = val; trace_intel_gpu_freq_change(intel_gpu_freq(dev_priv, val)); return 0; @@ -6072,7 +6203,7 @@ static int valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val) I915_WRITE(GEN6_PMINTRMSK, gen6_rps_pm_mask(dev_priv, val)); - if (val != dev_priv->rps.cur_freq) { + if (val != dev_priv->gt_pm.rps.cur_freq) { err = vlv_punit_write(dev_priv, PUNIT_REG_GPU_FREQ_REQ, val); if (err) return err; @@ -6080,7 +6211,7 @@ static int valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val) gen6_set_rps_thresholds(dev_priv, val); } - dev_priv->rps.cur_freq = val; + dev_priv->gt_pm.rps.cur_freq = val; trace_intel_gpu_freq_change(intel_gpu_freq(dev_priv, val)); return 0; @@ -6095,10 +6226,11 @@ static int valleyview_set_rps(struct drm_i915_private *dev_priv, u8 val) */ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) { - u32 val = dev_priv->rps.idle_freq; + struct intel_rps *rps = &dev_priv->gt_pm.rps; + u32 val = rps->idle_freq; int err; - if (dev_priv->rps.cur_freq <= val) + if (rps->cur_freq <= val) return; /* The punit delays the write of the frequency and voltage until it @@ -6123,34 +6255,38 @@ static void vlv_set_rps_idle(struct drm_i915_private *dev_priv) void gen6_rps_busy(struct drm_i915_private *dev_priv) { - mutex_lock(&dev_priv->rps.hw_lock); - if (dev_priv->rps.enabled) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + + mutex_lock(&dev_priv->pcu_lock); + if (rps->enabled) { u8 freq; if (dev_priv->pm_rps_events & GEN6_PM_RP_UP_EI_EXPIRED) gen6_rps_reset_ei(dev_priv); I915_WRITE(GEN6_PMINTRMSK, - gen6_rps_pm_mask(dev_priv, dev_priv->rps.cur_freq)); + gen6_rps_pm_mask(dev_priv, rps->cur_freq)); gen6_enable_rps_interrupts(dev_priv); /* Use the user's desired frequency as a guide, but for better * performance, jump directly to RPe as our starting frequency. */ - freq = max(dev_priv->rps.cur_freq, - dev_priv->rps.efficient_freq); + freq = max(rps->cur_freq, + rps->efficient_freq); if (intel_set_rps(dev_priv, clamp(freq, - dev_priv->rps.min_freq_softlimit, - dev_priv->rps.max_freq_softlimit))) + rps->min_freq_softlimit, + rps->max_freq_softlimit))) DRM_DEBUG_DRIVER("Failed to set idle frequency\n"); } - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } void gen6_rps_idle(struct drm_i915_private *dev_priv) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + /* Flush our bottom-half so that it does not race with us * setting the idle frequency and so that it is bounded by * our rpm wakeref. And then disable the interrupts to stop any @@ -6158,36 +6294,36 @@ void gen6_rps_idle(struct drm_i915_private *dev_priv) */ gen6_disable_rps_interrupts(dev_priv); - mutex_lock(&dev_priv->rps.hw_lock); - if (dev_priv->rps.enabled) { + mutex_lock(&dev_priv->pcu_lock); + if (rps->enabled) { if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) vlv_set_rps_idle(dev_priv); else - gen6_set_rps(dev_priv, dev_priv->rps.idle_freq); - dev_priv->rps.last_adj = 0; + gen6_set_rps(dev_priv, rps->idle_freq); + rps->last_adj = 0; I915_WRITE(GEN6_PMINTRMSK, gen6_sanitize_rps_pm_mask(dev_priv, ~0)); } - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } void gen6_rps_boost(struct drm_i915_gem_request *rq, - struct intel_rps_client *rps) + struct intel_rps_client *rps_client) { - struct drm_i915_private *i915 = rq->i915; + struct intel_rps *rps = &rq->i915->gt_pm.rps; unsigned long flags; bool boost; /* This is intentionally racy! We peek at the state here, then * validate inside the RPS worker. */ - if (!i915->rps.enabled) + if (!rps->enabled) return; boost = false; spin_lock_irqsave(&rq->lock, flags); if (!rq->waitboost && !i915_gem_request_completed(rq)) { - atomic_inc(&i915->rps.num_waiters); + atomic_inc(&rps->num_waiters); rq->waitboost = true; boost = true; } @@ -6195,22 +6331,23 @@ void gen6_rps_boost(struct drm_i915_gem_request *rq, if (!boost) return; - if (READ_ONCE(i915->rps.cur_freq) < i915->rps.boost_freq) - schedule_work(&i915->rps.work); + if (READ_ONCE(rps->cur_freq) < rps->boost_freq) + schedule_work(&rps->work); - atomic_inc(rps ? &rps->boosts : &i915->rps.boosts); + atomic_inc(rps_client ? &rps_client->boosts : &rps->boosts); } int intel_set_rps(struct drm_i915_private *dev_priv, u8 val) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; int err; - lockdep_assert_held(&dev_priv->rps.hw_lock); - GEM_BUG_ON(val > dev_priv->rps.max_freq); - GEM_BUG_ON(val < dev_priv->rps.min_freq); + lockdep_assert_held(&dev_priv->pcu_lock); + GEM_BUG_ON(val > rps->max_freq); + GEM_BUG_ON(val < rps->min_freq); - if (!dev_priv->rps.enabled) { - dev_priv->rps.cur_freq = val; + if (!rps->enabled) { + rps->cur_freq = val; return 0; } @@ -6233,21 +6370,30 @@ static void gen9_disable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RP_CONTROL, 0); } -static void gen6_disable_rps(struct drm_i915_private *dev_priv) +static void gen6_disable_rc6(struct drm_i915_private *dev_priv) { I915_WRITE(GEN6_RC_CONTROL, 0); +} + +static void gen6_disable_rps(struct drm_i915_private *dev_priv) +{ I915_WRITE(GEN6_RPNSWREQ, 1 << 31); I915_WRITE(GEN6_RP_CONTROL, 0); } -static void cherryview_disable_rps(struct drm_i915_private *dev_priv) +static void cherryview_disable_rc6(struct drm_i915_private *dev_priv) { I915_WRITE(GEN6_RC_CONTROL, 0); } -static void valleyview_disable_rps(struct drm_i915_private *dev_priv) +static void cherryview_disable_rps(struct drm_i915_private *dev_priv) +{ + I915_WRITE(GEN6_RP_CONTROL, 0); +} + +static void valleyview_disable_rc6(struct drm_i915_private *dev_priv) { - /* we're doing forcewake before Disabling RC6, + /* We're doing forcewake before Disabling RC6, * This what the BIOS expects when going into suspend */ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); @@ -6256,6 +6402,11 @@ static void valleyview_disable_rps(struct drm_i915_private *dev_priv) intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } +static void valleyview_disable_rps(struct drm_i915_private *dev_priv) +{ + I915_WRITE(GEN6_RP_CONTROL, 0); +} + static void intel_print_rc6_info(struct drm_i915_private *dev_priv, u32 mode) { if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { @@ -6378,24 +6529,26 @@ int sanitize_rc6_option(struct drm_i915_private *dev_priv, int enable_rc6) static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + /* All of these values are in units of 50MHz */ /* static values from HW: RP0 > RP1 > RPn (min_freq) */ if (IS_GEN9_LP(dev_priv)) { u32 rp_state_cap = I915_READ(BXT_RP_STATE_CAP); - dev_priv->rps.rp0_freq = (rp_state_cap >> 16) & 0xff; - dev_priv->rps.rp1_freq = (rp_state_cap >> 8) & 0xff; - dev_priv->rps.min_freq = (rp_state_cap >> 0) & 0xff; + rps->rp0_freq = (rp_state_cap >> 16) & 0xff; + rps->rp1_freq = (rp_state_cap >> 8) & 0xff; + rps->min_freq = (rp_state_cap >> 0) & 0xff; } else { u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); - dev_priv->rps.rp0_freq = (rp_state_cap >> 0) & 0xff; - dev_priv->rps.rp1_freq = (rp_state_cap >> 8) & 0xff; - dev_priv->rps.min_freq = (rp_state_cap >> 16) & 0xff; + rps->rp0_freq = (rp_state_cap >> 0) & 0xff; + rps->rp1_freq = (rp_state_cap >> 8) & 0xff; + rps->min_freq = (rp_state_cap >> 16) & 0xff; } /* hw_max = RP0 until we check for overclocking */ - dev_priv->rps.max_freq = dev_priv->rps.rp0_freq; + rps->max_freq = rps->rp0_freq; - dev_priv->rps.efficient_freq = dev_priv->rps.rp1_freq; + rps->efficient_freq = rps->rp1_freq; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv) || IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { u32 ddcc_status = 0; @@ -6403,33 +6556,34 @@ static void gen6_init_rps_frequencies(struct drm_i915_private *dev_priv) if (sandybridge_pcode_read(dev_priv, HSW_PCODE_DYNAMIC_DUTY_CYCLE_CONTROL, &ddcc_status) == 0) - dev_priv->rps.efficient_freq = + rps->efficient_freq = clamp_t(u8, ((ddcc_status >> 8) & 0xff), - dev_priv->rps.min_freq, - dev_priv->rps.max_freq); + rps->min_freq, + rps->max_freq); } if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { /* Store the frequency values in 16.66 MHZ units, which is * the natural hardware unit for SKL */ - dev_priv->rps.rp0_freq *= GEN9_FREQ_SCALER; - dev_priv->rps.rp1_freq *= GEN9_FREQ_SCALER; - dev_priv->rps.min_freq *= GEN9_FREQ_SCALER; - dev_priv->rps.max_freq *= GEN9_FREQ_SCALER; - dev_priv->rps.efficient_freq *= GEN9_FREQ_SCALER; + rps->rp0_freq *= GEN9_FREQ_SCALER; + rps->rp1_freq *= GEN9_FREQ_SCALER; + rps->min_freq *= GEN9_FREQ_SCALER; + rps->max_freq *= GEN9_FREQ_SCALER; + rps->efficient_freq *= GEN9_FREQ_SCALER; } } static void reset_rps(struct drm_i915_private *dev_priv, int (*set)(struct drm_i915_private *, u8)) { - u8 freq = dev_priv->rps.cur_freq; + struct intel_rps *rps = &dev_priv->gt_pm.rps; + u8 freq = rps->cur_freq; /* force a reset */ - dev_priv->rps.power = -1; - dev_priv->rps.cur_freq = -1; + rps->power = -1; + rps->cur_freq = -1; if (set(dev_priv, freq)) DRM_ERROR("Failed to reset RPS to initial values\n"); @@ -6442,7 +6596,7 @@ static void gen9_enable_rps(struct drm_i915_private *dev_priv) /* Program defaults and thresholds for RPS*/ I915_WRITE(GEN6_RC_VIDEO_FREQ, - GEN9_FREQUENCY(dev_priv->rps.rp1_freq)); + GEN9_FREQUENCY(dev_priv->gt_pm.rps.rp1_freq)); /* 1 second timeout*/ I915_WRITE(GEN6_RP_DOWN_TIMEOUT, @@ -6462,7 +6616,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; - uint32_t rc6_mask = 0; + u32 rc6_mode, rc6_mask = 0; /* 1a: Software RC state - RC0 */ I915_WRITE(GEN6_RC_STATE, 0); @@ -6496,12 +6650,19 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) I915_WRITE(GEN9_RENDER_PG_IDLE_HYSTERESIS, 25); /* 3a: Enable RC6 */ - if (intel_enable_rc6() & INTEL_RC6_ENABLE) + if (intel_rc6_enabled() & INTEL_RC6_ENABLE) rc6_mask = GEN6_RC_CTL_RC6_ENABLE; DRM_INFO("RC6 %s\n", onoff(rc6_mask & GEN6_RC_CTL_RC6_ENABLE)); I915_WRITE(GEN6_RC6_THRESHOLD, 37500); /* 37.5/125ms per EI */ + + /* WaRsUseTimeoutMode:cnl (pre-prod) */ + if (IS_CNL_REVID(dev_priv, CNL_REVID_A0, CNL_REVID_C0)) + rc6_mode = GEN7_RC_CTL_TO_MODE; + else + rc6_mode = GEN6_RC_CTL_EI_MODE(1); + I915_WRITE(GEN6_RC_CONTROL, - GEN6_RC_CTL_HW_ENABLE | GEN6_RC_CTL_EI_MODE(1) | rc6_mask); + GEN6_RC_CTL_HW_ENABLE | rc6_mode | rc6_mask); /* * 3b: Enable Coarse Power Gating only when RC6 is enabled. @@ -6516,7 +6677,7 @@ static void gen9_enable_rc6(struct drm_i915_private *dev_priv) intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } -static void gen8_enable_rps(struct drm_i915_private *dev_priv) +static void gen8_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -6525,7 +6686,7 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv) /* 1a: Software RC state - RC0 */ I915_WRITE(GEN6_RC_STATE, 0); - /* 1c & 1d: Get forcewake during program sequence. Although the driver + /* 1b: Get forcewake during program sequence. Although the driver * hasn't enabled a state yet where we need forcewake, BIOS may have.*/ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); @@ -6539,36 +6700,38 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv) for_each_engine(engine, dev_priv, id) I915_WRITE(RING_MAX_IDLE(engine->mmio_base), 10); I915_WRITE(GEN6_RC_SLEEP, 0); - if (IS_BROADWELL(dev_priv)) - I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */ - else - I915_WRITE(GEN6_RC6_THRESHOLD, 50000); /* 50/125ms per EI */ + I915_WRITE(GEN6_RC6_THRESHOLD, 625); /* 800us/1.28 for TO */ /* 3: Enable RC6 */ - if (intel_enable_rc6() & INTEL_RC6_ENABLE) + if (intel_rc6_enabled() & INTEL_RC6_ENABLE) rc6_mask = GEN6_RC_CTL_RC6_ENABLE; intel_print_rc6_info(dev_priv, rc6_mask); - if (IS_BROADWELL(dev_priv)) - I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | - GEN7_RC_CTL_TO_MODE | - rc6_mask); - else - I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | - GEN6_RC_CTL_EI_MODE(1) | - rc6_mask); - /* 4 Program defaults and thresholds for RPS*/ + I915_WRITE(GEN6_RC_CONTROL, GEN6_RC_CTL_HW_ENABLE | + GEN7_RC_CTL_TO_MODE | + rc6_mask); + + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); +} + +static void gen8_enable_rps(struct drm_i915_private *dev_priv) +{ + struct intel_rps *rps = &dev_priv->gt_pm.rps; + + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + + /* 1 Program defaults and thresholds for RPS*/ I915_WRITE(GEN6_RPNSWREQ, - HSW_FREQUENCY(dev_priv->rps.rp1_freq)); + HSW_FREQUENCY(rps->rp1_freq)); I915_WRITE(GEN6_RC_VIDEO_FREQ, - HSW_FREQUENCY(dev_priv->rps.rp1_freq)); + HSW_FREQUENCY(rps->rp1_freq)); /* NB: Docs say 1s, and 1000000 - which aren't equivalent */ I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 100000000 / 128); /* 1 second timeout */ /* Docs recommend 900MHz, and 300 MHz respectively */ I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, - dev_priv->rps.max_freq_softlimit << 24 | - dev_priv->rps.min_freq_softlimit << 16); + rps->max_freq_softlimit << 24 | + rps->min_freq_softlimit << 16); I915_WRITE(GEN6_RP_UP_THRESHOLD, 7600000 / 128); /* 76ms busyness per EI, 90% */ I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 31300000 / 128); /* 313ms busyness per EI, 70%*/ @@ -6577,7 +6740,7 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - /* 5: Enable RPS */ + /* 2: Enable RPS */ I915_WRITE(GEN6_RP_CONTROL, GEN6_RP_MEDIA_TURBO | GEN6_RP_MEDIA_HW_NORMAL_MODE | @@ -6586,14 +6749,12 @@ static void gen8_enable_rps(struct drm_i915_private *dev_priv) GEN6_RP_UP_BUSY_AVG | GEN6_RP_DOWN_IDLE_AVG); - /* 6: Ring frequency + overclocking (our driver does this later */ - reset_rps(dev_priv, gen6_set_rps); intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } -static void gen6_enable_rps(struct drm_i915_private *dev_priv) +static void gen6_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -6602,14 +6763,6 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) int rc6_mode; int ret; - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); - - /* Here begins a magic sequence of register writes to enable - * auto-downclocking. - * - * Perhaps there might be some value in exposing these to - * userspace... - */ I915_WRITE(GEN6_RC_STATE, 0); /* Clear the DBG now so we don't confuse earlier errors */ @@ -6643,7 +6796,7 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ /* Check if we are enabling RC6 */ - rc6_mode = intel_enable_rc6(); + rc6_mode = intel_rc6_enabled(); if (rc6_mode & INTEL_RC6_ENABLE) rc6_mask |= GEN6_RC_CTL_RC6_ENABLE; @@ -6663,12 +6816,6 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) GEN6_RC_CTL_EI_MODE(1) | GEN6_RC_CTL_HW_ENABLE); - /* Power down if completely idle for over 50ms */ - I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000); - I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - - reset_rps(dev_priv, gen6_set_rps); - rc6vids = 0; ret = sandybridge_pcode_read(dev_priv, GEN6_PCODE_READ_RC6VIDS, &rc6vids); if (IS_GEN6(dev_priv) && ret) { @@ -6686,8 +6833,28 @@ static void gen6_enable_rps(struct drm_i915_private *dev_priv) intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } +static void gen6_enable_rps(struct drm_i915_private *dev_priv) +{ + /* Here begins a magic sequence of register writes to enable + * auto-downclocking. + * + * Perhaps there might be some value in exposing these to + * userspace... + */ + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + + /* Power down if completely idle for over 50ms */ + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 50000); + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + + reset_rps(dev_priv, gen6_set_rps); + + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); +} + static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; int min_freq = 15; unsigned int gpu_freq; unsigned int max_ia_freq, min_ring_freq; @@ -6695,7 +6862,7 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) int scaling_factor = 180; struct cpufreq_policy *policy; - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); policy = cpufreq_cpu_get(0); if (policy) { @@ -6718,11 +6885,11 @@ static void gen6_update_ring_freq(struct drm_i915_private *dev_priv) if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) { /* Convert GT frequency to 50 HZ units */ - min_gpu_freq = dev_priv->rps.min_freq / GEN9_FREQ_SCALER; - max_gpu_freq = dev_priv->rps.max_freq / GEN9_FREQ_SCALER; + min_gpu_freq = rps->min_freq / GEN9_FREQ_SCALER; + max_gpu_freq = rps->max_freq / GEN9_FREQ_SCALER; } else { - min_gpu_freq = dev_priv->rps.min_freq; - max_gpu_freq = dev_priv->rps.max_freq; + min_gpu_freq = rps->min_freq; + max_gpu_freq = rps->max_freq; } /* @@ -6973,17 +7140,18 @@ static void valleyview_cleanup_pctx(struct drm_i915_private *dev_priv) static void vlv_init_gpll_ref_freq(struct drm_i915_private *dev_priv) { - dev_priv->rps.gpll_ref_freq = + dev_priv->gt_pm.rps.gpll_ref_freq = vlv_get_cck_clock(dev_priv, "GPLL ref", CCK_GPLL_CLOCK_CONTROL, dev_priv->czclk_freq); DRM_DEBUG_DRIVER("GPLL reference freq: %d kHz\n", - dev_priv->rps.gpll_ref_freq); + dev_priv->gt_pm.rps.gpll_ref_freq); } static void valleyview_init_gt_powersave(struct drm_i915_private *dev_priv) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 val; valleyview_setup_pctx(dev_priv); @@ -7005,30 +7173,31 @@ static void valleyview_init_gt_powersave(struct drm_i915_private *dev_priv) } DRM_DEBUG_DRIVER("DDR speed: %d MHz\n", dev_priv->mem_freq); - dev_priv->rps.max_freq = valleyview_rps_max_freq(dev_priv); - dev_priv->rps.rp0_freq = dev_priv->rps.max_freq; + rps->max_freq = valleyview_rps_max_freq(dev_priv); + rps->rp0_freq = rps->max_freq; DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", - intel_gpu_freq(dev_priv, dev_priv->rps.max_freq), - dev_priv->rps.max_freq); + intel_gpu_freq(dev_priv, rps->max_freq), + rps->max_freq); - dev_priv->rps.efficient_freq = valleyview_rps_rpe_freq(dev_priv); + rps->efficient_freq = valleyview_rps_rpe_freq(dev_priv); DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n", - intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq), - dev_priv->rps.efficient_freq); + intel_gpu_freq(dev_priv, rps->efficient_freq), + rps->efficient_freq); - dev_priv->rps.rp1_freq = valleyview_rps_guar_freq(dev_priv); + rps->rp1_freq = valleyview_rps_guar_freq(dev_priv); DRM_DEBUG_DRIVER("RP1(Guar Freq) GPU freq: %d MHz (%u)\n", - intel_gpu_freq(dev_priv, dev_priv->rps.rp1_freq), - dev_priv->rps.rp1_freq); + intel_gpu_freq(dev_priv, rps->rp1_freq), + rps->rp1_freq); - dev_priv->rps.min_freq = valleyview_rps_min_freq(dev_priv); + rps->min_freq = valleyview_rps_min_freq(dev_priv); DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", - intel_gpu_freq(dev_priv, dev_priv->rps.min_freq), - dev_priv->rps.min_freq); + intel_gpu_freq(dev_priv, rps->min_freq), + rps->min_freq); } static void cherryview_init_gt_powersave(struct drm_i915_private *dev_priv) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; u32 val; cherryview_setup_pctx(dev_priv); @@ -7049,31 +7218,29 @@ static void cherryview_init_gt_powersave(struct drm_i915_private *dev_priv) } DRM_DEBUG_DRIVER("DDR speed: %d MHz\n", dev_priv->mem_freq); - dev_priv->rps.max_freq = cherryview_rps_max_freq(dev_priv); - dev_priv->rps.rp0_freq = dev_priv->rps.max_freq; + rps->max_freq = cherryview_rps_max_freq(dev_priv); + rps->rp0_freq = rps->max_freq; DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", - intel_gpu_freq(dev_priv, dev_priv->rps.max_freq), - dev_priv->rps.max_freq); + intel_gpu_freq(dev_priv, rps->max_freq), + rps->max_freq); - dev_priv->rps.efficient_freq = cherryview_rps_rpe_freq(dev_priv); + rps->efficient_freq = cherryview_rps_rpe_freq(dev_priv); DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n", - intel_gpu_freq(dev_priv, dev_priv->rps.efficient_freq), - dev_priv->rps.efficient_freq); + intel_gpu_freq(dev_priv, rps->efficient_freq), + rps->efficient_freq); - dev_priv->rps.rp1_freq = cherryview_rps_guar_freq(dev_priv); + rps->rp1_freq = cherryview_rps_guar_freq(dev_priv); DRM_DEBUG_DRIVER("RP1(Guar) GPU freq: %d MHz (%u)\n", - intel_gpu_freq(dev_priv, dev_priv->rps.rp1_freq), - dev_priv->rps.rp1_freq); + intel_gpu_freq(dev_priv, rps->rp1_freq), + rps->rp1_freq); - dev_priv->rps.min_freq = cherryview_rps_min_freq(dev_priv); + rps->min_freq = cherryview_rps_min_freq(dev_priv); DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", - intel_gpu_freq(dev_priv, dev_priv->rps.min_freq), - dev_priv->rps.min_freq); + intel_gpu_freq(dev_priv, rps->min_freq), + rps->min_freq); - WARN_ONCE((dev_priv->rps.max_freq | - dev_priv->rps.efficient_freq | - dev_priv->rps.rp1_freq | - dev_priv->rps.min_freq) & 1, + WARN_ONCE((rps->max_freq | rps->efficient_freq | rps->rp1_freq | + rps->min_freq) & 1, "Odd GPU freq values\n"); } @@ -7082,13 +7249,11 @@ static void valleyview_cleanup_gt_powersave(struct drm_i915_private *dev_priv) valleyview_cleanup_pctx(dev_priv); } -static void cherryview_enable_rps(struct drm_i915_private *dev_priv) +static void cherryview_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; - u32 gtfifodbg, val, rc6_mode = 0, pcbr; - - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + u32 gtfifodbg, rc6_mode = 0, pcbr; gtfifodbg = I915_READ(GTFIFODBG) & ~(GT_FIFO_SBDEDICATE_FREE_ENTRY_CHV | GT_FIFO_FREE_ENTRIES_CHV); @@ -7119,7 +7284,7 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv) /* TO threshold set to 500 us ( 0x186 * 1.28 us) */ I915_WRITE(GEN6_RC6_THRESHOLD, 0x186); - /* allows RC6 residency counter to work */ + /* Allows RC6 residency counter to work */ I915_WRITE(VLV_COUNTER_CONTROL, _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH | VLV_MEDIA_RC6_COUNT_EN | @@ -7129,13 +7294,22 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv) pcbr = I915_READ(VLV_PCBR); /* 3: Enable RC6 */ - if ((intel_enable_rc6() & INTEL_RC6_ENABLE) && + if ((intel_rc6_enabled() & INTEL_RC6_ENABLE) && (pcbr >> VLV_PCBR_ADDR_SHIFT)) rc6_mode = GEN7_RC_CTL_TO_MODE; I915_WRITE(GEN6_RC_CONTROL, rc6_mode); - /* 4 Program defaults and thresholds for RPS*/ + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); +} + +static void cherryview_enable_rps(struct drm_i915_private *dev_priv) +{ + u32 val; + + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + + /* 1: Program defaults and thresholds for RPS*/ I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); @@ -7144,7 +7318,7 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - /* 5: Enable RPS */ + /* 2: Enable RPS */ I915_WRITE(GEN6_RP_CONTROL, GEN6_RP_MEDIA_HW_NORMAL_MODE | GEN6_RP_MEDIA_IS_GFX | @@ -7171,13 +7345,11 @@ static void cherryview_enable_rps(struct drm_i915_private *dev_priv) intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); } -static void valleyview_enable_rps(struct drm_i915_private *dev_priv) +static void valleyview_enable_rc6(struct drm_i915_private *dev_priv) { struct intel_engine_cs *engine; enum intel_engine_id id; - u32 gtfifodbg, val, rc6_mode = 0; - - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + u32 gtfifodbg, rc6_mode = 0; valleyview_check_pctx(dev_priv); @@ -7188,28 +7360,11 @@ static void valleyview_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GTFIFODBG, gtfifodbg); } - /* If VLV, Forcewake all wells, else re-direct to regular path */ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); /* Disable RC states. */ I915_WRITE(GEN6_RC_CONTROL, 0); - I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); - I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); - I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); - I915_WRITE(GEN6_RP_UP_EI, 66000); - I915_WRITE(GEN6_RP_DOWN_EI, 350000); - - I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); - - I915_WRITE(GEN6_RP_CONTROL, - GEN6_RP_MEDIA_TURBO | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_CONT); - I915_WRITE(GEN6_RC6_WAKE_RATE_LIMIT, 0x00280000); I915_WRITE(GEN6_RC_EVALUATION_INTERVAL, 125000); I915_WRITE(GEN6_RC_IDLE_HYSTERSIS, 25); @@ -7219,7 +7374,7 @@ static void valleyview_enable_rps(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_RC6_THRESHOLD, 0x557); - /* allows RC6 residency counter to work */ + /* Allows RC6 residency counter to work */ I915_WRITE(VLV_COUNTER_CONTROL, _MASKED_BIT_ENABLE(VLV_COUNT_RANGE_HIGH | VLV_MEDIA_RC0_COUNT_EN | @@ -7227,13 +7382,38 @@ static void valleyview_enable_rps(struct drm_i915_private *dev_priv) VLV_MEDIA_RC6_COUNT_EN | VLV_RENDER_RC6_COUNT_EN)); - if (intel_enable_rc6() & INTEL_RC6_ENABLE) + if (intel_rc6_enabled() & INTEL_RC6_ENABLE) rc6_mode = GEN7_RC_CTL_TO_MODE | VLV_RC_CTL_CTX_RST_PARALLEL; intel_print_rc6_info(dev_priv, rc6_mode); I915_WRITE(GEN6_RC_CONTROL, rc6_mode); + intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); +} + +static void valleyview_enable_rps(struct drm_i915_private *dev_priv) +{ + u32 val; + + intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); + + I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); + I915_WRITE(GEN6_RP_UP_THRESHOLD, 59400); + I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 245000); + I915_WRITE(GEN6_RP_UP_EI, 66000); + I915_WRITE(GEN6_RP_DOWN_EI, 350000); + + I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10); + + I915_WRITE(GEN6_RP_CONTROL, + GEN6_RP_MEDIA_TURBO | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_CONT); + /* Setting Fixed Bias */ val = VLV_OVERRIDE_EN | VLV_SOC_TDP_EN | @@ -7441,7 +7621,7 @@ static unsigned long __i915_gfx_val(struct drm_i915_private *dev_priv) lockdep_assert_held(&mchdev_lock); - pxvid = I915_READ(PXVFREQ(dev_priv->rps.cur_freq)); + pxvid = I915_READ(PXVFREQ(dev_priv->gt_pm.rps.cur_freq)); pxvid = (pxvid >> 24) & 0x7f; ext_v = pvid_to_extvid(dev_priv, pxvid); @@ -7728,17 +7908,19 @@ static void intel_init_emon(struct drm_i915_private *dev_priv) void intel_init_gt_powersave(struct drm_i915_private *dev_priv) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + /* * RPM depends on RC6 to save restore the GT HW context, so make RC6 a * requirement. */ - if (!i915.enable_rc6) { + if (!i915_modparams.enable_rc6) { DRM_INFO("RC6 disabled, disabling runtime PM support\n"); intel_runtime_pm_get(dev_priv); } mutex_lock(&dev_priv->drm.struct_mutex); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); /* Initialize RPS limits (for userspace) */ if (IS_CHERRYVIEW(dev_priv)) @@ -7749,16 +7931,16 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv) gen6_init_rps_frequencies(dev_priv); /* Derive initial user preferences/limits from the hardware limits */ - dev_priv->rps.idle_freq = dev_priv->rps.min_freq; - dev_priv->rps.cur_freq = dev_priv->rps.idle_freq; + rps->idle_freq = rps->min_freq; + rps->cur_freq = rps->idle_freq; - dev_priv->rps.max_freq_softlimit = dev_priv->rps.max_freq; - dev_priv->rps.min_freq_softlimit = dev_priv->rps.min_freq; + rps->max_freq_softlimit = rps->max_freq; + rps->min_freq_softlimit = rps->min_freq; if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) - dev_priv->rps.min_freq_softlimit = + rps->min_freq_softlimit = max_t(int, - dev_priv->rps.efficient_freq, + rps->efficient_freq, intel_freq_opcode(dev_priv, 450)); /* After setting max-softlimit, find the overclock max freq */ @@ -7769,16 +7951,16 @@ void intel_init_gt_powersave(struct drm_i915_private *dev_priv) sandybridge_pcode_read(dev_priv, GEN6_READ_OC_PARAMS, ¶ms); if (params & BIT(31)) { /* OC supported */ DRM_DEBUG_DRIVER("Overclocking supported, max: %dMHz, overclock: %dMHz\n", - (dev_priv->rps.max_freq & 0xff) * 50, + (rps->max_freq & 0xff) * 50, (params & 0xff) * 50); - dev_priv->rps.max_freq = params & 0xff; + rps->max_freq = params & 0xff; } } /* Finally allow us to boost to max by default */ - dev_priv->rps.boost_freq = dev_priv->rps.max_freq; + rps->boost_freq = rps->max_freq; - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); mutex_unlock(&dev_priv->drm.struct_mutex); intel_autoenable_gt_powersave(dev_priv); @@ -7789,7 +7971,7 @@ void intel_cleanup_gt_powersave(struct drm_i915_private *dev_priv) if (IS_VALLEYVIEW(dev_priv)) valleyview_cleanup_gt_powersave(dev_priv); - if (!i915.enable_rc6) + if (!i915_modparams.enable_rc6) intel_runtime_pm_put(dev_priv); } @@ -7806,7 +7988,7 @@ void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv) if (INTEL_GEN(dev_priv) < 6) return; - if (cancel_delayed_work_sync(&dev_priv->rps.autoenable_work)) + if (cancel_delayed_work_sync(&dev_priv->gt_pm.autoenable_work)) intel_runtime_pm_put(dev_priv); /* gen6_rps_idle() will be called later to disable interrupts */ @@ -7814,90 +7996,168 @@ void intel_suspend_gt_powersave(struct drm_i915_private *dev_priv) void intel_sanitize_gt_powersave(struct drm_i915_private *dev_priv) { - dev_priv->rps.enabled = true; /* force disabling */ + dev_priv->gt_pm.rps.enabled = true; /* force RPS disabling */ + dev_priv->gt_pm.rc6.enabled = true; /* force RC6 disabling */ intel_disable_gt_powersave(dev_priv); gen6_reset_rps_interrupts(dev_priv); } -void intel_disable_gt_powersave(struct drm_i915_private *dev_priv) +static inline void intel_disable_llc_pstate(struct drm_i915_private *i915) { - if (!READ_ONCE(dev_priv->rps.enabled)) + lockdep_assert_held(&i915->pcu_lock); + + if (!i915->gt_pm.llc_pstate.enabled) return; - mutex_lock(&dev_priv->rps.hw_lock); + /* Currently there is no HW configuration to be done to disable. */ - if (INTEL_GEN(dev_priv) >= 9) { + i915->gt_pm.llc_pstate.enabled = false; +} + +static void intel_disable_rc6(struct drm_i915_private *dev_priv) +{ + lockdep_assert_held(&dev_priv->pcu_lock); + + if (!dev_priv->gt_pm.rc6.enabled) + return; + + if (INTEL_GEN(dev_priv) >= 9) gen9_disable_rc6(dev_priv); + else if (IS_CHERRYVIEW(dev_priv)) + cherryview_disable_rc6(dev_priv); + else if (IS_VALLEYVIEW(dev_priv)) + valleyview_disable_rc6(dev_priv); + else if (INTEL_GEN(dev_priv) >= 6) + gen6_disable_rc6(dev_priv); + + dev_priv->gt_pm.rc6.enabled = false; +} + +static void intel_disable_rps(struct drm_i915_private *dev_priv) +{ + lockdep_assert_held(&dev_priv->pcu_lock); + + if (!dev_priv->gt_pm.rps.enabled) + return; + + if (INTEL_GEN(dev_priv) >= 9) gen9_disable_rps(dev_priv); - } else if (IS_CHERRYVIEW(dev_priv)) { + else if (IS_CHERRYVIEW(dev_priv)) cherryview_disable_rps(dev_priv); - } else if (IS_VALLEYVIEW(dev_priv)) { + else if (IS_VALLEYVIEW(dev_priv)) valleyview_disable_rps(dev_priv); - } else if (INTEL_GEN(dev_priv) >= 6) { + else if (INTEL_GEN(dev_priv) >= 6) gen6_disable_rps(dev_priv); - } else if (IS_IRONLAKE_M(dev_priv)) { + else if (IS_IRONLAKE_M(dev_priv)) ironlake_disable_drps(dev_priv); - } - dev_priv->rps.enabled = false; - mutex_unlock(&dev_priv->rps.hw_lock); + dev_priv->gt_pm.rps.enabled = false; } -void intel_enable_gt_powersave(struct drm_i915_private *dev_priv) +void intel_disable_gt_powersave(struct drm_i915_private *dev_priv) { - /* We shouldn't be disabling as we submit, so this should be less - * racy than it appears! - */ - if (READ_ONCE(dev_priv->rps.enabled)) + mutex_lock(&dev_priv->pcu_lock); + + intel_disable_rc6(dev_priv); + intel_disable_rps(dev_priv); + if (HAS_LLC(dev_priv)) + intel_disable_llc_pstate(dev_priv); + + mutex_unlock(&dev_priv->pcu_lock); +} + +static inline void intel_enable_llc_pstate(struct drm_i915_private *i915) +{ + lockdep_assert_held(&i915->pcu_lock); + + if (i915->gt_pm.llc_pstate.enabled) return; - /* Powersaving is controlled by the host when inside a VM */ - if (intel_vgpu_active(dev_priv)) + gen6_update_ring_freq(i915); + + i915->gt_pm.llc_pstate.enabled = true; +} + +static void intel_enable_rc6(struct drm_i915_private *dev_priv) +{ + lockdep_assert_held(&dev_priv->pcu_lock); + + if (dev_priv->gt_pm.rc6.enabled) return; - mutex_lock(&dev_priv->rps.hw_lock); + if (IS_CHERRYVIEW(dev_priv)) + cherryview_enable_rc6(dev_priv); + else if (IS_VALLEYVIEW(dev_priv)) + valleyview_enable_rc6(dev_priv); + else if (INTEL_GEN(dev_priv) >= 9) + gen9_enable_rc6(dev_priv); + else if (IS_BROADWELL(dev_priv)) + gen8_enable_rc6(dev_priv); + else if (INTEL_GEN(dev_priv) >= 6) + gen6_enable_rc6(dev_priv); + + dev_priv->gt_pm.rc6.enabled = true; +} + +static void intel_enable_rps(struct drm_i915_private *dev_priv) +{ + struct intel_rps *rps = &dev_priv->gt_pm.rps; + + lockdep_assert_held(&dev_priv->pcu_lock); + + if (rps->enabled) + return; if (IS_CHERRYVIEW(dev_priv)) { cherryview_enable_rps(dev_priv); } else if (IS_VALLEYVIEW(dev_priv)) { valleyview_enable_rps(dev_priv); } else if (INTEL_GEN(dev_priv) >= 9) { - gen9_enable_rc6(dev_priv); gen9_enable_rps(dev_priv); - if (IS_GEN9_BC(dev_priv) || IS_CANNONLAKE(dev_priv)) - gen6_update_ring_freq(dev_priv); } else if (IS_BROADWELL(dev_priv)) { gen8_enable_rps(dev_priv); - gen6_update_ring_freq(dev_priv); } else if (INTEL_GEN(dev_priv) >= 6) { gen6_enable_rps(dev_priv); - gen6_update_ring_freq(dev_priv); } else if (IS_IRONLAKE_M(dev_priv)) { ironlake_enable_drps(dev_priv); intel_init_emon(dev_priv); } - WARN_ON(dev_priv->rps.max_freq < dev_priv->rps.min_freq); - WARN_ON(dev_priv->rps.idle_freq > dev_priv->rps.max_freq); + WARN_ON(rps->max_freq < rps->min_freq); + WARN_ON(rps->idle_freq > rps->max_freq); + + WARN_ON(rps->efficient_freq < rps->min_freq); + WARN_ON(rps->efficient_freq > rps->max_freq); + + rps->enabled = true; +} + +void intel_enable_gt_powersave(struct drm_i915_private *dev_priv) +{ + /* Powersaving is controlled by the host when inside a VM */ + if (intel_vgpu_active(dev_priv)) + return; + + mutex_lock(&dev_priv->pcu_lock); - WARN_ON(dev_priv->rps.efficient_freq < dev_priv->rps.min_freq); - WARN_ON(dev_priv->rps.efficient_freq > dev_priv->rps.max_freq); + intel_enable_rc6(dev_priv); + intel_enable_rps(dev_priv); + if (HAS_LLC(dev_priv)) + intel_enable_llc_pstate(dev_priv); - dev_priv->rps.enabled = true; - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } static void __intel_autoenable_gt_powersave(struct work_struct *work) { struct drm_i915_private *dev_priv = - container_of(work, typeof(*dev_priv), rps.autoenable_work.work); + container_of(work, + typeof(*dev_priv), + gt_pm.autoenable_work.work); struct intel_engine_cs *rcs; struct drm_i915_gem_request *req; - if (READ_ONCE(dev_priv->rps.enabled)) - goto out; - rcs = dev_priv->engine[RCS]; if (rcs->last_retired_context) goto out; @@ -7911,7 +8171,7 @@ static void __intel_autoenable_gt_powersave(struct work_struct *work) if (IS_ERR(req)) goto unlock; - if (!i915.enable_execlists && i915_switch_context(req) == 0) + if (!i915_modparams.enable_execlists && i915_switch_context(req) == 0) rcs->init_context(req); /* Mark the device busy, calling intel_enable_gt_powersave() */ @@ -7925,9 +8185,6 @@ out: void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv) { - if (READ_ONCE(dev_priv->rps.enabled)) - return; - if (IS_IRONLAKE_M(dev_priv)) { ironlake_enable_drps(dev_priv); intel_init_emon(dev_priv); @@ -7945,7 +8202,7 @@ void intel_autoenable_gt_powersave(struct drm_i915_private *dev_priv) * runtime resume it's necessary). */ if (queue_delayed_work(dev_priv->wq, - &dev_priv->rps.autoenable_work, + &dev_priv->gt_pm.autoenable_work, round_jiffies_up_relative(HZ))) intel_runtime_pm_get_noresume(dev_priv); } @@ -7975,18 +8232,6 @@ static void g4x_disable_trickle_feed(struct drm_i915_private *dev_priv) } } -static void ilk_init_lp_watermarks(struct drm_i915_private *dev_priv) -{ - I915_WRITE(WM3_LP_ILK, I915_READ(WM3_LP_ILK) & ~WM1_LP_SR_EN); - I915_WRITE(WM2_LP_ILK, I915_READ(WM2_LP_ILK) & ~WM1_LP_SR_EN); - I915_WRITE(WM1_LP_ILK, I915_READ(WM1_LP_ILK) & ~WM1_LP_SR_EN); - - /* - * Don't touch WM1S_LP_EN here. - * Doing so could cause underruns. - */ -} - static void ilk_init_clock_gating(struct drm_i915_private *dev_priv) { uint32_t dspclk_gate = ILK_VRHUNIT_CLOCK_GATE_DISABLE; @@ -8020,8 +8265,6 @@ static void ilk_init_clock_gating(struct drm_i915_private *dev_priv) (I915_READ(DISP_ARB_CTL) | DISP_FBC_WM_DIS)); - ilk_init_lp_watermarks(dev_priv); - /* * Based on the document from hardware guys the following bits * should be set unconditionally in order to enable FBC. @@ -8134,8 +8377,6 @@ static void gen6_init_clock_gating(struct drm_i915_private *dev_priv) I915_WRITE(GEN6_GT_MODE, _MASKED_FIELD(GEN6_WIZ_HASHING_MASK, GEN6_WIZ_HASHING_16x4)); - ilk_init_lp_watermarks(dev_priv); - I915_WRITE(CACHE_MODE_0, _MASKED_BIT_DISABLE(CM0_STC_EVICT_DISABLE_LRA_SNB)); @@ -8252,14 +8493,17 @@ static void gen8_set_l3sqc_credits(struct drm_i915_private *dev_priv, int high_prio_credits) { u32 misccpctl; + u32 val; /* WaTempDisableDOPClkGating:bdw */ misccpctl = I915_READ(GEN7_MISCCPCTL); I915_WRITE(GEN7_MISCCPCTL, misccpctl & ~GEN7_DOP_CLOCK_GATE_ENABLE); - I915_WRITE(GEN8_L3SQCREG1, - L3_GENERAL_PRIO_CREDITS(general_prio_credits) | - L3_HIGH_PRIO_CREDITS(high_prio_credits)); + val = I915_READ(GEN8_L3SQCREG1); + val &= ~L3_PRIO_CREDITS_MASK; + val |= L3_GENERAL_PRIO_CREDITS(general_prio_credits); + val |= L3_HIGH_PRIO_CREDITS(high_prio_credits); + I915_WRITE(GEN8_L3SQCREG1, val); /* * Wait at least 100 clocks before re-enabling clock gating. @@ -8276,7 +8520,8 @@ static void cnp_init_clock_gating(struct drm_i915_private *dev_priv) return; /* Wa #1181 */ - I915_WRITE(SOUTH_DSPCLK_GATE_D, CNP_PWM_CGE_GATING_DISABLE); + I915_WRITE(SOUTH_DSPCLK_GATE_D, I915_READ(SOUTH_DSPCLK_GATE_D) | + CNP_PWM_CGE_GATING_DISABLE); } static void cnl_init_clock_gating(struct drm_i915_private *dev_priv) @@ -8353,10 +8598,11 @@ static void skl_init_clock_gating(struct drm_i915_private *dev_priv) static void bdw_init_clock_gating(struct drm_i915_private *dev_priv) { + /* The GTT cache must be disabled if the system is using 2M pages. */ + bool can_use_gtt_cache = !HAS_PAGE_SIZES(dev_priv, + I915_GTT_PAGE_SIZE_2M); enum pipe pipe; - ilk_init_lp_watermarks(dev_priv); - /* WaSwitchSolVfFArbitrationPriority:bdw */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); @@ -8387,12 +8633,8 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv) /* WaProgramL3SqcReg1Default:bdw */ gen8_set_l3sqc_credits(dev_priv, 30, 2); - /* - * WaGttCachingOffByDefault:bdw - * GTT cache may not work with big pages, so if those - * are ever enabled GTT cache may need to be disabled. - */ - I915_WRITE(HSW_GTT_CACHE_EN, GTT_CACHE_EN_ALL); + /* WaGttCachingOffByDefault:bdw */ + I915_WRITE(HSW_GTT_CACHE_EN, can_use_gtt_cache ? GTT_CACHE_EN_ALL : 0); /* WaKVMNotificationOnConfigChange:bdw */ I915_WRITE(CHICKEN_PAR2_1, I915_READ(CHICKEN_PAR2_1) @@ -8411,8 +8653,6 @@ static void bdw_init_clock_gating(struct drm_i915_private *dev_priv) static void hsw_init_clock_gating(struct drm_i915_private *dev_priv) { - ilk_init_lp_watermarks(dev_priv); - /* L3 caching of data atomics doesn't work -- disable it. */ I915_WRITE(HSW_SCRATCH1, HSW_SCRATCH1_L3_DATA_ATOMICS_DISABLE); I915_WRITE(HSW_ROW_CHICKEN3, @@ -8456,10 +8696,6 @@ static void hsw_init_clock_gating(struct drm_i915_private *dev_priv) /* WaSwitchSolVfFArbitrationPriority:hsw */ I915_WRITE(GAM_ECOCHK, I915_READ(GAM_ECOCHK) | HSW_ECOCHK_ARB_PRIO_SOL); - /* WaRsPkgCStateDisplayPMReq:hsw */ - I915_WRITE(CHICKEN_PAR1_1, - I915_READ(CHICKEN_PAR1_1) | FORCE_ARB_IDLE_PLANES); - lpt_init_clock_gating(dev_priv); } @@ -8467,8 +8703,6 @@ static void ivb_init_clock_gating(struct drm_i915_private *dev_priv) { uint32_t snpcr; - ilk_init_lp_watermarks(dev_priv); - I915_WRITE(ILK_DSPCLK_GATE_D, ILK_VRHUNIT_CLOCK_GATE_DISABLE); /* WaDisableEarlyCull:ivb */ @@ -8973,7 +9207,7 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val { int status; - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); /* GEN6_PCODE_* are outside of the forcewake domain, we can * use te fw I915_READ variants to reduce the amount of work @@ -9020,7 +9254,7 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, { int status; - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); /* GEN6_PCODE_* are outside of the forcewake domain, we can * use te fw I915_READ variants to reduce the amount of work @@ -9097,7 +9331,7 @@ int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request, u32 status; int ret; - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); #define COND skl_pcode_try_request(dev_priv, mbox, request, reply_mask, reply, \ &status) @@ -9139,31 +9373,39 @@ out: static int byt_gpu_freq(struct drm_i915_private *dev_priv, int val) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + /* * N = val - 0xb7 * Slow = Fast = GPLL ref * N */ - return DIV_ROUND_CLOSEST(dev_priv->rps.gpll_ref_freq * (val - 0xb7), 1000); + return DIV_ROUND_CLOSEST(rps->gpll_ref_freq * (val - 0xb7), 1000); } static int byt_freq_opcode(struct drm_i915_private *dev_priv, int val) { - return DIV_ROUND_CLOSEST(1000 * val, dev_priv->rps.gpll_ref_freq) + 0xb7; + struct intel_rps *rps = &dev_priv->gt_pm.rps; + + return DIV_ROUND_CLOSEST(1000 * val, rps->gpll_ref_freq) + 0xb7; } static int chv_gpu_freq(struct drm_i915_private *dev_priv, int val) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + /* * N = val / 2 * CU (slow) = CU2x (fast) / 2 = GPLL ref * N / 2 */ - return DIV_ROUND_CLOSEST(dev_priv->rps.gpll_ref_freq * val, 2 * 2 * 1000); + return DIV_ROUND_CLOSEST(rps->gpll_ref_freq * val, 2 * 2 * 1000); } static int chv_freq_opcode(struct drm_i915_private *dev_priv, int val) { + struct intel_rps *rps = &dev_priv->gt_pm.rps; + /* CHV needs even values */ - return DIV_ROUND_CLOSEST(2 * 1000 * val, dev_priv->rps.gpll_ref_freq) * 2; + return DIV_ROUND_CLOSEST(2 * 1000 * val, rps->gpll_ref_freq) * 2; } int intel_gpu_freq(struct drm_i915_private *dev_priv, int val) @@ -9194,14 +9436,14 @@ int intel_freq_opcode(struct drm_i915_private *dev_priv, int val) void intel_pm_setup(struct drm_i915_private *dev_priv) { - mutex_init(&dev_priv->rps.hw_lock); + mutex_init(&dev_priv->pcu_lock); - INIT_DELAYED_WORK(&dev_priv->rps.autoenable_work, + INIT_DELAYED_WORK(&dev_priv->gt_pm.autoenable_work, __intel_autoenable_gt_powersave); - atomic_set(&dev_priv->rps.num_waiters, 0); + atomic_set(&dev_priv->gt_pm.rps.num_waiters, 0); - dev_priv->pm.suspended = false; - atomic_set(&dev_priv->pm.wakeref_count, 0); + dev_priv->runtime_pm.suspended = false; + atomic_set(&dev_priv->runtime_pm.wakeref_count, 0); } static u64 vlv_residency_raw(struct drm_i915_private *dev_priv, @@ -9254,7 +9496,7 @@ u64 intel_rc6_residency_us(struct drm_i915_private *dev_priv, { u64 time_hw, units, div; - if (!intel_enable_rc6()) + if (!intel_rc6_enabled()) return 0; intel_runtime_pm_get(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_psr.c b/drivers/gpu/drm/i915/intel_psr.c index f62ab05d3d62..6e3b430fccdc 100644 --- a/drivers/gpu/drm/i915/intel_psr.c +++ b/drivers/gpu/drm/i915/intel_psr.c @@ -58,6 +58,9 @@ static bool is_edp_psr(struct intel_dp *intel_dp) { + if (!intel_dp_is_edp(intel_dp)) + return false; + return intel_dp->psr_dpcd[0] & DP_PSR_IS_SUPPORTED; } @@ -72,37 +75,6 @@ static bool vlv_is_psr_active_on_pipe(struct drm_device *dev, int pipe) (val == VLV_EDP_PSR_ACTIVE_SF_UPDATE); } -static void intel_psr_write_vsc(struct intel_dp *intel_dp, - const struct edp_vsc_psr *vsc_psr) -{ - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct intel_crtc *crtc = to_intel_crtc(dig_port->base.base.crtc); - enum transcoder cpu_transcoder = crtc->config->cpu_transcoder; - i915_reg_t ctl_reg = HSW_TVIDEO_DIP_CTL(cpu_transcoder); - uint32_t *data = (uint32_t *) vsc_psr; - unsigned int i; - - /* As per BSPec (Pipe Video Data Island Packet), we need to disable - the video DIP being updated before program video DIP data buffer - registers for DIP being updated. */ - I915_WRITE(ctl_reg, 0); - POSTING_READ(ctl_reg); - - for (i = 0; i < sizeof(*vsc_psr); i += 4) { - I915_WRITE(HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, - i >> 2), *data); - data++; - } - for (; i < VIDEO_DIP_VSC_DATA_SIZE; i += 4) - I915_WRITE(HSW_TVIDEO_DIP_VSC_DATA(cpu_transcoder, - i >> 2), 0); - - I915_WRITE(ctl_reg, VIDEO_DIP_ENABLE_VSC_HSW); - POSTING_READ(ctl_reg); -} - static void vlv_psr_setup_vsc(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state) { @@ -117,44 +89,40 @@ static void vlv_psr_setup_vsc(struct intel_dp *intel_dp, I915_WRITE(VLV_VSCSDP(crtc->pipe), val); } -static void skl_psr_setup_su_vsc(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) +static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) { struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(intel_dig_port->base.base.dev); struct edp_vsc_psr psr_vsc; - /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ - memset(&psr_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - if (dev_priv->psr.colorimetry_support && - dev_priv->psr.y_cord_support) { - psr_vsc.sdp_header.HB2 = 0x5; - psr_vsc.sdp_header.HB3 = 0x13; - } else if (dev_priv->psr.y_cord_support) { - psr_vsc.sdp_header.HB2 = 0x4; - psr_vsc.sdp_header.HB3 = 0xe; + if (dev_priv->psr.psr2_support) { + /* Prepare VSC Header for SU as per EDP 1.4 spec, Table 6.11 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + if (dev_priv->psr.colorimetry_support && + dev_priv->psr.y_cord_support) { + psr_vsc.sdp_header.HB2 = 0x5; + psr_vsc.sdp_header.HB3 = 0x13; + } else if (dev_priv->psr.y_cord_support) { + psr_vsc.sdp_header.HB2 = 0x4; + psr_vsc.sdp_header.HB3 = 0xe; + } else { + psr_vsc.sdp_header.HB2 = 0x3; + psr_vsc.sdp_header.HB3 = 0xc; + } } else { - psr_vsc.sdp_header.HB2 = 0x3; - psr_vsc.sdp_header.HB3 = 0xc; + /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; } - intel_psr_write_vsc(intel_dp, &psr_vsc); -} - -static void hsw_psr_setup_vsc(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) -{ - struct edp_vsc_psr psr_vsc; - - /* Prepare VSC packet as per EDP 1.3 spec, Table 3.10 */ - memset(&psr_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - intel_psr_write_vsc(intel_dp, &psr_vsc); + intel_dig_port->write_infoframe(&intel_dig_port->base.base, crtc_state, + DP_SDP_VSC, &psr_vsc, sizeof(psr_vsc)); } static void vlv_psr_enable_sink(struct intel_dp *intel_dp) @@ -239,7 +207,7 @@ static void vlv_psr_enable_source(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->base.crtc); - /* Transition from PSR_state 0 to PSR_state 1, i.e. PSR Inactive */ + /* Transition from PSR_state 0 (disabled) to PSR_state 1 (inactive) */ I915_WRITE(VLV_PSRCTL(crtc->pipe), VLV_EDP_PSR_MODE_SW_TIMER | VLV_EDP_PSR_SRC_TRANSMITTER_STATE | @@ -254,16 +222,17 @@ static void vlv_psr_activate(struct intel_dp *intel_dp) struct drm_crtc *crtc = dig_port->base.base.crtc; enum pipe pipe = to_intel_crtc(crtc)->pipe; - /* Let's do the transition from PSR_state 1 to PSR_state 2 - * that is PSR transition to active - static frame transmission. - * Then Hardware is responsible for the transition to PSR_state 3 - * that is PSR active - no Remote Frame Buffer (RFB) update. + /* + * Let's do the transition from PSR_state 1 (inactive) to + * PSR_state 2 (transition to active - static frame transmission). + * Then Hardware is responsible for the transition to + * PSR_state 3 (active - no Remote Frame Buffer (RFB) update). */ I915_WRITE(VLV_PSRCTL(pipe), I915_READ(VLV_PSRCTL(pipe)) | VLV_EDP_PSR_ACTIVE_ENTRY); } -static void intel_enable_source_psr1(struct intel_dp *intel_dp) +static void hsw_activate_psr1(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; @@ -317,7 +286,7 @@ static void intel_enable_source_psr1(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR_CTL, val); } -static void intel_enable_source_psr2(struct intel_dp *intel_dp) +static void hsw_activate_psr2(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; @@ -331,6 +300,7 @@ static void intel_enable_source_psr2(struct intel_dp *intel_dp) */ uint32_t idle_frames = max(6, dev_priv->vbt.psr.idle_frames); uint32_t val; + uint8_t sink_latency; val = idle_frames << EDP_PSR_IDLE_FRAME_SHIFT; @@ -338,8 +308,16 @@ static void intel_enable_source_psr2(struct intel_dp *intel_dp) * mesh at all with our frontbuffer tracking. And the hw alone isn't * good enough. */ val |= EDP_PSR2_ENABLE | - EDP_SU_TRACK_ENABLE | - EDP_FRAMES_BEFORE_SU_ENTRY; + EDP_SU_TRACK_ENABLE; + + if (drm_dp_dpcd_readb(&intel_dp->aux, + DP_SYNCHRONIZATION_LATENCY_IN_SINK, + &sink_latency) == 1) { + sink_latency &= DP_MAX_RESYNC_FRAME_COUNT_MASK; + } else { + sink_latency = 0; + } + val |= EDP_PSR2_FRAME_BEFORE_SU(sink_latency + 1); if (dev_priv->vbt.psr.tp2_tp3_wakeup_time > 5) val |= EDP_PSR2_TP2_TIME_2500; @@ -353,35 +331,43 @@ static void intel_enable_source_psr2(struct intel_dp *intel_dp) I915_WRITE(EDP_PSR2_CTL, val); } -static void hsw_psr_enable_source(struct intel_dp *intel_dp) +static void hsw_psr_activate(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + /* On HSW+ after we enable PSR on source it will activate it + * as soon as it match configure idle_frame count. So + * we just actually enable it here on activation time. + */ + /* psr1 and psr2 are mutually exclusive.*/ if (dev_priv->psr.psr2_support) - intel_enable_source_psr2(intel_dp); + hsw_activate_psr2(intel_dp); else - intel_enable_source_psr1(intel_dp); + hsw_activate_psr1(intel_dp); } -static bool intel_psr_match_conditions(struct intel_dp *intel_dp) +void intel_psr_compute_config(struct intel_dp *intel_dp, + struct intel_crtc_state *crtc_state) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_device *dev = dig_port->base.base.dev; - struct drm_i915_private *dev_priv = to_i915(dev); - struct drm_crtc *crtc = dig_port->base.base.crtc; - struct intel_crtc *intel_crtc = to_intel_crtc(crtc); + struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); const struct drm_display_mode *adjusted_mode = - &intel_crtc->config->base.adjusted_mode; + &crtc_state->base.adjusted_mode; int psr_setup_time; - lockdep_assert_held(&dev_priv->psr.lock); - WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); - WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (!HAS_PSR(dev_priv)) + return; + + if (!is_edp_psr(intel_dp)) + return; - dev_priv->psr.source_ok = false; + if (!i915_modparams.enable_psr) { + DRM_DEBUG_KMS("PSR disable by flag\n"); + return; + } /* * HSW spec explicitly says PSR is tied to port A. @@ -392,66 +378,70 @@ static bool intel_psr_match_conditions(struct intel_dp *intel_dp) */ if (HAS_DDI(dev_priv) && dig_port->port != PORT_A) { DRM_DEBUG_KMS("PSR condition failed: Port not supported\n"); - return false; - } - - if (!i915.enable_psr) { - DRM_DEBUG_KMS("PSR disable by flag\n"); - return false; + return; } if ((IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) && !dev_priv->psr.link_standby) { DRM_ERROR("PSR condition failed: Link off requested but not supported on this platform\n"); - return false; + return; } if (IS_HASWELL(dev_priv) && - I915_READ(HSW_STEREO_3D_CTL(intel_crtc->config->cpu_transcoder)) & + I915_READ(HSW_STEREO_3D_CTL(crtc_state->cpu_transcoder)) & S3D_ENABLE) { DRM_DEBUG_KMS("PSR condition failed: Stereo 3D is Enabled\n"); - return false; + return; } if (IS_HASWELL(dev_priv) && adjusted_mode->flags & DRM_MODE_FLAG_INTERLACE) { DRM_DEBUG_KMS("PSR condition failed: Interlaced is Enabled\n"); - return false; + return; } psr_setup_time = drm_dp_psr_setup_time(intel_dp->psr_dpcd); if (psr_setup_time < 0) { DRM_DEBUG_KMS("PSR condition failed: Invalid PSR setup time (0x%02x)\n", intel_dp->psr_dpcd[1]); - return false; + return; } if (intel_usecs_to_scanlines(adjusted_mode, psr_setup_time) > adjusted_mode->crtc_vtotal - adjusted_mode->crtc_vdisplay - 1) { DRM_DEBUG_KMS("PSR condition failed: PSR setup time (%d us) too long\n", psr_setup_time); - return false; + return; + } + + /* + * FIXME psr2_support is messed up. It's both computed + * dynamically during PSR enable, and extracted from sink + * caps during eDP detection. + */ + if (!dev_priv->psr.psr2_support) { + crtc_state->has_psr = true; + return; } /* PSR2 is restricted to work with panel resolutions upto 3200x2000 */ - if (dev_priv->psr.psr2_support && - (intel_crtc->config->pipe_src_w > 3200 || - intel_crtc->config->pipe_src_h > 2000)) { - dev_priv->psr.psr2_support = false; - return false; + if (adjusted_mode->crtc_hdisplay > 3200 || + adjusted_mode->crtc_vdisplay > 2000) { + DRM_DEBUG_KMS("PSR2 disabled, panel resolution too big\n"); + return; } /* * FIXME:enable psr2 only for y-cordinate psr2 panels * After gtc implementation , remove this restriction. */ - if (!dev_priv->psr.y_cord_support && dev_priv->psr.psr2_support) { + if (!dev_priv->psr.y_cord_support) { DRM_DEBUG_KMS("PSR2 disabled, panel does not support Y coordinate\n"); - return false; + return; } - dev_priv->psr.source_ok = true; - return true; + crtc_state->has_psr = true; + crtc_state->has_psr2 = true; } static void intel_psr_activate(struct intel_dp *intel_dp) @@ -467,19 +457,46 @@ static void intel_psr_activate(struct intel_dp *intel_dp) WARN_ON(dev_priv->psr.active); lockdep_assert_held(&dev_priv->psr.lock); - /* Enable/Re-enable PSR on the host */ - if (HAS_DDI(dev_priv)) - /* On HSW+ after we enable PSR on source it will activate it - * as soon as it match configure idle_frame count. So - * we just actually enable it here on activation time. - */ - hsw_psr_enable_source(intel_dp); - else - vlv_psr_activate(intel_dp); - + dev_priv->psr.activate(intel_dp); dev_priv->psr.active = true; } +static void hsw_psr_enable_source(struct intel_dp *intel_dp, + const struct intel_crtc_state *crtc_state) +{ + struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); + struct drm_device *dev = dig_port->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(dev); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + u32 chicken; + + if (dev_priv->psr.psr2_support) { + chicken = PSR2_VSC_ENABLE_PROG_HEADER; + if (dev_priv->psr.y_cord_support) + chicken |= PSR2_ADD_VERTICAL_LINE_COUNT; + I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); + + I915_WRITE(EDP_PSR_DEBUG_CTL, + EDP_PSR_DEBUG_MASK_MEMUP | + EDP_PSR_DEBUG_MASK_HPD | + EDP_PSR_DEBUG_MASK_LPSP | + EDP_PSR_DEBUG_MASK_MAX_SLEEP | + EDP_PSR_DEBUG_MASK_DISP_REG_WRITE); + } else { + /* + * Per Spec: Avoid continuous PSR exit by masking MEMUP + * and HPD. also mask LPSP to avoid dependency on other + * drivers that might block runtime_pm besides + * preventing other hw tracking issues now we can rely + * on frontbuffer tracking. + */ + I915_WRITE(EDP_PSR_DEBUG_CTL, + EDP_PSR_DEBUG_MASK_MEMUP | + EDP_PSR_DEBUG_MASK_HPD | + EDP_PSR_DEBUG_MASK_LPSP); + } +} + /** * intel_psr_enable - Enable PSR * @intel_dp: Intel DP @@ -493,96 +510,44 @@ void intel_psr_enable(struct intel_dp *intel_dp, struct intel_digital_port *intel_dig_port = dp_to_dig_port(intel_dp); struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - u32 chicken; - if (!HAS_PSR(dev_priv)) { - DRM_DEBUG_KMS("PSR not supported on this platform\n"); + if (!crtc_state->has_psr) return; - } - - if (!is_edp_psr(intel_dp)) { - DRM_DEBUG_KMS("PSR not supported by this panel\n"); - return; - } + WARN_ON(dev_priv->drrs.dp); mutex_lock(&dev_priv->psr.lock); if (dev_priv->psr.enabled) { DRM_DEBUG_KMS("PSR already in use\n"); goto unlock; } - if (!intel_psr_match_conditions(intel_dp)) - goto unlock; + dev_priv->psr.psr2_support = crtc_state->has_psr2; + dev_priv->psr.source_ok = true; dev_priv->psr.busy_frontbuffer_bits = 0; - if (HAS_DDI(dev_priv)) { - if (dev_priv->psr.psr2_support) { - skl_psr_setup_su_vsc(intel_dp, crtc_state); - - chicken = PSR2_VSC_ENABLE_PROG_HEADER; - if (dev_priv->psr.y_cord_support) - chicken |= PSR2_ADD_VERTICAL_LINE_COUNT; - I915_WRITE(CHICKEN_TRANS(cpu_transcoder), chicken); - - I915_WRITE(EDP_PSR_DEBUG_CTL, - EDP_PSR_DEBUG_MASK_MEMUP | - EDP_PSR_DEBUG_MASK_HPD | - EDP_PSR_DEBUG_MASK_LPSP | - EDP_PSR_DEBUG_MASK_MAX_SLEEP | - EDP_PSR_DEBUG_MASK_DISP_REG_WRITE); - } else { - /* set up vsc header for psr1 */ - hsw_psr_setup_vsc(intel_dp, crtc_state); - - /* - * Per Spec: Avoid continuous PSR exit by masking MEMUP - * and HPD. also mask LPSP to avoid dependency on other - * drivers that might block runtime_pm besides - * preventing other hw tracking issues now we can rely - * on frontbuffer tracking. - */ - I915_WRITE(EDP_PSR_DEBUG_CTL, - EDP_PSR_DEBUG_MASK_MEMUP | - EDP_PSR_DEBUG_MASK_HPD | - EDP_PSR_DEBUG_MASK_LPSP); - } - - /* Enable PSR on the panel */ - hsw_psr_enable_sink(intel_dp); + dev_priv->psr.setup_vsc(intel_dp, crtc_state); + dev_priv->psr.enable_sink(intel_dp); + dev_priv->psr.enable_source(intel_dp, crtc_state); + dev_priv->psr.enabled = intel_dp; - if (INTEL_GEN(dev_priv) >= 9) - intel_psr_activate(intel_dp); + if (INTEL_GEN(dev_priv) >= 9) { + intel_psr_activate(intel_dp); } else { - vlv_psr_setup_vsc(intel_dp, crtc_state); - - /* Enable PSR on the panel */ - vlv_psr_enable_sink(intel_dp); - - /* On HSW+ enable_source also means go to PSR entry/active - * state as soon as idle_frame achieved and here would be - * to soon. However on VLV enable_source just enable PSR - * but let it on inactive state. So we might do this prior - * to active transition, i.e. here. + /* + * FIXME: Activation should happen immediately since this + * function is just called after pipe is fully trained and + * enabled. + * However on some platforms we face issues when first + * activation follows a modeset so quickly. + * - On VLV/CHV we get bank screen on first activation + * - On HSW/BDW we get a recoverable frozen screen until + * next exit-activate sequence. */ - vlv_psr_enable_source(intel_dp, crtc_state); - } - - /* - * FIXME: Activation should happen immediately since this function - * is just called after pipe is fully trained and enabled. - * However on every platform we face issues when first activation - * follows a modeset so quickly. - * - On VLV/CHV we get bank screen on first activation - * - On HSW/BDW we get a recoverable frozen screen until next - * exit-activate sequence. - */ - if (INTEL_GEN(dev_priv) < 9) schedule_delayed_work(&dev_priv->psr.work, msecs_to_jiffies(intel_dp->panel_power_cycle_delay * 5)); + } - dev_priv->psr.enabled = intel_dp; unlock: mutex_unlock(&dev_priv->psr.lock); } @@ -597,7 +562,7 @@ static void vlv_psr_disable(struct intel_dp *intel_dp, uint32_t val; if (dev_priv->psr.active) { - /* Put VLV PSR back to PSR_state 0 that is PSR Disabled. */ + /* Put VLV PSR back to PSR_state 0 (disabled). */ if (intel_wait_for_register(dev_priv, VLV_PSRSTAT(crtc->pipe), VLV_EDP_PSR_IN_TRANS, @@ -678,17 +643,16 @@ void intel_psr_disable(struct intel_dp *intel_dp, struct drm_device *dev = intel_dig_port->base.base.dev; struct drm_i915_private *dev_priv = to_i915(dev); + if (!old_crtc_state->has_psr) + return; + mutex_lock(&dev_priv->psr.lock); if (!dev_priv->psr.enabled) { mutex_unlock(&dev_priv->psr.lock); return; } - /* Disable PSR on Source */ - if (HAS_DDI(dev_priv)) - hsw_psr_disable(intel_dp, old_crtc_state); - else - vlv_psr_disable(intel_dp, old_crtc_state); + dev_priv->psr.disable_source(intel_dp, old_crtc_state); /* Disable PSR on Sink */ drm_dp_dpcd_writeb(&intel_dp->aux, DP_PSR_EN_CFG, 0); @@ -788,17 +752,20 @@ static void intel_psr_exit(struct drm_i915_private *dev_priv) } else { val = I915_READ(VLV_PSRCTL(pipe)); - /* Here we do the transition from PSR_state 3 to PSR_state 5 - * directly once PSR State 4 that is active with single frame - * update can be skipped. PSR_state 5 that is PSR exit then - * Hardware is responsible to transition back to PSR_state 1 - * that is PSR inactive. Same state after - * vlv_edp_psr_enable_source. + /* + * Here we do the transition drirectly from + * PSR_state 3 (active - no Remote Frame Buffer (RFB) update) to + * PSR_state 5 (exit). + * PSR State 4 (active with single frame update) can be skipped. + * On PSR_state 5 (exit) Hardware is responsible to transition + * back to PSR_state 1 (inactive). + * Now we are at Same state after vlv_psr_enable_source. */ val &= ~VLV_EDP_PSR_ACTIVE_ENTRY; I915_WRITE(VLV_PSRCTL(pipe), val); - /* Send AUX wake up - Spec says after transitioning to PSR + /* + * Send AUX wake up - Spec says after transitioning to PSR * active we have to send AUX wake up by writing 01h in DPCD * 600h of sink device. * XXX: This might slow down the transition, but without this @@ -829,6 +796,9 @@ void intel_psr_single_frame_update(struct drm_i915_private *dev_priv, enum pipe pipe; u32 val; + if (!HAS_PSR(dev_priv)) + return; + /* * Single frame update is already supported on BDW+ but it requires * many W/A and it isn't really needed. @@ -875,6 +845,9 @@ void intel_psr_invalidate(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; + if (!HAS_PSR(dev_priv)) + return; + mutex_lock(&dev_priv->psr.lock); if (!dev_priv->psr.enabled) { mutex_unlock(&dev_priv->psr.lock); @@ -912,6 +885,9 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; + if (!HAS_PSR(dev_priv)) + return; + mutex_lock(&dev_priv->psr.lock); if (!dev_priv->psr.enabled) { mutex_unlock(&dev_priv->psr.lock); @@ -944,12 +920,15 @@ void intel_psr_flush(struct drm_i915_private *dev_priv, */ void intel_psr_init(struct drm_i915_private *dev_priv) { + if (!HAS_PSR(dev_priv)) + return; + dev_priv->psr_mmio_base = IS_HASWELL(dev_priv) ? HSW_EDP_PSR_BASE : BDW_EDP_PSR_BASE; /* Per platform default: all disabled. */ - if (i915.enable_psr == -1) - i915.enable_psr = 0; + if (i915_modparams.enable_psr == -1) + i915_modparams.enable_psr = 0; /* Set link_standby x link_off defaults */ if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) @@ -963,15 +942,29 @@ void intel_psr_init(struct drm_i915_private *dev_priv) dev_priv->psr.link_standby = dev_priv->vbt.psr.full_link; /* Override link_standby x link_off defaults */ - if (i915.enable_psr == 2 && !dev_priv->psr.link_standby) { + if (i915_modparams.enable_psr == 2 && !dev_priv->psr.link_standby) { DRM_DEBUG_KMS("PSR: Forcing link standby\n"); dev_priv->psr.link_standby = true; } - if (i915.enable_psr == 3 && dev_priv->psr.link_standby) { + if (i915_modparams.enable_psr == 3 && dev_priv->psr.link_standby) { DRM_DEBUG_KMS("PSR: Forcing main link off\n"); dev_priv->psr.link_standby = false; } INIT_DELAYED_WORK(&dev_priv->psr.work, intel_psr_work); mutex_init(&dev_priv->psr.lock); + + if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { + dev_priv->psr.enable_source = vlv_psr_enable_source; + dev_priv->psr.disable_source = vlv_psr_disable; + dev_priv->psr.enable_sink = vlv_psr_enable_sink; + dev_priv->psr.activate = vlv_psr_activate; + dev_priv->psr.setup_vsc = vlv_psr_setup_vsc; + } else { + dev_priv->psr.enable_source = hsw_psr_enable_source; + dev_priv->psr.disable_source = hsw_psr_disable; + dev_priv->psr.enable_sink = hsw_psr_enable_sink; + dev_priv->psr.activate = hsw_psr_activate; + dev_priv->psr.setup_vsc = hsw_psr_setup_vsc; + } } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index cdf084ef5aae..8da1bde442dd 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -402,17 +402,18 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine) */ if (IS_GEN7(dev_priv)) { switch (engine->id) { + /* + * No more rings exist on Gen7. Default case is only to shut up + * gcc switch check warning. + */ + default: + GEM_BUG_ON(engine->id); case RCS: mmio = RENDER_HWS_PGA_GEN7; break; case BCS: mmio = BLT_HWS_PGA_GEN7; break; - /* - * VCS2 actually doesn't exist on Gen7. Only shut up - * gcc switch check warning - */ - case VCS2: case VCS: mmio = BSD_HWS_PGA_GEN7; break; @@ -427,6 +428,9 @@ static void intel_ring_setup_status_page(struct intel_engine_cs *engine) mmio = RING_HWS_PGA(engine->mmio_base); } + if (INTEL_GEN(dev_priv) >= 6) + I915_WRITE(RING_HWSTAM(engine->mmio_base), 0xffffffff); + I915_WRITE(mmio, engine->status_page.ggtt_offset); POSTING_READ(mmio); @@ -480,11 +484,6 @@ static bool stop_ring(struct intel_engine_cs *engine) I915_WRITE_HEAD(engine, 0); I915_WRITE_TAIL(engine, 0); - if (INTEL_GEN(dev_priv) > 2) { - (void)I915_READ_CTL(engine); - I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); - } - return (I915_READ_HEAD(engine) & HEAD_ADDR) == 0; } @@ -566,6 +565,9 @@ static int init_ring_common(struct intel_engine_cs *engine) intel_engine_init_hangcheck(engine); + if (INTEL_GEN(dev_priv) > 2) + I915_WRITE_MODE(engine, _MASKED_BIT_DISABLE(STOP_RING)); + out: intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); @@ -575,7 +577,16 @@ out: static void reset_ring_common(struct intel_engine_cs *engine, struct drm_i915_gem_request *request) { - /* Try to restore the logical GPU state to match the continuation + /* + * RC6 must be prevented until the reset is complete and the engine + * reinitialised. If it occurs in the middle of this sequence, the + * state written to/loaded from the power context is ill-defined (e.g. + * the PP_BASE_DIR may be lost). + */ + assert_forcewakes_active(engine->i915, FORCEWAKE_ALL); + + /* + * Try to restore the logical GPU state to match the continuation * of the request queue. If we skip the context/PD restore, then * the next request may try to execute assuming that its context * is valid and loaded on the GPU and so may try to access invalid @@ -778,6 +789,24 @@ static u32 *gen6_signal(struct drm_i915_gem_request *req, u32 *cs) return cs; } +static void cancel_requests(struct intel_engine_cs *engine) +{ + struct drm_i915_gem_request *request; + unsigned long flags; + + spin_lock_irqsave(&engine->timeline->lock, flags); + + /* Mark all submitted requests as skipped. */ + list_for_each_entry(request, &engine->timeline->requests, link) { + GEM_BUG_ON(!request->global_seqno); + if (!i915_gem_request_completed(request)) + dma_fence_set_error(&request->fence, -EIO); + } + /* Remaining _unready_ requests will be nop'ed when submitted */ + + spin_unlock_irqrestore(&engine->timeline->lock, flags); +} + static void i9xx_submit_request(struct drm_i915_gem_request *request) { struct drm_i915_private *dev_priv = request->i915; @@ -1174,113 +1203,7 @@ i915_emit_bb_start(struct drm_i915_gem_request *req, return 0; } -static void cleanup_phys_status_page(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - - if (!dev_priv->status_page_dmah) - return; - - drm_pci_free(&dev_priv->drm, dev_priv->status_page_dmah); - engine->status_page.page_addr = NULL; -} - -static void cleanup_status_page(struct intel_engine_cs *engine) -{ - struct i915_vma *vma; - struct drm_i915_gem_object *obj; - - vma = fetch_and_zero(&engine->status_page.vma); - if (!vma) - return; - - obj = vma->obj; - - i915_vma_unpin(vma); - i915_vma_close(vma); - - i915_gem_object_unpin_map(obj); - __i915_gem_object_release_unless_active(obj); -} - -static int init_status_page(struct intel_engine_cs *engine) -{ - struct drm_i915_gem_object *obj; - struct i915_vma *vma; - unsigned int flags; - void *vaddr; - int ret; - - obj = i915_gem_object_create_internal(engine->i915, PAGE_SIZE); - if (IS_ERR(obj)) { - DRM_ERROR("Failed to allocate status page\n"); - return PTR_ERR(obj); - } - - ret = i915_gem_object_set_cache_level(obj, I915_CACHE_LLC); - if (ret) - goto err; - - vma = i915_vma_instance(obj, &engine->i915->ggtt.base, NULL); - if (IS_ERR(vma)) { - ret = PTR_ERR(vma); - goto err; - } - - flags = PIN_GLOBAL; - if (!HAS_LLC(engine->i915)) - /* On g33, we cannot place HWS above 256MiB, so - * restrict its pinning to the low mappable arena. - * Though this restriction is not documented for - * gen4, gen5, or byt, they also behave similarly - * and hang if the HWS is placed at the top of the - * GTT. To generalise, it appears that all !llc - * platforms have issues with us placing the HWS - * above the mappable region (even though we never - * actualy map it). - */ - flags |= PIN_MAPPABLE; - ret = i915_vma_pin(vma, 0, 4096, flags); - if (ret) - goto err; - - vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); - if (IS_ERR(vaddr)) { - ret = PTR_ERR(vaddr); - goto err_unpin; - } - - engine->status_page.vma = vma; - engine->status_page.ggtt_offset = i915_ggtt_offset(vma); - engine->status_page.page_addr = memset(vaddr, 0, PAGE_SIZE); - - DRM_DEBUG_DRIVER("%s hws offset: 0x%08x\n", - engine->name, i915_ggtt_offset(vma)); - return 0; - -err_unpin: - i915_vma_unpin(vma); -err: - i915_gem_object_put(obj); - return ret; -} - -static int init_phys_status_page(struct intel_engine_cs *engine) -{ - struct drm_i915_private *dev_priv = engine->i915; - - GEM_BUG_ON(engine->id != RCS); - - dev_priv->status_page_dmah = - drm_pci_alloc(&dev_priv->drm, PAGE_SIZE, PAGE_SIZE); - if (!dev_priv->status_page_dmah) - return -ENOMEM; - - engine->status_page.page_addr = dev_priv->status_page_dmah->vaddr; - memset(engine->status_page.page_addr, 0, PAGE_SIZE); - return 0; -} int intel_ring_pin(struct intel_ring *ring, struct drm_i915_private *i915, @@ -1321,6 +1244,8 @@ int intel_ring_pin(struct intel_ring *ring, if (IS_ERR(addr)) goto err; + vma->obj->pin_global++; + ring->vaddr = addr; return 0; @@ -1352,6 +1277,7 @@ void intel_ring_unpin(struct intel_ring *ring) i915_gem_object_unpin_map(ring->vma->obj); ring->vaddr = NULL; + ring->vma->obj->pin_global--; i915_vma_unpin(ring->vma); } @@ -1516,6 +1442,7 @@ intel_ring_context_pin(struct intel_engine_cs *engine, goto err; ce->state->obj->mm.dirty = true; + ce->state->obj->pin_global++; } /* The kernel context is only used as a placeholder for flushing the @@ -1550,8 +1477,10 @@ static void intel_ring_context_unpin(struct intel_engine_cs *engine, if (--ce->pin_count) return; - if (ce->state) + if (ce->state) { + ce->state->obj->pin_global--; i915_vma_unpin(ce->state); + } i915_gem_context_put(ctx); } @@ -1567,17 +1496,10 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine) if (err) goto err; - if (HWS_NEEDS_PHYSICAL(engine->i915)) - err = init_phys_status_page(engine); - else - err = init_status_page(engine); - if (err) - goto err; - ring = intel_engine_create_ring(engine, 32 * PAGE_SIZE); if (IS_ERR(ring)) { err = PTR_ERR(ring); - goto err_hws; + goto err; } /* Ring wraparound at offset 0 sometimes hangs. No idea why. */ @@ -1592,11 +1514,6 @@ static int intel_init_ring_buffer(struct intel_engine_cs *engine) err_ring: intel_ring_free(ring); -err_hws: - if (HWS_NEEDS_PHYSICAL(engine->i915)) - cleanup_phys_status_page(engine); - else - cleanup_status_page(engine); err: intel_engine_cleanup_common(engine); return err; @@ -1615,11 +1532,6 @@ void intel_engine_cleanup(struct intel_engine_cs *engine) if (engine->cleanup) engine->cleanup(engine); - if (HWS_NEEDS_PHYSICAL(dev_priv)) - cleanup_phys_status_page(engine); - else - cleanup_status_page(engine); - intel_engine_cleanup_common(engine); dev_priv->engine[engine->id] = NULL; @@ -1983,7 +1895,7 @@ static void intel_ring_init_semaphores(struct drm_i915_private *dev_priv, struct drm_i915_gem_object *obj; int ret, i; - if (!i915.semaphores) + if (!i915_modparams.semaphores) return; if (INTEL_GEN(dev_priv) >= 8 && !dev_priv->semaphore) { @@ -2083,7 +1995,7 @@ err_obj: i915_gem_object_put(obj); err: DRM_DEBUG_DRIVER("Failed to allocate space for semaphores, disabling\n"); - i915.semaphores = 0; + i915_modparams.semaphores = 0; } static void intel_ring_init_irq(struct drm_i915_private *dev_priv, @@ -2115,11 +2027,13 @@ static void intel_ring_init_irq(struct drm_i915_private *dev_priv, static void i9xx_set_default_submission(struct intel_engine_cs *engine) { engine->submit_request = i9xx_submit_request; + engine->cancel_requests = cancel_requests; } static void gen6_bsd_set_default_submission(struct intel_engine_cs *engine) { engine->submit_request = gen6_bsd_submit_request; + engine->cancel_requests = cancel_requests; } static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, @@ -2138,7 +2052,7 @@ static void intel_ring_default_vfuncs(struct drm_i915_private *dev_priv, engine->emit_breadcrumb = i9xx_emit_breadcrumb; engine->emit_breadcrumb_sz = i9xx_emit_breadcrumb_sz; - if (i915.semaphores) { + if (i915_modparams.semaphores) { int num_rings; engine->emit_breadcrumb = gen6_sema_emit_breadcrumb; @@ -2182,7 +2096,7 @@ int intel_init_render_ring_buffer(struct intel_engine_cs *engine) engine->emit_breadcrumb = gen8_render_emit_breadcrumb; engine->emit_breadcrumb_sz = gen8_render_emit_breadcrumb_sz; engine->emit_flush = gen8_render_ring_flush; - if (i915.semaphores) { + if (i915_modparams.semaphores) { int num_rings; engine->semaphore.signal = gen8_rcs_signal; diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h index 79c0021f3700..6a42ed618a28 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.h +++ b/drivers/gpu/drm/i915/intel_ringbuffer.h @@ -7,6 +7,8 @@ #include "i915_gem_timeline.h" #include "i915_selftest.h" +struct drm_printer; + #define I915_CMD_HASH_ORDER 9 /* Early gen2 devices have a cacheline of just 32 bytes, using 64 is overkill, @@ -184,6 +186,104 @@ struct i915_priolist { int priority; }; +/** + * struct intel_engine_execlists - execlist submission queue and port state + * + * The struct intel_engine_execlists represents the combined logical state of + * driver and the hardware state for execlist mode of submission. + */ +struct intel_engine_execlists { + /** + * @irq_tasklet: softirq tasklet for bottom handler + */ + struct tasklet_struct irq_tasklet; + + /** + * @default_priolist: priority list for I915_PRIORITY_NORMAL + */ + struct i915_priolist default_priolist; + + /** + * @no_priolist: priority lists disabled + */ + bool no_priolist; + + /** + * @port: execlist port states + * + * For each hardware ELSP (ExecList Submission Port) we keep + * track of the last request and the number of times we submitted + * that port to hw. We then count the number of times the hw reports + * a context completion or preemption. As only one context can + * be active on hw, we limit resubmission of context to port[0]. This + * is called Lite Restore, of the context. + */ + struct execlist_port { + /** + * @request_count: combined request and submission count + */ + struct drm_i915_gem_request *request_count; +#define EXECLIST_COUNT_BITS 2 +#define port_request(p) ptr_mask_bits((p)->request_count, EXECLIST_COUNT_BITS) +#define port_count(p) ptr_unmask_bits((p)->request_count, EXECLIST_COUNT_BITS) +#define port_pack(rq, count) ptr_pack_bits(rq, count, EXECLIST_COUNT_BITS) +#define port_unpack(p, count) ptr_unpack_bits((p)->request_count, count, EXECLIST_COUNT_BITS) +#define port_set(p, packed) ((p)->request_count = (packed)) +#define port_isset(p) ((p)->request_count) +#define port_index(p, execlists) ((p) - (execlists)->port) + + /** + * @context_id: context ID for port + */ + GEM_DEBUG_DECL(u32 context_id); + +#define EXECLIST_MAX_PORTS 2 + } port[EXECLIST_MAX_PORTS]; + + /** + * @active: is the HW active? We consider the HW as active after + * submitting any context for execution and until we have seen the + * last context completion event. After that, we do not expect any + * more events until we submit, and so can park the HW. + * + * As we have a small number of different sources from which we feed + * the HW, we track the state of each inside a single bitfield. + */ + unsigned int active; +#define EXECLISTS_ACTIVE_USER 0 +#define EXECLISTS_ACTIVE_PREEMPT 1 + + /** + * @port_mask: number of execlist ports - 1 + */ + unsigned int port_mask; + + /** + * @queue: queue of requests, in priority lists + */ + struct rb_root queue; + + /** + * @first: leftmost level in priority @queue + */ + struct rb_node *first; + + /** + * @fw_domains: forcewake domains for irq tasklet + */ + unsigned int fw_domains; + + /** + * @csb_head: context status buffer head + */ + unsigned int csb_head; + + /** + * @csb_use_mmio: access csb through mmio, instead of hwsp + */ + bool csb_use_mmio; +}; + #define INTEL_ENGINE_CS_MAX_NAME 8 struct intel_engine_cs { @@ -306,6 +406,14 @@ struct intel_engine_cs { void (*schedule)(struct drm_i915_gem_request *request, int priority); + /* + * Cancel all requests on the hardware, or queued for execution. + * This should only cancel the ready requests that have been + * submitted to the engine (via the engine->submit_request callback). + * This is called when marking the device as wedged. + */ + void (*cancel_requests)(struct intel_engine_cs *engine); + /* Some chipsets are not quite as coherent as advertised and need * an expensive kick to force a true read of the up-to-date seqno. * However, the up-to-date seqno is not always required and the last @@ -372,25 +480,7 @@ struct intel_engine_cs { u32 *(*signal)(struct drm_i915_gem_request *req, u32 *cs); } semaphore; - /* Execlists */ - struct tasklet_struct irq_tasklet; - struct i915_priolist default_priolist; - bool no_priolist; - struct execlist_port { - struct drm_i915_gem_request *request_count; -#define EXECLIST_COUNT_BITS 2 -#define port_request(p) ptr_mask_bits((p)->request_count, EXECLIST_COUNT_BITS) -#define port_count(p) ptr_unmask_bits((p)->request_count, EXECLIST_COUNT_BITS) -#define port_pack(rq, count) ptr_pack_bits(rq, count, EXECLIST_COUNT_BITS) -#define port_unpack(p, count) ptr_unpack_bits((p)->request_count, count, EXECLIST_COUNT_BITS) -#define port_set(p, packed) ((p)->request_count = (packed)) -#define port_isset(p) ((p)->request_count) -#define port_index(p, e) ((p) - (e)->execlist_port) - GEM_DEBUG_DECL(u32 context_id); - } execlist_port[2]; - struct rb_root execlist_queue; - struct rb_node *execlist_first; - unsigned int fw_domains; + struct intel_engine_execlists execlists; /* Contexts are pinned whilst they are active on the GPU. The last * context executed remains active whilst the GPU is idle - the @@ -443,6 +533,46 @@ struct intel_engine_cs { u32 (*get_cmd_length_mask)(u32 cmd_header); }; +static inline void +execlists_set_active(struct intel_engine_execlists *execlists, + unsigned int bit) +{ + __set_bit(bit, (unsigned long *)&execlists->active); +} + +static inline void +execlists_clear_active(struct intel_engine_execlists *execlists, + unsigned int bit) +{ + __clear_bit(bit, (unsigned long *)&execlists->active); +} + +static inline bool +execlists_is_active(const struct intel_engine_execlists *execlists, + unsigned int bit) +{ + return test_bit(bit, (unsigned long *)&execlists->active); +} + +static inline unsigned int +execlists_num_ports(const struct intel_engine_execlists * const execlists) +{ + return execlists->port_mask + 1; +} + +static inline void +execlists_port_complete(struct intel_engine_execlists * const execlists, + struct execlist_port * const port) +{ + const unsigned int m = execlists->port_mask; + + GEM_BUG_ON(port_index(port, execlists) != 0); + GEM_BUG_ON(!execlists_is_active(execlists, EXECLISTS_ACTIVE_USER)); + + memmove(port, port + 1, m * sizeof(struct execlist_port)); + memset(port + m, 0, sizeof(struct execlist_port)); +} + static inline unsigned int intel_engine_flag(const struct intel_engine_cs *engine) { @@ -496,6 +626,10 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) #define I915_GEM_HWS_SCRATCH_INDEX 0x40 #define I915_GEM_HWS_SCRATCH_ADDR (I915_GEM_HWS_SCRATCH_INDEX << MI_STORE_DWORD_INDEX_SHIFT) +#define I915_HWS_CSB_BUF0_INDEX 0x10 +#define I915_HWS_CSB_WRITE_INDEX 0x1f +#define CNL_HWS_CSB_WRITE_INDEX 0x2f + struct intel_ring * intel_engine_create_ring(struct intel_engine_cs *engine, int size); int intel_ring_pin(struct intel_ring *ring, @@ -737,4 +871,6 @@ void intel_engines_reset_default_submission(struct drm_i915_private *i915); bool intel_engine_can_store_dword(struct intel_engine_cs *engine); +void intel_engine_dump(struct intel_engine_cs *engine, struct drm_printer *p); + #endif /* _INTEL_RINGBUFFER_H_ */ diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index a3bfb9f27e7a..8af286c63d3b 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -187,7 +187,7 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well; bool is_enabled; - if (dev_priv->pm.suspended) + if (dev_priv->runtime_pm.suspended) return false; is_enabled = true; @@ -368,7 +368,7 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv, { enum i915_power_well_id id = power_well->id; bool wait_fuses = power_well->hsw.has_fuses; - enum skl_power_gate pg; + enum skl_power_gate uninitialized_var(pg); u32 val; if (wait_fuses) { @@ -785,7 +785,7 @@ static void vlv_set_power_well(struct drm_i915_private *dev_priv, state = enable ? PUNIT_PWRGT_PWR_ON(power_well_id) : PUNIT_PWRGT_PWR_GATE(power_well_id); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); #define COND \ ((vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask) == state) @@ -806,7 +806,7 @@ static void vlv_set_power_well(struct drm_i915_private *dev_priv, #undef COND out: - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } static void vlv_power_well_enable(struct drm_i915_private *dev_priv, @@ -833,7 +833,7 @@ static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv, mask = PUNIT_PWRGT_MASK(power_well_id); ctrl = PUNIT_PWRGT_PWR_ON(power_well_id); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); state = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_STATUS) & mask; /* @@ -852,7 +852,7 @@ static bool vlv_power_well_enabled(struct drm_i915_private *dev_priv, ctrl = vlv_punit_read(dev_priv, PUNIT_REG_PWRGT_CTRL) & mask; WARN_ON(ctrl != state); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); return enabled; } @@ -1364,7 +1364,7 @@ static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv, bool enabled; u32 state, ctrl; - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); state = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe); /* @@ -1381,7 +1381,7 @@ static bool chv_pipe_power_well_enabled(struct drm_i915_private *dev_priv, ctrl = vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSC_MASK(pipe); WARN_ON(ctrl << 16 != state); - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); return enabled; } @@ -1396,7 +1396,7 @@ static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv, state = enable ? DP_SSS_PWR_ON(pipe) : DP_SSS_PWR_GATE(pipe); - mutex_lock(&dev_priv->rps.hw_lock); + mutex_lock(&dev_priv->pcu_lock); #define COND \ ((vlv_punit_read(dev_priv, PUNIT_REG_DSPFREQ) & DP_SSS_MASK(pipe)) == state) @@ -1417,7 +1417,7 @@ static void chv_set_pipe_power_well(struct drm_i915_private *dev_priv, #undef COND out: - mutex_unlock(&dev_priv->rps.hw_lock); + mutex_unlock(&dev_priv->pcu_lock); } static void chv_pipe_power_well_enable(struct drm_i915_private *dev_priv, @@ -2413,7 +2413,7 @@ static uint32_t get_allowed_dc_mask(const struct drm_i915_private *dev_priv, mask = 0; } - if (!i915.disable_power_well) + if (!i915_modparams.disable_power_well) max_dc = 0; if (enable_dc >= 0 && enable_dc <= max_dc) { @@ -2471,10 +2471,11 @@ int intel_power_domains_init(struct drm_i915_private *dev_priv) { struct i915_power_domains *power_domains = &dev_priv->power_domains; - i915.disable_power_well = sanitize_disable_power_well_option(dev_priv, - i915.disable_power_well); - dev_priv->csr.allowed_dc_mask = get_allowed_dc_mask(dev_priv, - i915.enable_dc); + i915_modparams.disable_power_well = + sanitize_disable_power_well_option(dev_priv, + i915_modparams.disable_power_well); + dev_priv->csr.allowed_dc_mask = + get_allowed_dc_mask(dev_priv, i915_modparams.enable_dc); BUILD_BUG_ON(POWER_DOMAIN_NUM > 64); @@ -2535,7 +2536,7 @@ void intel_power_domains_fini(struct drm_i915_private *dev_priv) intel_display_set_init_power(dev_priv, true); /* Remove the refcount we took to keep power well support disabled. */ - if (!i915.disable_power_well) + if (!i915_modparams.disable_power_well) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); /* @@ -2808,6 +2809,9 @@ static void cnl_display_core_init(struct drm_i915_private *dev_priv, bool resume /* 6. Enable DBUF */ gen9_dbuf_enable(dev_priv); + + if (resume && dev_priv->csr.dmc_payload) + intel_csr_load_program(dev_priv); } static void cnl_display_core_uninit(struct drm_i915_private *dev_priv) @@ -2995,7 +2999,7 @@ void intel_power_domains_init_hw(struct drm_i915_private *dev_priv, bool resume) /* For now, we need the power well to be always enabled. */ intel_display_set_init_power(dev_priv, true); /* Disable power support if the user asked so. */ - if (!i915.disable_power_well) + if (!i915_modparams.disable_power_well) intel_display_power_get(dev_priv, POWER_DOMAIN_INIT); intel_power_domains_sync_hw(dev_priv); power_domains->initializing = false; @@ -3014,7 +3018,7 @@ void intel_power_domains_suspend(struct drm_i915_private *dev_priv) * Even if power well support was disabled we still want to disable * power wells while we are system suspended. */ - if (!i915.disable_power_well) + if (!i915_modparams.disable_power_well) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT); if (IS_CANNONLAKE(dev_priv)) @@ -3124,7 +3128,7 @@ void intel_runtime_pm_get(struct drm_i915_private *dev_priv) ret = pm_runtime_get_sync(kdev); WARN_ONCE(ret < 0, "pm_runtime_get_sync() failed: %d\n", ret); - atomic_inc(&dev_priv->pm.wakeref_count); + atomic_inc(&dev_priv->runtime_pm.wakeref_count); assert_rpm_wakelock_held(dev_priv); } @@ -3158,7 +3162,7 @@ bool intel_runtime_pm_get_if_in_use(struct drm_i915_private *dev_priv) return false; } - atomic_inc(&dev_priv->pm.wakeref_count); + atomic_inc(&dev_priv->runtime_pm.wakeref_count); assert_rpm_wakelock_held(dev_priv); return true; @@ -3189,7 +3193,7 @@ void intel_runtime_pm_get_noresume(struct drm_i915_private *dev_priv) assert_rpm_wakelock_held(dev_priv); pm_runtime_get_noresume(kdev); - atomic_inc(&dev_priv->pm.wakeref_count); + atomic_inc(&dev_priv->runtime_pm.wakeref_count); } /** @@ -3206,7 +3210,7 @@ void intel_runtime_pm_put(struct drm_i915_private *dev_priv) struct device *kdev = &pdev->dev; assert_rpm_wakelock_held(dev_priv); - atomic_dec(&dev_priv->pm.wakeref_count); + atomic_dec(&dev_priv->runtime_pm.wakeref_count); pm_runtime_mark_last_busy(kdev); pm_runtime_put_autosuspend(kdev); diff --git a/drivers/gpu/drm/i915/intel_sideband.c b/drivers/gpu/drm/i915/intel_sideband.c index 7d971cb56116..75c872bb8cc9 100644 --- a/drivers/gpu/drm/i915/intel_sideband.c +++ b/drivers/gpu/drm/i915/intel_sideband.c @@ -81,7 +81,7 @@ u32 vlv_punit_read(struct drm_i915_private *dev_priv, u32 addr) { u32 val = 0; - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); mutex_lock(&dev_priv->sb_lock); vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, @@ -95,7 +95,7 @@ int vlv_punit_write(struct drm_i915_private *dev_priv, u32 addr, u32 val) { int err; - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); mutex_lock(&dev_priv->sb_lock); err = vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_PUNIT, @@ -125,7 +125,7 @@ u32 vlv_nc_read(struct drm_i915_private *dev_priv, u8 addr) { u32 val = 0; - WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); + WARN_ON(!mutex_is_locked(&dev_priv->pcu_lock)); mutex_lock(&dev_priv->sb_lock); vlv_sideband_rw(dev_priv, PCI_DEVFN(0, 0), IOSF_PORT_NC, diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index b0d6e3e28d07..4fcf80ca91dd 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -66,7 +66,13 @@ int intel_usecs_to_scanlines(const struct drm_display_mode *adjusted_mode, 1000 * adjusted_mode->crtc_htotal); } +/* FIXME: We should instead only take spinlocks once for the entire update + * instead of once per mmio. */ +#if IS_ENABLED(CONFIG_PROVE_LOCKING) +#define VBLANK_EVASION_TIME_US 250 +#else #define VBLANK_EVASION_TIME_US 100 +#endif /** * intel_pipe_update_start() - start update of a set of display registers @@ -224,7 +230,7 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) #endif } -static void +void skl_update_plane(struct intel_plane *plane, const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state) @@ -305,7 +311,7 @@ skl_update_plane(struct intel_plane *plane, spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } -static void +void skl_disable_plane(struct intel_plane *plane, struct intel_crtc *crtc) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); @@ -994,7 +1000,7 @@ int intel_sprite_set_colorkey(struct drm_device *dev, void *data, set->flags & I915_SET_COLORKEY_DESTINATION) return -EINVAL; - plane = drm_plane_find(dev, set->plane_id); + plane = drm_plane_find(dev, file_priv, set->plane_id); if (!plane || plane->type != DRM_PLANE_TYPE_OVERLAY) return -ENOENT; diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index 0cc999fa09c5..a79a7591b2cf 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c @@ -1385,7 +1385,7 @@ intel_tv_get_modes(struct drm_connector *connector) mode_ptr->vsync_end = mode_ptr->vsync_start + 1; mode_ptr->vtotal = vactive_s + 33; - tmp = (u64) tv_mode->refresh * mode_ptr->vtotal; + tmp = mul_u32_u32(tv_mode->refresh, mode_ptr->vtotal); tmp *= mode_ptr->htotal; tmp = div_u64(tmp, 1000000); mode_ptr->clock = (int) tmp; diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 0178ba42a0e5..25bd162f38d2 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c @@ -22,22 +22,9 @@ * */ -#include "i915_drv.h" #include "intel_uc.h" -#include <linux/firmware.h> - -/* Cleans up uC firmware by releasing the firmware GEM obj. - */ -static void __intel_uc_fw_fini(struct intel_uc_fw *uc_fw) -{ - struct drm_i915_gem_object *obj; - - obj = fetch_and_zero(&uc_fw->obj); - if (obj) - i915_gem_object_put(obj); - - uc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE; -} +#include "i915_drv.h" +#include "i915_guc_submission.h" /* Reset GuC providing us with fresh state for both GuC and HuC. */ @@ -63,234 +50,70 @@ static int __intel_uc_reset_hw(struct drm_i915_private *dev_priv) void intel_uc_sanitize_options(struct drm_i915_private *dev_priv) { if (!HAS_GUC(dev_priv)) { - if (i915.enable_guc_loading > 0 || - i915.enable_guc_submission > 0) + if (i915_modparams.enable_guc_loading > 0 || + i915_modparams.enable_guc_submission > 0) DRM_INFO("Ignoring GuC options, no hardware\n"); - i915.enable_guc_loading = 0; - i915.enable_guc_submission = 0; + i915_modparams.enable_guc_loading = 0; + i915_modparams.enable_guc_submission = 0; return; } /* A negative value means "use platform default" */ - if (i915.enable_guc_loading < 0) - i915.enable_guc_loading = HAS_GUC_UCODE(dev_priv); + if (i915_modparams.enable_guc_loading < 0) + i915_modparams.enable_guc_loading = HAS_GUC_UCODE(dev_priv); /* Verify firmware version */ - if (i915.enable_guc_loading) { + if (i915_modparams.enable_guc_loading) { if (HAS_HUC_UCODE(dev_priv)) intel_huc_select_fw(&dev_priv->huc); - if (intel_guc_select_fw(&dev_priv->guc)) - i915.enable_guc_loading = 0; + if (intel_guc_fw_select(&dev_priv->guc)) + i915_modparams.enable_guc_loading = 0; } /* Can't enable guc submission without guc loaded */ - if (!i915.enable_guc_loading) - i915.enable_guc_submission = 0; + if (!i915_modparams.enable_guc_loading) + i915_modparams.enable_guc_submission = 0; /* A negative value means "use platform default" */ - if (i915.enable_guc_submission < 0) - i915.enable_guc_submission = HAS_GUC_SCHED(dev_priv); -} - -static void gen8_guc_raise_irq(struct intel_guc *guc) -{ - struct drm_i915_private *dev_priv = guc_to_i915(guc); - - I915_WRITE(GUC_SEND_INTERRUPT, GUC_SEND_TRIGGER); + if (i915_modparams.enable_guc_submission < 0) + i915_modparams.enable_guc_submission = HAS_GUC_SCHED(dev_priv); } void intel_uc_init_early(struct drm_i915_private *dev_priv) { - struct intel_guc *guc = &dev_priv->guc; - - intel_guc_ct_init_early(&guc->ct); - - mutex_init(&guc->send_mutex); - guc->send = intel_guc_send_nop; - guc->notify = gen8_guc_raise_irq; -} - -static void fetch_uc_fw(struct drm_i915_private *dev_priv, - struct intel_uc_fw *uc_fw) -{ - struct pci_dev *pdev = dev_priv->drm.pdev; - struct drm_i915_gem_object *obj; - const struct firmware *fw = NULL; - struct uc_css_header *css; - size_t size; - int err; - - if (!uc_fw->path) - return; - - uc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING; - - DRM_DEBUG_DRIVER("before requesting firmware: uC fw fetch status %s\n", - intel_uc_fw_status_repr(uc_fw->fetch_status)); - - err = request_firmware(&fw, uc_fw->path, &pdev->dev); - if (err) - goto fail; - if (!fw) - goto fail; - - DRM_DEBUG_DRIVER("fetch uC fw from %s succeeded, fw %p\n", - uc_fw->path, fw); - - /* Check the size of the blob before examining buffer contents */ - if (fw->size < sizeof(struct uc_css_header)) { - DRM_NOTE("Firmware header is missing\n"); - goto fail; - } - - css = (struct uc_css_header *)fw->data; - - /* Firmware bits always start from header */ - uc_fw->header_offset = 0; - uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw - - css->key_size_dw - css->exponent_size_dw) * sizeof(u32); - - if (uc_fw->header_size != sizeof(struct uc_css_header)) { - DRM_NOTE("CSS header definition mismatch\n"); - goto fail; - } - - /* then, uCode */ - uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size; - uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); - - /* now RSA */ - if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) { - DRM_NOTE("RSA key size is bad\n"); - goto fail; - } - uc_fw->rsa_offset = uc_fw->ucode_offset + uc_fw->ucode_size; - uc_fw->rsa_size = css->key_size_dw * sizeof(u32); - - /* At least, it should have header, uCode and RSA. Size of all three. */ - size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size; - if (fw->size < size) { - DRM_NOTE("Missing firmware components\n"); - goto fail; - } - - /* - * The GuC firmware image has the version number embedded at a - * well-known offset within the firmware blob; note that major / minor - * version are TWO bytes each (i.e. u16), although all pointers and - * offsets are defined in terms of bytes (u8). - */ - switch (uc_fw->type) { - case INTEL_UC_FW_TYPE_GUC: - /* Header and uCode will be loaded to WOPCM. Size of the two. */ - size = uc_fw->header_size + uc_fw->ucode_size; - - /* Top 32k of WOPCM is reserved (8K stack + 24k RC6 context). */ - if (size > intel_guc_wopcm_size(dev_priv)) { - DRM_ERROR("Firmware is too large to fit in WOPCM\n"); - goto fail; - } - uc_fw->major_ver_found = css->guc.sw_version >> 16; - uc_fw->minor_ver_found = css->guc.sw_version & 0xFFFF; - break; - - case INTEL_UC_FW_TYPE_HUC: - uc_fw->major_ver_found = css->huc.sw_version >> 16; - uc_fw->minor_ver_found = css->huc.sw_version & 0xFFFF; - break; - - default: - DRM_ERROR("Unknown firmware type %d\n", uc_fw->type); - err = -ENOEXEC; - goto fail; - } - - if (uc_fw->major_ver_wanted == 0 && uc_fw->minor_ver_wanted == 0) { - DRM_NOTE("Skipping %s firmware version check\n", - intel_uc_fw_type_repr(uc_fw->type)); - } else if (uc_fw->major_ver_found != uc_fw->major_ver_wanted || - uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) { - DRM_NOTE("%s firmware version %d.%d, required %d.%d\n", - intel_uc_fw_type_repr(uc_fw->type), - uc_fw->major_ver_found, uc_fw->minor_ver_found, - uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted); - err = -ENOEXEC; - goto fail; - } - - DRM_DEBUG_DRIVER("firmware version %d.%d OK (minimum %d.%d)\n", - uc_fw->major_ver_found, uc_fw->minor_ver_found, - uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted); - - obj = i915_gem_object_create_from_data(dev_priv, fw->data, fw->size); - if (IS_ERR(obj)) { - err = PTR_ERR(obj); - goto fail; - } - - uc_fw->obj = obj; - uc_fw->size = fw->size; - - DRM_DEBUG_DRIVER("uC fw fetch status SUCCESS, obj %p\n", - uc_fw->obj); - - release_firmware(fw); - uc_fw->fetch_status = INTEL_UC_FIRMWARE_SUCCESS; - return; - -fail: - DRM_WARN("Failed to fetch valid uC firmware from %s (error %d)\n", - uc_fw->path, err); - DRM_DEBUG_DRIVER("uC fw fetch status FAIL; err %d, fw %p, obj %p\n", - err, fw, uc_fw->obj); - - release_firmware(fw); /* OK even if fw is NULL */ - uc_fw->fetch_status = INTEL_UC_FIRMWARE_FAIL; + intel_guc_init_early(&dev_priv->guc); } void intel_uc_init_fw(struct drm_i915_private *dev_priv) { - fetch_uc_fw(dev_priv, &dev_priv->huc.fw); - fetch_uc_fw(dev_priv, &dev_priv->guc.fw); + intel_uc_fw_fetch(dev_priv, &dev_priv->huc.fw); + intel_uc_fw_fetch(dev_priv, &dev_priv->guc.fw); } void intel_uc_fini_fw(struct drm_i915_private *dev_priv) { - __intel_uc_fw_fini(&dev_priv->guc.fw); - __intel_uc_fw_fini(&dev_priv->huc.fw); + intel_uc_fw_fini(&dev_priv->guc.fw); + intel_uc_fw_fini(&dev_priv->huc.fw); } -static inline i915_reg_t guc_send_reg(struct intel_guc *guc, u32 i) -{ - GEM_BUG_ON(!guc->send_regs.base); - GEM_BUG_ON(!guc->send_regs.count); - GEM_BUG_ON(i >= guc->send_regs.count); - - return _MMIO(guc->send_regs.base + 4 * i); -} - -static void guc_init_send_regs(struct intel_guc *guc) +/** + * intel_uc_init_mmio - setup uC MMIO access + * + * @dev_priv: device private + * + * Setup minimal state necessary for MMIO accesses later in the + * initialization sequence. + */ +void intel_uc_init_mmio(struct drm_i915_private *dev_priv) { - struct drm_i915_private *dev_priv = guc_to_i915(guc); - enum forcewake_domains fw_domains = 0; - unsigned int i; - - guc->send_regs.base = i915_mmio_reg_offset(SOFT_SCRATCH(0)); - guc->send_regs.count = SOFT_SCRATCH_COUNT - 1; - - for (i = 0; i < guc->send_regs.count; i++) { - fw_domains |= intel_uncore_forcewake_for_reg(dev_priv, - guc_send_reg(guc, i), - FW_REG_READ | FW_REG_WRITE); - } - guc->send_regs.fw_domains = fw_domains; + intel_guc_init_send_regs(&dev_priv->guc); } static void guc_capture_load_err_log(struct intel_guc *guc) { - if (!guc->log.vma || i915.guc_log_level < 0) + if (!guc->log.vma || i915_modparams.guc_log_level < 0) return; if (!guc->load_err_log) @@ -309,8 +132,6 @@ static int guc_enable_communication(struct intel_guc *guc) { struct drm_i915_private *dev_priv = guc_to_i915(guc); - guc_init_send_regs(guc); - if (HAS_GUC_CT(dev_priv)) return intel_guc_enable_ct(guc); @@ -333,7 +154,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) struct intel_guc *guc = &dev_priv->guc; int ret, attempts; - if (!i915.enable_guc_loading) + if (!i915_modparams.enable_guc_loading) return 0; guc_disable_communication(guc); @@ -342,7 +163,7 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) /* We need to notify the guc whenever we change the GGTT */ i915_ggtt_enable_guc(dev_priv); - if (i915.enable_guc_submission) { + if (i915_modparams.enable_guc_submission) { /* * This is stuff we need to have available at fw load time * if we are planning to enable submission later @@ -374,7 +195,8 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) goto err_submission; intel_huc_init_hw(&dev_priv->huc); - ret = intel_guc_init_hw(&dev_priv->guc); + intel_guc_init_params(guc); + ret = intel_guc_fw_upload(guc); if (ret == 0 || ret != -EAGAIN) break; @@ -390,9 +212,9 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) if (ret) goto err_log_capture; - intel_guc_auth_huc(dev_priv); - if (i915.enable_guc_submission) { - if (i915.guc_log_level >= 0) + intel_huc_auth(&dev_priv->huc); + if (i915_modparams.enable_guc_submission) { + if (i915_modparams.guc_log_level >= 0) gen9_enable_guc_interrupts(dev_priv); ret = i915_guc_submission_enable(dev_priv); @@ -400,6 +222,12 @@ int intel_uc_init_hw(struct drm_i915_private *dev_priv) goto err_interrupts; } + dev_info(dev_priv->drm.dev, "GuC %s (firmware %s [version %u.%u])\n", + i915_modparams.enable_guc_submission ? "submission enabled" : + "loaded", + guc->fw.path, + guc->fw.major_ver_found, guc->fw.minor_ver_found); + return 0; /* @@ -417,24 +245,26 @@ err_interrupts: err_log_capture: guc_capture_load_err_log(guc); err_submission: - if (i915.enable_guc_submission) + if (i915_modparams.enable_guc_submission) i915_guc_submission_fini(dev_priv); err_guc: i915_ggtt_disable_guc(dev_priv); - DRM_ERROR("GuC init failed\n"); - if (i915.enable_guc_loading > 1 || i915.enable_guc_submission > 1) + if (i915_modparams.enable_guc_loading > 1 || + i915_modparams.enable_guc_submission > 1) { + DRM_ERROR("GuC init failed. Firmware loading disabled.\n"); ret = -EIO; - else + } else { + DRM_NOTE("GuC init failed. Firmware loading disabled.\n"); ret = 0; + } - if (i915.enable_guc_submission) { - i915.enable_guc_submission = 0; + if (i915_modparams.enable_guc_submission) { + i915_modparams.enable_guc_submission = 0; DRM_NOTE("Falling back from GuC submission to execlist mode\n"); } - i915.enable_guc_loading = 0; - DRM_NOTE("GuC firmware loading disabled\n"); + i915_modparams.enable_guc_loading = 0; return ret; } @@ -443,97 +273,18 @@ void intel_uc_fini_hw(struct drm_i915_private *dev_priv) { guc_free_load_err_log(&dev_priv->guc); - if (!i915.enable_guc_loading) + if (!i915_modparams.enable_guc_loading) return; - if (i915.enable_guc_submission) + if (i915_modparams.enable_guc_submission) i915_guc_submission_disable(dev_priv); guc_disable_communication(&dev_priv->guc); - if (i915.enable_guc_submission) { + if (i915_modparams.enable_guc_submission) { gen9_disable_guc_interrupts(dev_priv); i915_guc_submission_fini(dev_priv); } i915_ggtt_disable_guc(dev_priv); } - -int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len) -{ - WARN(1, "Unexpected send: action=%#x\n", *action); - return -ENODEV; -} - -/* - * This function implements the MMIO based host to GuC interface. - */ -int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len) -{ - struct drm_i915_private *dev_priv = guc_to_i915(guc); - u32 status; - int i; - int ret; - - GEM_BUG_ON(!len); - GEM_BUG_ON(len > guc->send_regs.count); - - /* If CT is available, we expect to use MMIO only during init/fini */ - GEM_BUG_ON(HAS_GUC_CT(dev_priv) && - *action != INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER && - *action != INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER); - - mutex_lock(&guc->send_mutex); - intel_uncore_forcewake_get(dev_priv, guc->send_regs.fw_domains); - - for (i = 0; i < len; i++) - I915_WRITE(guc_send_reg(guc, i), action[i]); - - POSTING_READ(guc_send_reg(guc, i - 1)); - - intel_guc_notify(guc); - - /* - * No GuC command should ever take longer than 10ms. - * Fast commands should still complete in 10us. - */ - ret = __intel_wait_for_register_fw(dev_priv, - guc_send_reg(guc, 0), - INTEL_GUC_RECV_MASK, - INTEL_GUC_RECV_MASK, - 10, 10, &status); - if (status != INTEL_GUC_STATUS_SUCCESS) { - /* - * Either the GuC explicitly returned an error (which - * we convert to -EIO here) or no response at all was - * received within the timeout limit (-ETIMEDOUT) - */ - if (ret != -ETIMEDOUT) - ret = -EIO; - - DRM_WARN("INTEL_GUC_SEND: Action 0x%X failed;" - " ret=%d status=0x%08X response=0x%08X\n", - action[0], ret, status, I915_READ(SOFT_SCRATCH(15))); - } - - intel_uncore_forcewake_put(dev_priv, guc->send_regs.fw_domains); - mutex_unlock(&guc->send_mutex); - - return ret; -} - -int intel_guc_sample_forcewake(struct intel_guc *guc) -{ - struct drm_i915_private *dev_priv = guc_to_i915(guc); - u32 action[2]; - - action[0] = INTEL_GUC_ACTION_SAMPLE_FORCEWAKE; - /* WaRsDisableCoarsePowerGating:skl,bxt */ - if (!intel_enable_rc6() || NEEDS_WaRsDisableCoarsePowerGating(dev_priv)) - action[1] = 0; - else - /* bit 0 and 1 are for Render and Media domain separately */ - action[1] = GUC_FORCEWAKE_RENDER | GUC_FORCEWAKE_MEDIA; - - return intel_guc_send(guc, action, ARRAY_SIZE(action)); -} diff --git a/drivers/gpu/drm/i915/intel_uc.h b/drivers/gpu/drm/i915/intel_uc.h index 22ae52b17b0f..e18d3bb02088 100644 --- a/drivers/gpu/drm/i915/intel_uc.h +++ b/drivers/gpu/drm/i915/intel_uc.h @@ -24,256 +24,15 @@ #ifndef _INTEL_UC_H_ #define _INTEL_UC_H_ -#include "intel_guc_fwif.h" -#include "i915_guc_reg.h" -#include "intel_ringbuffer.h" -#include "intel_guc_ct.h" -#include "i915_vma.h" +#include "intel_guc.h" +#include "intel_huc.h" -struct drm_i915_gem_request; - -/* - * This structure primarily describes the GEM object shared with the GuC. - * The specs sometimes refer to this object as a "GuC context", but we use - * the term "client" to avoid confusion with hardware contexts. This - * GEM object is held for the entire lifetime of our interaction with - * the GuC, being allocated before the GuC is loaded with its firmware. - * Because there's no way to update the address used by the GuC after - * initialisation, the shared object must stay pinned into the GGTT as - * long as the GuC is in use. We also keep the first page (only) mapped - * into kernel address space, as it includes shared data that must be - * updated on every request submission. - * - * The single GEM object described here is actually made up of several - * separate areas, as far as the GuC is concerned. The first page (kept - * kmap'd) includes the "process descriptor" which holds sequence data for - * the doorbell, and one cacheline which actually *is* the doorbell; a - * write to this will "ring the doorbell" (i.e. send an interrupt to the - * GuC). The subsequent pages of the client object constitute the work - * queue (a circular array of work items), again described in the process - * descriptor. Work queue pages are mapped momentarily as required. - * - * We also keep a few statistics on failures. Ideally, these should all - * be zero! - * no_wq_space: times that the submission pre-check found no space was - * available in the work queue (note, the queue is shared, - * not per-engine). It is OK for this to be nonzero, but - * it should not be huge! - * b_fail: failed to ring the doorbell. This should never happen, unless - * somehow the hardware misbehaves, or maybe if the GuC firmware - * crashes? We probably need to reset the GPU to recover. - * retcode: errno from last guc_submit() - */ -struct i915_guc_client { - struct i915_vma *vma; - void *vaddr; - struct i915_gem_context *owner; - struct intel_guc *guc; - - uint32_t engines; /* bitmap of (host) engine ids */ - uint32_t priority; - u32 stage_id; - uint32_t proc_desc_offset; - - u16 doorbell_id; - unsigned long doorbell_offset; - u32 doorbell_cookie; - - spinlock_t wq_lock; - uint32_t wq_offset; - uint32_t wq_size; - uint32_t wq_tail; - uint32_t wq_rsvd; - uint32_t no_wq_space; - - /* Per-engine counts of GuC submissions */ - uint64_t submissions[I915_NUM_ENGINES]; -}; - -enum intel_uc_fw_status { - INTEL_UC_FIRMWARE_FAIL = -1, - INTEL_UC_FIRMWARE_NONE = 0, - INTEL_UC_FIRMWARE_PENDING, - INTEL_UC_FIRMWARE_SUCCESS -}; - -/* User-friendly representation of an enum */ -static inline -const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status) -{ - switch (status) { - case INTEL_UC_FIRMWARE_FAIL: - return "FAIL"; - case INTEL_UC_FIRMWARE_NONE: - return "NONE"; - case INTEL_UC_FIRMWARE_PENDING: - return "PENDING"; - case INTEL_UC_FIRMWARE_SUCCESS: - return "SUCCESS"; - } - return "<invalid>"; -} - -enum intel_uc_fw_type { - INTEL_UC_FW_TYPE_GUC, - INTEL_UC_FW_TYPE_HUC -}; - -/* User-friendly representation of an enum */ -static inline const char *intel_uc_fw_type_repr(enum intel_uc_fw_type type) -{ - switch (type) { - case INTEL_UC_FW_TYPE_GUC: - return "GuC"; - case INTEL_UC_FW_TYPE_HUC: - return "HuC"; - } - return "uC"; -} - -/* - * This structure encapsulates all the data needed during the process - * of fetching, caching, and loading the firmware image into the GuC. - */ -struct intel_uc_fw { - const char *path; - size_t size; - struct drm_i915_gem_object *obj; - enum intel_uc_fw_status fetch_status; - enum intel_uc_fw_status load_status; - - uint16_t major_ver_wanted; - uint16_t minor_ver_wanted; - uint16_t major_ver_found; - uint16_t minor_ver_found; - - enum intel_uc_fw_type type; - uint32_t header_size; - uint32_t header_offset; - uint32_t rsa_size; - uint32_t rsa_offset; - uint32_t ucode_size; - uint32_t ucode_offset; -}; - -struct intel_guc_log { - uint32_t flags; - struct i915_vma *vma; - /* The runtime stuff gets created only when GuC logging gets enabled */ - struct { - void *buf_addr; - struct workqueue_struct *flush_wq; - struct work_struct flush_work; - struct rchan *relay_chan; - } runtime; - /* logging related stats */ - u32 capture_miss_count; - u32 flush_interrupt_count; - u32 prev_overflow_count[GUC_MAX_LOG_BUFFER]; - u32 total_overflow_count[GUC_MAX_LOG_BUFFER]; - u32 flush_count[GUC_MAX_LOG_BUFFER]; -}; - -struct intel_guc { - struct intel_uc_fw fw; - struct intel_guc_log log; - struct intel_guc_ct ct; - - /* Log snapshot if GuC errors during load */ - struct drm_i915_gem_object *load_err_log; - - /* intel_guc_recv interrupt related state */ - bool interrupts_enabled; - - struct i915_vma *ads_vma; - struct i915_vma *stage_desc_pool; - void *stage_desc_pool_vaddr; - struct ida stage_ids; - - struct i915_guc_client *execbuf_client; - - DECLARE_BITMAP(doorbell_bitmap, GUC_NUM_DOORBELLS); - uint32_t db_cacheline; /* Cyclic counter mod pagesize */ - - /* GuC's FW specific registers used in MMIO send */ - struct { - u32 base; - unsigned int count; - enum forcewake_domains fw_domains; - } send_regs; - - /* To serialize the intel_guc_send actions */ - struct mutex send_mutex; - - /* GuC's FW specific send function */ - int (*send)(struct intel_guc *guc, const u32 *data, u32 len); - - /* GuC's FW specific notify function */ - void (*notify)(struct intel_guc *guc); -}; - -struct intel_huc { - /* Generic uC firmware management */ - struct intel_uc_fw fw; - - /* HuC-specific additions */ -}; - -/* intel_uc.c */ void intel_uc_sanitize_options(struct drm_i915_private *dev_priv); void intel_uc_init_early(struct drm_i915_private *dev_priv); +void intel_uc_init_mmio(struct drm_i915_private *dev_priv); void intel_uc_init_fw(struct drm_i915_private *dev_priv); void intel_uc_fini_fw(struct drm_i915_private *dev_priv); int intel_uc_init_hw(struct drm_i915_private *dev_priv); void intel_uc_fini_hw(struct drm_i915_private *dev_priv); -int intel_guc_sample_forcewake(struct intel_guc *guc); -int intel_guc_send_nop(struct intel_guc *guc, const u32 *action, u32 len); -int intel_guc_send_mmio(struct intel_guc *guc, const u32 *action, u32 len); - -static inline int intel_guc_send(struct intel_guc *guc, const u32 *action, u32 len) -{ - return guc->send(guc, action, len); -} - -static inline void intel_guc_notify(struct intel_guc *guc) -{ - guc->notify(guc); -} - -/* intel_guc_loader.c */ -int intel_guc_select_fw(struct intel_guc *guc); -int intel_guc_init_hw(struct intel_guc *guc); -int intel_guc_suspend(struct drm_i915_private *dev_priv); -int intel_guc_resume(struct drm_i915_private *dev_priv); -u32 intel_guc_wopcm_size(struct drm_i915_private *dev_priv); - -/* i915_guc_submission.c */ -int i915_guc_submission_init(struct drm_i915_private *dev_priv); -int i915_guc_submission_enable(struct drm_i915_private *dev_priv); -int i915_guc_wq_reserve(struct drm_i915_gem_request *rq); -void i915_guc_wq_unreserve(struct drm_i915_gem_request *request); -void i915_guc_submission_disable(struct drm_i915_private *dev_priv); -void i915_guc_submission_fini(struct drm_i915_private *dev_priv); -struct i915_vma *intel_guc_allocate_vma(struct intel_guc *guc, u32 size); - -/* intel_guc_log.c */ -int intel_guc_log_create(struct intel_guc *guc); -void intel_guc_log_destroy(struct intel_guc *guc); -int i915_guc_log_control(struct drm_i915_private *dev_priv, u64 control_val); -void i915_guc_log_register(struct drm_i915_private *dev_priv); -void i915_guc_log_unregister(struct drm_i915_private *dev_priv); - -static inline u32 guc_ggtt_offset(struct i915_vma *vma) -{ - u32 offset = i915_ggtt_offset(vma); - GEM_BUG_ON(offset < GUC_WOPCM_TOP); - GEM_BUG_ON(range_overflows_t(u64, offset, vma->size, GUC_GGTT_TOP)); - return offset; -} - -/* intel_huc.c */ -void intel_huc_select_fw(struct intel_huc *huc); -void intel_huc_init_hw(struct intel_huc *huc); -void intel_guc_auth_huc(struct drm_i915_private *dev_priv); #endif diff --git a/drivers/gpu/drm/i915/intel_uc_fw.c b/drivers/gpu/drm/i915/intel_uc_fw.c new file mode 100644 index 000000000000..973888e94cba --- /dev/null +++ b/drivers/gpu/drm/i915/intel_uc_fw.c @@ -0,0 +1,318 @@ +/* + * Copyright © 2016-2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION 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 <linux/firmware.h> +#include <drm/drm_print.h> + +#include "intel_uc_fw.h" +#include "i915_drv.h" + +/** + * intel_uc_fw_fetch - fetch uC firmware + * + * @dev_priv: device private + * @uc_fw: uC firmware + * + * Fetch uC firmware into GEM obj. + */ +void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, + struct intel_uc_fw *uc_fw) +{ + struct pci_dev *pdev = dev_priv->drm.pdev; + struct drm_i915_gem_object *obj; + const struct firmware *fw = NULL; + struct uc_css_header *css; + size_t size; + int err; + + DRM_DEBUG_DRIVER("%s fw fetch %s\n", + intel_uc_fw_type_repr(uc_fw->type), uc_fw->path); + + if (!uc_fw->path) + return; + + uc_fw->fetch_status = INTEL_UC_FIRMWARE_PENDING; + DRM_DEBUG_DRIVER("%s fw fetch %s\n", + intel_uc_fw_type_repr(uc_fw->type), + intel_uc_fw_status_repr(uc_fw->fetch_status)); + + err = request_firmware(&fw, uc_fw->path, &pdev->dev); + if (err) { + DRM_DEBUG_DRIVER("%s fw request_firmware err=%d\n", + intel_uc_fw_type_repr(uc_fw->type), err); + goto fail; + } + + DRM_DEBUG_DRIVER("%s fw size %zu ptr %p\n", + intel_uc_fw_type_repr(uc_fw->type), fw->size, fw); + + /* Check the size of the blob before examining buffer contents */ + if (fw->size < sizeof(struct uc_css_header)) { + DRM_WARN("%s: Unexpected firmware size (%zu, min %zu)\n", + intel_uc_fw_type_repr(uc_fw->type), + fw->size, sizeof(struct uc_css_header)); + err = -ENODATA; + goto fail; + } + + css = (struct uc_css_header *)fw->data; + + /* Firmware bits always start from header */ + uc_fw->header_offset = 0; + uc_fw->header_size = (css->header_size_dw - css->modulus_size_dw - + css->key_size_dw - css->exponent_size_dw) * + sizeof(u32); + + if (uc_fw->header_size != sizeof(struct uc_css_header)) { + DRM_WARN("%s: Mismatched firmware header definition\n", + intel_uc_fw_type_repr(uc_fw->type)); + err = -ENOEXEC; + goto fail; + } + + /* then, uCode */ + uc_fw->ucode_offset = uc_fw->header_offset + uc_fw->header_size; + uc_fw->ucode_size = (css->size_dw - css->header_size_dw) * sizeof(u32); + + /* Header and uCode will be loaded to WOPCM */ + size = uc_fw->header_size + uc_fw->ucode_size; + if (size > intel_guc_wopcm_size(dev_priv)) { + DRM_WARN("%s: Firmware is too large to fit in WOPCM\n", + intel_uc_fw_type_repr(uc_fw->type)); + err = -E2BIG; + goto fail; + } + + /* now RSA */ + if (css->key_size_dw != UOS_RSA_SCRATCH_MAX_COUNT) { + DRM_WARN("%s: Mismatched firmware RSA key size (%u)\n", + intel_uc_fw_type_repr(uc_fw->type), css->key_size_dw); + err = -ENOEXEC; + goto fail; + } + uc_fw->rsa_offset = uc_fw->ucode_offset + uc_fw->ucode_size; + uc_fw->rsa_size = css->key_size_dw * sizeof(u32); + + /* At least, it should have header, uCode and RSA. Size of all three. */ + size = uc_fw->header_size + uc_fw->ucode_size + uc_fw->rsa_size; + if (fw->size < size) { + DRM_WARN("%s: Truncated firmware (%zu, expected %zu)\n", + intel_uc_fw_type_repr(uc_fw->type), fw->size, size); + err = -ENOEXEC; + goto fail; + } + + /* + * The GuC firmware image has the version number embedded at a + * well-known offset within the firmware blob; note that major / minor + * version are TWO bytes each (i.e. u16), although all pointers and + * offsets are defined in terms of bytes (u8). + */ + switch (uc_fw->type) { + case INTEL_UC_FW_TYPE_GUC: + uc_fw->major_ver_found = css->guc.sw_version >> 16; + uc_fw->minor_ver_found = css->guc.sw_version & 0xFFFF; + break; + + case INTEL_UC_FW_TYPE_HUC: + uc_fw->major_ver_found = css->huc.sw_version >> 16; + uc_fw->minor_ver_found = css->huc.sw_version & 0xFFFF; + break; + + default: + MISSING_CASE(uc_fw->type); + break; + } + + DRM_DEBUG_DRIVER("%s fw version %u.%u (wanted %u.%u)\n", + intel_uc_fw_type_repr(uc_fw->type), + uc_fw->major_ver_found, uc_fw->minor_ver_found, + uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted); + + if (uc_fw->major_ver_wanted == 0 && uc_fw->minor_ver_wanted == 0) { + DRM_NOTE("%s: Skipping firmware version check\n", + intel_uc_fw_type_repr(uc_fw->type)); + } else if (uc_fw->major_ver_found != uc_fw->major_ver_wanted || + uc_fw->minor_ver_found < uc_fw->minor_ver_wanted) { + DRM_NOTE("%s: Wrong firmware version (%u.%u, required %u.%u)\n", + intel_uc_fw_type_repr(uc_fw->type), + uc_fw->major_ver_found, uc_fw->minor_ver_found, + uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted); + err = -ENOEXEC; + goto fail; + } + + obj = i915_gem_object_create_from_data(dev_priv, fw->data, fw->size); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + DRM_DEBUG_DRIVER("%s fw object_create err=%d\n", + intel_uc_fw_type_repr(uc_fw->type), err); + goto fail; + } + + uc_fw->obj = obj; + uc_fw->size = fw->size; + uc_fw->fetch_status = INTEL_UC_FIRMWARE_SUCCESS; + DRM_DEBUG_DRIVER("%s fw fetch %s\n", + intel_uc_fw_type_repr(uc_fw->type), + intel_uc_fw_status_repr(uc_fw->fetch_status)); + + release_firmware(fw); + return; + +fail: + uc_fw->fetch_status = INTEL_UC_FIRMWARE_FAIL; + DRM_DEBUG_DRIVER("%s fw fetch %s\n", + intel_uc_fw_type_repr(uc_fw->type), + intel_uc_fw_status_repr(uc_fw->fetch_status)); + + DRM_WARN("%s: Failed to fetch firmware %s (error %d)\n", + intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err); + DRM_INFO("%s: Firmware can be downloaded from %s\n", + intel_uc_fw_type_repr(uc_fw->type), INTEL_UC_FIRMWARE_URL); + + release_firmware(fw); /* OK even if fw is NULL */ +} + +/** + * intel_uc_fw_upload - load uC firmware using custom loader + * + * @uc_fw: uC firmware + * @loader: custom uC firmware loader function + * + * Loads uC firmware using custom loader and updates internal flags. + */ +int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, + int (*xfer)(struct intel_uc_fw *uc_fw, + struct i915_vma *vma)) +{ + struct i915_vma *vma; + int err; + + DRM_DEBUG_DRIVER("%s fw load %s\n", + intel_uc_fw_type_repr(uc_fw->type), uc_fw->path); + + if (uc_fw->fetch_status != INTEL_UC_FIRMWARE_SUCCESS) + return -EIO; + + uc_fw->load_status = INTEL_UC_FIRMWARE_PENDING; + DRM_DEBUG_DRIVER("%s fw load %s\n", + intel_uc_fw_type_repr(uc_fw->type), + intel_uc_fw_status_repr(uc_fw->load_status)); + + /* Pin object with firmware */ + err = i915_gem_object_set_to_gtt_domain(uc_fw->obj, false); + if (err) { + DRM_DEBUG_DRIVER("%s fw set-domain err=%d\n", + intel_uc_fw_type_repr(uc_fw->type), err); + goto fail; + } + + vma = i915_gem_object_ggtt_pin(uc_fw->obj, NULL, 0, 0, + PIN_OFFSET_BIAS | GUC_WOPCM_TOP); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + DRM_DEBUG_DRIVER("%s fw ggtt-pin err=%d\n", + intel_uc_fw_type_repr(uc_fw->type), err); + goto fail; + } + + /* Call custom loader */ + err = xfer(uc_fw, vma); + + /* + * We keep the object pages for reuse during resume. But we can unpin it + * now that DMA has completed, so it doesn't continue to take up space. + */ + i915_vma_unpin(vma); + + if (err) + goto fail; + + uc_fw->load_status = INTEL_UC_FIRMWARE_SUCCESS; + DRM_DEBUG_DRIVER("%s fw load %s\n", + intel_uc_fw_type_repr(uc_fw->type), + intel_uc_fw_status_repr(uc_fw->load_status)); + + DRM_INFO("%s: Loaded firmware %s (version %u.%u)\n", + intel_uc_fw_type_repr(uc_fw->type), + uc_fw->path, + uc_fw->major_ver_found, uc_fw->minor_ver_found); + + return 0; + +fail: + uc_fw->load_status = INTEL_UC_FIRMWARE_FAIL; + DRM_DEBUG_DRIVER("%s fw load %s\n", + intel_uc_fw_type_repr(uc_fw->type), + intel_uc_fw_status_repr(uc_fw->load_status)); + + DRM_WARN("%s: Failed to load firmware %s (error %d)\n", + intel_uc_fw_type_repr(uc_fw->type), uc_fw->path, err); + + return err; +} + +/** + * intel_uc_fw_fini - cleanup uC firmware + * + * @uc_fw: uC firmware + * + * Cleans up uC firmware by releasing the firmware GEM obj. + */ +void intel_uc_fw_fini(struct intel_uc_fw *uc_fw) +{ + struct drm_i915_gem_object *obj; + + obj = fetch_and_zero(&uc_fw->obj); + if (obj) + i915_gem_object_put(obj); + + uc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE; +} + +/** + * intel_uc_fw_dump - dump information about uC firmware + * @uc_fw: uC firmware + * @p: the &drm_printer + * + * Pretty printer for uC firmware. + */ +void intel_uc_fw_dump(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); + drm_printf(p, "\tstatus: fetch %s, load %s\n", + intel_uc_fw_status_repr(uc_fw->fetch_status), + intel_uc_fw_status_repr(uc_fw->load_status)); + drm_printf(p, "\tversion: wanted %u.%u, found %u.%u\n", + uc_fw->major_ver_wanted, uc_fw->minor_ver_wanted, + uc_fw->major_ver_found, uc_fw->minor_ver_found); + drm_printf(p, "\theader: offset %u, size %u\n", + uc_fw->header_offset, uc_fw->header_size); + drm_printf(p, "\tuCode: offset %u, size %u\n", + uc_fw->ucode_offset, uc_fw->ucode_size); + drm_printf(p, "\tRSA: offset %u, size %u\n", + uc_fw->rsa_offset, uc_fw->rsa_size); +} diff --git a/drivers/gpu/drm/i915/intel_uc_fw.h b/drivers/gpu/drm/i915/intel_uc_fw.h new file mode 100644 index 000000000000..132903669391 --- /dev/null +++ b/drivers/gpu/drm/i915/intel_uc_fw.h @@ -0,0 +1,121 @@ +/* + * Copyright © 2014-2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + * + */ + +#ifndef _INTEL_UC_FW_H_ +#define _INTEL_UC_FW_H_ + +struct drm_printer; +struct drm_i915_private; +struct i915_vma; + +/* Home of GuC, HuC and DMC firmwares */ +#define INTEL_UC_FIRMWARE_URL "https://01.org/linuxgraphics/downloads/firmware" + +enum intel_uc_fw_status { + INTEL_UC_FIRMWARE_FAIL = -1, + INTEL_UC_FIRMWARE_NONE = 0, + INTEL_UC_FIRMWARE_PENDING, + INTEL_UC_FIRMWARE_SUCCESS +}; + +enum intel_uc_fw_type { + INTEL_UC_FW_TYPE_GUC, + INTEL_UC_FW_TYPE_HUC +}; + +/* + * This structure encapsulates all the data needed during the process + * of fetching, caching, and loading the firmware image into the uC. + */ +struct intel_uc_fw { + const char *path; + size_t size; + struct drm_i915_gem_object *obj; + enum intel_uc_fw_status fetch_status; + enum intel_uc_fw_status load_status; + + /* + * The firmware build process will generate a version header file with major and + * minor version defined. The versions are built into CSS header of firmware. + * i915 kernel driver set the minimal firmware version required per platform. + */ + u16 major_ver_wanted; + u16 minor_ver_wanted; + u16 major_ver_found; + u16 minor_ver_found; + + enum intel_uc_fw_type type; + u32 header_size; + u32 header_offset; + u32 rsa_size; + u32 rsa_offset; + u32 ucode_size; + u32 ucode_offset; +}; + +static inline +const char *intel_uc_fw_status_repr(enum intel_uc_fw_status status) +{ + switch (status) { + case INTEL_UC_FIRMWARE_FAIL: + return "FAIL"; + case INTEL_UC_FIRMWARE_NONE: + return "NONE"; + case INTEL_UC_FIRMWARE_PENDING: + return "PENDING"; + case INTEL_UC_FIRMWARE_SUCCESS: + return "SUCCESS"; + } + return "<invalid>"; +} + +static inline const char *intel_uc_fw_type_repr(enum intel_uc_fw_type type) +{ + switch (type) { + case INTEL_UC_FW_TYPE_GUC: + return "GuC"; + case INTEL_UC_FW_TYPE_HUC: + return "HuC"; + } + return "uC"; +} + +static inline +void intel_uc_fw_init(struct intel_uc_fw *uc_fw, enum intel_uc_fw_type type) +{ + uc_fw->path = NULL; + uc_fw->fetch_status = INTEL_UC_FIRMWARE_NONE; + uc_fw->load_status = INTEL_UC_FIRMWARE_NONE; + uc_fw->type = type; +} + +void intel_uc_fw_fetch(struct drm_i915_private *dev_priv, + struct intel_uc_fw *uc_fw); +int intel_uc_fw_upload(struct intel_uc_fw *uc_fw, + int (*xfer)(struct intel_uc_fw *uc_fw, + struct i915_vma *vma)); +void intel_uc_fw_fini(struct intel_uc_fw *uc_fw); +void intel_uc_fw_dump(struct intel_uc_fw *uc_fw, struct drm_printer *p); + +#endif diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index 0529af7cfbb8..20e3c65c0999 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -436,7 +436,8 @@ void intel_uncore_resume_early(struct drm_i915_private *dev_priv) void intel_uncore_sanitize(struct drm_i915_private *dev_priv) { - i915.enable_rc6 = sanitize_rc6_option(dev_priv, i915.enable_rc6); + i915_modparams.enable_rc6 = + sanitize_rc6_option(dev_priv, i915_modparams.enable_rc6); /* BIOS often leaves RC6 enabled, but disable it for hw init */ intel_sanitize_gt_powersave(dev_priv); @@ -490,6 +491,57 @@ void intel_uncore_forcewake_get(struct drm_i915_private *dev_priv, } /** + * intel_uncore_forcewake_user_get - claim forcewake on behalf of userspace + * @dev_priv: i915 device instance + * + * This function is a wrapper around intel_uncore_forcewake_get() to acquire + * the GT powerwell and in the process disable our debugging for the + * duration of userspace's bypass. + */ +void intel_uncore_forcewake_user_get(struct drm_i915_private *dev_priv) +{ + spin_lock_irq(&dev_priv->uncore.lock); + if (!dev_priv->uncore.user_forcewake.count++) { + intel_uncore_forcewake_get__locked(dev_priv, FORCEWAKE_ALL); + + /* Save and disable mmio debugging for the user bypass */ + dev_priv->uncore.user_forcewake.saved_mmio_check = + dev_priv->uncore.unclaimed_mmio_check; + dev_priv->uncore.user_forcewake.saved_mmio_debug = + i915_modparams.mmio_debug; + + dev_priv->uncore.unclaimed_mmio_check = 0; + i915_modparams.mmio_debug = 0; + } + spin_unlock_irq(&dev_priv->uncore.lock); +} + +/** + * intel_uncore_forcewake_user_put - release forcewake on behalf of userspace + * @dev_priv: i915 device instance + * + * This function complements intel_uncore_forcewake_user_get() and releases + * the GT powerwell taken on behalf of the userspace bypass. + */ +void intel_uncore_forcewake_user_put(struct drm_i915_private *dev_priv) +{ + spin_lock_irq(&dev_priv->uncore.lock); + if (!--dev_priv->uncore.user_forcewake.count) { + if (intel_uncore_unclaimed_mmio(dev_priv)) + dev_info(dev_priv->drm.dev, + "Invalid mmio detected during user access\n"); + + dev_priv->uncore.unclaimed_mmio_check = + dev_priv->uncore.user_forcewake.saved_mmio_check; + i915_modparams.mmio_debug = + dev_priv->uncore.user_forcewake.saved_mmio_debug; + + intel_uncore_forcewake_put__locked(dev_priv, FORCEWAKE_ALL); + } + spin_unlock_irq(&dev_priv->uncore.lock); +} + +/** * intel_uncore_forcewake_get__locked - grab forcewake domain references * @dev_priv: i915 device instance * @fw_domains: forcewake domains to get reference on @@ -574,7 +626,23 @@ void assert_forcewakes_inactive(struct drm_i915_private *dev_priv) if (!dev_priv->uncore.funcs.force_wake_get) return; - WARN_ON(dev_priv->uncore.fw_domains_active); + WARN(dev_priv->uncore.fw_domains_active, + "Expected all fw_domains to be inactive, but %08x are still on\n", + dev_priv->uncore.fw_domains_active); +} + +void assert_forcewakes_active(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains) +{ + if (!dev_priv->uncore.funcs.force_wake_get) + return; + + assert_rpm_wakelock_held(dev_priv); + + fw_domains &= dev_priv->uncore.fw_domains; + WARN(fw_domains & ~dev_priv->uncore.fw_domains_active, + "Expected %08x fw_domains to be active, but %08x are off\n", + fw_domains, fw_domains & ~dev_priv->uncore.fw_domains_active); } /* We give fast paths for the really cool registers */ @@ -790,7 +858,8 @@ __unclaimed_reg_debug(struct drm_i915_private *dev_priv, "Unclaimed %s register 0x%x\n", read ? "read from" : "write to", i915_mmio_reg_offset(reg))) - i915.mmio_debug--; /* Only report the first N failures */ + /* Only report the first N failures */ + i915_modparams.mmio_debug--; } static inline void @@ -799,7 +868,7 @@ unclaimed_reg_debug(struct drm_i915_private *dev_priv, const bool read, const bool before) { - if (likely(!i915.mmio_debug)) + if (likely(!i915_modparams.mmio_debug)) return; __unclaimed_reg_debug(dev_priv, reg, read, before); @@ -1241,102 +1310,104 @@ void intel_uncore_fini(struct drm_i915_private *dev_priv) intel_uncore_forcewake_reset(dev_priv, false); } -#define GEN_RANGE(l, h) GENMASK((h) - 1, (l) - 1) - -static const struct register_whitelist { - i915_reg_t offset_ldw, offset_udw; - uint32_t size; - /* supported gens, 0x10 for 4, 0x30 for 4 and 5, etc. */ - uint32_t gen_bitmask; -} whitelist[] = { - { .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE), - .offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE), - .size = 8, .gen_bitmask = GEN_RANGE(4, 10) }, -}; +static const struct reg_whitelist { + i915_reg_t offset_ldw; + i915_reg_t offset_udw; + u16 gen_mask; + u8 size; +} reg_read_whitelist[] = { { + .offset_ldw = RING_TIMESTAMP(RENDER_RING_BASE), + .offset_udw = RING_TIMESTAMP_UDW(RENDER_RING_BASE), + .gen_mask = INTEL_GEN_MASK(4, 10), + .size = 8 +} }; int i915_reg_read_ioctl(struct drm_device *dev, void *data, struct drm_file *file) { struct drm_i915_private *dev_priv = to_i915(dev); struct drm_i915_reg_read *reg = data; - struct register_whitelist const *entry = whitelist; - unsigned size; - i915_reg_t offset_ldw, offset_udw; - int i, ret = 0; - - for (i = 0; i < ARRAY_SIZE(whitelist); i++, entry++) { - if (i915_mmio_reg_offset(entry->offset_ldw) == (reg->offset & -entry->size) && - (INTEL_INFO(dev_priv)->gen_mask & entry->gen_bitmask)) + struct reg_whitelist const *entry; + unsigned int flags; + int remain; + int ret = 0; + + entry = reg_read_whitelist; + remain = ARRAY_SIZE(reg_read_whitelist); + while (remain) { + u32 entry_offset = i915_mmio_reg_offset(entry->offset_ldw); + + GEM_BUG_ON(!is_power_of_2(entry->size)); + GEM_BUG_ON(entry->size > 8); + GEM_BUG_ON(entry_offset & (entry->size - 1)); + + if (INTEL_INFO(dev_priv)->gen_mask & entry->gen_mask && + entry_offset == (reg->offset & -entry->size)) break; + entry++; + remain--; } - if (i == ARRAY_SIZE(whitelist)) + if (!remain) return -EINVAL; - /* We use the low bits to encode extra flags as the register should - * be naturally aligned (and those that are not so aligned merely - * limit the available flags for that register). - */ - offset_ldw = entry->offset_ldw; - offset_udw = entry->offset_udw; - size = entry->size; - size |= reg->offset ^ i915_mmio_reg_offset(offset_ldw); + flags = reg->offset & (entry->size - 1); intel_runtime_pm_get(dev_priv); - - switch (size) { - case 8 | 1: - reg->val = I915_READ64_2x32(offset_ldw, offset_udw); - break; - case 8: - reg->val = I915_READ64(offset_ldw); - break; - case 4: - reg->val = I915_READ(offset_ldw); - break; - case 2: - reg->val = I915_READ16(offset_ldw); - break; - case 1: - reg->val = I915_READ8(offset_ldw); - break; - default: + if (entry->size == 8 && flags == I915_REG_READ_8B_WA) + reg->val = I915_READ64_2x32(entry->offset_ldw, + entry->offset_udw); + else if (entry->size == 8 && flags == 0) + reg->val = I915_READ64(entry->offset_ldw); + else if (entry->size == 4 && flags == 0) + reg->val = I915_READ(entry->offset_ldw); + else if (entry->size == 2 && flags == 0) + reg->val = I915_READ16(entry->offset_ldw); + else if (entry->size == 1 && flags == 0) + reg->val = I915_READ8(entry->offset_ldw); + else ret = -EINVAL; - goto out; - } - -out: intel_runtime_pm_put(dev_priv); + return ret; } -static void gen3_stop_rings(struct drm_i915_private *dev_priv) +static void gen3_stop_engine(struct intel_engine_cs *engine) +{ + struct drm_i915_private *dev_priv = engine->i915; + const u32 base = engine->mmio_base; + const i915_reg_t mode = RING_MI_MODE(base); + + I915_WRITE_FW(mode, _MASKED_BIT_ENABLE(STOP_RING)); + if (intel_wait_for_register_fw(dev_priv, + mode, + MODE_IDLE, + MODE_IDLE, + 500)) + DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", + engine->name); + + I915_WRITE_FW(RING_CTL(base), 0); + I915_WRITE_FW(RING_HEAD(base), 0); + I915_WRITE_FW(RING_TAIL(base), 0); + + /* Check acts as a post */ + if (I915_READ_FW(RING_HEAD(base)) != 0) + DRM_DEBUG_DRIVER("%s: ring head not parked\n", + engine->name); +} + +static void i915_stop_engines(struct drm_i915_private *dev_priv, + unsigned engine_mask) { struct intel_engine_cs *engine; enum intel_engine_id id; - for_each_engine(engine, dev_priv, id) { - const u32 base = engine->mmio_base; - const i915_reg_t mode = RING_MI_MODE(base); - - I915_WRITE_FW(mode, _MASKED_BIT_ENABLE(STOP_RING)); - if (intel_wait_for_register_fw(dev_priv, - mode, - MODE_IDLE, - MODE_IDLE, - 500)) - DRM_DEBUG_DRIVER("%s: timed out on STOP_RING\n", - engine->name); - - I915_WRITE_FW(RING_CTL(base), 0); - I915_WRITE_FW(RING_HEAD(base), 0); - I915_WRITE_FW(RING_TAIL(base), 0); - - /* Check acts as a post */ - if (I915_READ_FW(RING_HEAD(base)) != 0) - DRM_DEBUG_DRIVER("%s: ring head not parked\n", - engine->name); - } + if (INTEL_GEN(dev_priv) < 3) + return; + + for_each_engine_masked(engine, dev_priv, engine_mask, id) + gen3_stop_engine(engine); } static bool i915_reset_complete(struct pci_dev *pdev) @@ -1371,9 +1442,6 @@ static int g33_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) { struct pci_dev *pdev = dev_priv->drm.pdev; - /* Stop engines before we reset; see g4x_do_reset() below for why. */ - gen3_stop_rings(dev_priv); - pci_write_config_byte(pdev, I915_GDRST, GRDOM_RESET_ENABLE); return wait_for(g4x_reset_complete(pdev), 500); } @@ -1388,12 +1456,6 @@ static int g4x_do_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) I915_READ(VDECCLK_GATE_D) | VCP_UNIT_CLOCK_GATE_DISABLE); POSTING_READ(VDECCLK_GATE_D); - /* We stop engines, otherwise we might get failed reset and a - * dead gpu (on elk). - * WaMediaResetMainRingCleanup:ctg,elk (presumably) - */ - gen3_stop_rings(dev_priv); - pci_write_config_byte(pdev, I915_GDRST, GRDOM_MEDIA | GRDOM_RESET_ENABLE); ret = wait_for(g4x_reset_complete(pdev), 500); @@ -1662,7 +1724,7 @@ typedef int (*reset_func)(struct drm_i915_private *, unsigned engine_mask); static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv) { - if (!i915.reset) + if (!i915_modparams.reset) return NULL; if (INTEL_INFO(dev_priv)->gen >= 8) @@ -1683,22 +1745,34 @@ static reset_func intel_get_gpu_reset(struct drm_i915_private *dev_priv) int intel_gpu_reset(struct drm_i915_private *dev_priv, unsigned engine_mask) { - reset_func reset; + reset_func reset = intel_get_gpu_reset(dev_priv); int retry; int ret; might_sleep(); - reset = intel_get_gpu_reset(dev_priv); - if (reset == NULL) - return -ENODEV; - /* If the power well sleeps during the reset, the reset * request may be dropped and never completes (causing -EIO). */ intel_uncore_forcewake_get(dev_priv, FORCEWAKE_ALL); for (retry = 0; retry < 3; retry++) { - ret = reset(dev_priv, engine_mask); + + /* We stop engines, otherwise we might get failed reset and a + * dead gpu (on elk). Also as modern gpu as kbl can suffer + * from system hang if batchbuffer is progressing when + * the reset is issued, regardless of READY_TO_RESET ack. + * Thus assume it is best to stop engines on all gens + * where we have a gpu reset. + * + * WaMediaResetMainRingCleanup:ctg,elk (presumably) + * + * FIXME: Wa for more modern gens needs to be validated + */ + i915_stop_engines(dev_priv, engine_mask); + + ret = -ENODEV; + if (reset) + ret = reset(dev_priv, engine_mask); if (ret != -ETIMEDOUT) break; @@ -1722,7 +1796,7 @@ bool intel_has_reset_engine(struct drm_i915_private *dev_priv) { return (dev_priv->info.has_reset_engine && !dev_priv->guc.execbuf_client && - i915.reset >= 2); + i915_modparams.reset >= 2); } int intel_guc_reset(struct drm_i915_private *dev_priv) @@ -1747,7 +1821,7 @@ bool intel_uncore_unclaimed_mmio(struct drm_i915_private *dev_priv) bool intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) { - if (unlikely(i915.mmio_debug || + if (unlikely(i915_modparams.mmio_debug || dev_priv->uncore.unclaimed_mmio_check <= 0)) return false; @@ -1755,7 +1829,7 @@ intel_uncore_arm_unclaimed_mmio_detection(struct drm_i915_private *dev_priv) DRM_DEBUG("Unclaimed register detected, " "enabling oneshot unclaimed register reporting. " "Please use i915.mmio_debug=N for more information.\n"); - i915.mmio_debug++; + i915_modparams.mmio_debug++; dev_priv->uncore.unclaimed_mmio_check--; return true; } diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index 5f90278da461..582771251b57 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -25,6 +25,12 @@ #ifndef __INTEL_UNCORE_H__ #define __INTEL_UNCORE_H__ +#include <linux/spinlock.h> +#include <linux/notifier.h> +#include <linux/hrtimer.h> + +#include "i915_reg.h" + struct drm_i915_private; enum forcewake_domain_id { @@ -102,6 +108,13 @@ struct intel_uncore { i915_reg_t reg_ack; } fw_domain[FW_DOMAIN_ID_COUNT]; + struct { + unsigned int count; + + int saved_mmio_check; + int saved_mmio_debug; + } user_forcewake; + int unclaimed_mmio_check; }; @@ -124,6 +137,8 @@ void intel_uncore_resume_early(struct drm_i915_private *dev_priv); u64 intel_uncore_edram_size(struct drm_i915_private *dev_priv); void assert_forcewakes_inactive(struct drm_i915_private *dev_priv); +void assert_forcewakes_active(struct drm_i915_private *dev_priv, + enum forcewake_domains fw_domains); const char *intel_uncore_forcewake_domain_to_str(const enum forcewake_domain_id id); enum forcewake_domains @@ -144,6 +159,9 @@ void intel_uncore_forcewake_get__locked(struct drm_i915_private *dev_priv, void intel_uncore_forcewake_put__locked(struct drm_i915_private *dev_priv, enum forcewake_domains domains); +void intel_uncore_forcewake_user_get(struct drm_i915_private *dev_priv); +void intel_uncore_forcewake_user_put(struct drm_i915_private *dev_priv); + int intel_wait_for_register(struct drm_i915_private *dev_priv, i915_reg_t reg, u32 mask, diff --git a/drivers/gpu/drm/i915/intel_vbt_defs.h b/drivers/gpu/drm/i915/intel_vbt_defs.h index 404569c9fdfc..f225c288a121 100644 --- a/drivers/gpu/drm/i915/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/intel_vbt_defs.h @@ -306,6 +306,14 @@ struct bdb_general_features { #define LEGACY_CHILD_DEVICE_CONFIG_SIZE 33 +/* DDC Bus DDI Type 155+ */ +enum vbt_gmbus_ddi { + DDC_BUS_DDI_B = 0x1, + DDC_BUS_DDI_C, + DDC_BUS_DDI_D, + DDC_BUS_DDI_F, +}; + /* * The child device config, aka the display device data structure, provides a * description of a port and its configuration on the platform. diff --git a/drivers/gpu/drm/i915/selftests/huge_gem_object.c b/drivers/gpu/drm/i915/selftests/huge_gem_object.c index c5c7e8efbdd3..a2632df39173 100644 --- a/drivers/gpu/drm/i915/selftests/huge_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/huge_gem_object.c @@ -37,8 +37,7 @@ static void huge_free_pages(struct drm_i915_gem_object *obj, kfree(pages); } -static struct sg_table * -huge_get_pages(struct drm_i915_gem_object *obj) +static int huge_get_pages(struct drm_i915_gem_object *obj) { #define GFP (GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY) const unsigned long nreal = obj->scratch / PAGE_SIZE; @@ -49,11 +48,11 @@ huge_get_pages(struct drm_i915_gem_object *obj) pages = kmalloc(sizeof(*pages), GFP); if (!pages) - return ERR_PTR(-ENOMEM); + return -ENOMEM; if (sg_alloc_table(pages, npages, GFP)) { kfree(pages); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } sg = pages->sgl; @@ -81,11 +80,14 @@ huge_get_pages(struct drm_i915_gem_object *obj) if (i915_gem_gtt_prepare_pages(obj, pages)) goto err; - return pages; + __i915_gem_object_set_pages(obj, pages, PAGE_SIZE); + + return 0; err: huge_free_pages(obj, pages); - return ERR_PTR(-ENOMEM); + + return -ENOMEM; #undef GFP } diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c new file mode 100644 index 000000000000..5cc8101bb2b1 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -0,0 +1,1734 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION 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 "../i915_selftest.h" + +#include <linux/prime_numbers.h> + +#include "mock_drm.h" + +static const unsigned int page_sizes[] = { + I915_GTT_PAGE_SIZE_2M, + I915_GTT_PAGE_SIZE_64K, + I915_GTT_PAGE_SIZE_4K, +}; + +static unsigned int get_largest_page_size(struct drm_i915_private *i915, + u64 rem) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(page_sizes); ++i) { + unsigned int page_size = page_sizes[i]; + + if (HAS_PAGE_SIZES(i915, page_size) && rem >= page_size) + return page_size; + } + + return 0; +} + +static void huge_pages_free_pages(struct sg_table *st) +{ + struct scatterlist *sg; + + for (sg = st->sgl; sg; sg = __sg_next(sg)) { + if (sg_page(sg)) + __free_pages(sg_page(sg), get_order(sg->length)); + } + + sg_free_table(st); + kfree(st); +} + +static int get_huge_pages(struct drm_i915_gem_object *obj) +{ +#define GFP (GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY) + unsigned int page_mask = obj->mm.page_mask; + struct sg_table *st; + struct scatterlist *sg; + unsigned int sg_page_sizes; + u64 rem; + + st = kmalloc(sizeof(*st), GFP); + if (!st) + return -ENOMEM; + + if (sg_alloc_table(st, obj->base.size >> PAGE_SHIFT, GFP)) { + kfree(st); + return -ENOMEM; + } + + rem = obj->base.size; + sg = st->sgl; + st->nents = 0; + sg_page_sizes = 0; + + /* + * Our goal here is simple, we want to greedily fill the object from + * largest to smallest page-size, while ensuring that we use *every* + * page-size as per the given page-mask. + */ + do { + unsigned int bit = ilog2(page_mask); + unsigned int page_size = BIT(bit); + int order = get_order(page_size); + + do { + struct page *page; + + GEM_BUG_ON(order >= MAX_ORDER); + page = alloc_pages(GFP | __GFP_ZERO, order); + if (!page) + goto err; + + sg_set_page(sg, page, page_size, 0); + sg_page_sizes |= page_size; + st->nents++; + + rem -= page_size; + if (!rem) { + sg_mark_end(sg); + break; + } + + sg = __sg_next(sg); + } while ((rem - ((page_size-1) & page_mask)) >= page_size); + + page_mask &= (page_size-1); + } while (page_mask); + + if (i915_gem_gtt_prepare_pages(obj, st)) + goto err; + + obj->mm.madv = I915_MADV_DONTNEED; + + GEM_BUG_ON(sg_page_sizes != obj->mm.page_mask); + __i915_gem_object_set_pages(obj, st, sg_page_sizes); + + return 0; + +err: + sg_set_page(sg, NULL, 0, 0); + sg_mark_end(sg); + huge_pages_free_pages(st); + + return -ENOMEM; +} + +static void put_huge_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) +{ + i915_gem_gtt_finish_pages(obj, pages); + huge_pages_free_pages(pages); + + obj->mm.dirty = false; + obj->mm.madv = I915_MADV_WILLNEED; +} + +static const struct drm_i915_gem_object_ops huge_page_ops = { + .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE | + I915_GEM_OBJECT_IS_SHRINKABLE, + .get_pages = get_huge_pages, + .put_pages = put_huge_pages, +}; + +static struct drm_i915_gem_object * +huge_pages_object(struct drm_i915_private *i915, + u64 size, + unsigned int page_mask) +{ + struct drm_i915_gem_object *obj; + + GEM_BUG_ON(!size); + GEM_BUG_ON(!IS_ALIGNED(size, BIT(__ffs(page_mask)))); + + if (size >> PAGE_SHIFT > INT_MAX) + return ERR_PTR(-E2BIG); + + if (overflows_type(size, obj->base.size)) + return ERR_PTR(-E2BIG); + + obj = i915_gem_object_alloc(i915); + if (!obj) + return ERR_PTR(-ENOMEM); + + drm_gem_private_object_init(&i915->drm, &obj->base, size); + i915_gem_object_init(obj, &huge_page_ops); + + obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->cache_level = I915_CACHE_NONE; + + obj->mm.page_mask = page_mask; + + return obj; +} + +static int fake_get_huge_pages(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + const u64 max_len = rounddown_pow_of_two(UINT_MAX); + struct sg_table *st; + struct scatterlist *sg; + unsigned int sg_page_sizes; + u64 rem; + + st = kmalloc(sizeof(*st), GFP); + if (!st) + return -ENOMEM; + + if (sg_alloc_table(st, obj->base.size >> PAGE_SHIFT, GFP)) { + kfree(st); + return -ENOMEM; + } + + /* Use optimal page sized chunks to fill in the sg table */ + rem = obj->base.size; + sg = st->sgl; + st->nents = 0; + sg_page_sizes = 0; + do { + unsigned int page_size = get_largest_page_size(i915, rem); + unsigned int len = min(page_size * div_u64(rem, page_size), + max_len); + + GEM_BUG_ON(!page_size); + + sg->offset = 0; + sg->length = len; + sg_dma_len(sg) = len; + sg_dma_address(sg) = page_size; + + sg_page_sizes |= len; + + st->nents++; + + rem -= len; + if (!rem) { + sg_mark_end(sg); + break; + } + + sg = sg_next(sg); + } while (1); + + obj->mm.madv = I915_MADV_DONTNEED; + + __i915_gem_object_set_pages(obj, st, sg_page_sizes); + + return 0; +} + +static int fake_get_huge_pages_single(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct sg_table *st; + struct scatterlist *sg; + unsigned int page_size; + + st = kmalloc(sizeof(*st), GFP); + if (!st) + return -ENOMEM; + + if (sg_alloc_table(st, 1, GFP)) { + kfree(st); + return -ENOMEM; + } + + sg = st->sgl; + st->nents = 1; + + page_size = get_largest_page_size(i915, obj->base.size); + GEM_BUG_ON(!page_size); + + sg->offset = 0; + sg->length = obj->base.size; + sg_dma_len(sg) = obj->base.size; + sg_dma_address(sg) = page_size; + + obj->mm.madv = I915_MADV_DONTNEED; + + __i915_gem_object_set_pages(obj, st, sg->length); + + return 0; +#undef GFP +} + +static void fake_free_huge_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) +{ + sg_free_table(pages); + kfree(pages); +} + +static void fake_put_huge_pages(struct drm_i915_gem_object *obj, + struct sg_table *pages) +{ + fake_free_huge_pages(obj, pages); + obj->mm.dirty = false; + obj->mm.madv = I915_MADV_WILLNEED; +} + +static const struct drm_i915_gem_object_ops fake_ops = { + .flags = I915_GEM_OBJECT_IS_SHRINKABLE, + .get_pages = fake_get_huge_pages, + .put_pages = fake_put_huge_pages, +}; + +static const struct drm_i915_gem_object_ops fake_ops_single = { + .flags = I915_GEM_OBJECT_IS_SHRINKABLE, + .get_pages = fake_get_huge_pages_single, + .put_pages = fake_put_huge_pages, +}; + +static struct drm_i915_gem_object * +fake_huge_pages_object(struct drm_i915_private *i915, u64 size, bool single) +{ + struct drm_i915_gem_object *obj; + + GEM_BUG_ON(!size); + GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_PAGE_SIZE)); + + if (size >> PAGE_SHIFT > UINT_MAX) + return ERR_PTR(-E2BIG); + + if (overflows_type(size, obj->base.size)) + return ERR_PTR(-E2BIG); + + obj = i915_gem_object_alloc(i915); + if (!obj) + return ERR_PTR(-ENOMEM); + + drm_gem_private_object_init(&i915->drm, &obj->base, size); + + if (single) + i915_gem_object_init(obj, &fake_ops_single); + else + i915_gem_object_init(obj, &fake_ops); + + obj->base.write_domain = I915_GEM_DOMAIN_CPU; + obj->base.read_domains = I915_GEM_DOMAIN_CPU; + obj->cache_level = I915_CACHE_NONE; + + return obj; +} + +static int igt_check_page_sizes(struct i915_vma *vma) +{ + struct drm_i915_private *i915 = to_i915(vma->obj->base.dev); + unsigned int supported = INTEL_INFO(i915)->page_sizes; + struct drm_i915_gem_object *obj = vma->obj; + int err = 0; + + if (!HAS_PAGE_SIZES(i915, vma->page_sizes.sg)) { + pr_err("unsupported page_sizes.sg=%u, supported=%u\n", + vma->page_sizes.sg & ~supported, supported); + err = -EINVAL; + } + + if (!HAS_PAGE_SIZES(i915, vma->page_sizes.gtt)) { + pr_err("unsupported page_sizes.gtt=%u, supported=%u\n", + vma->page_sizes.gtt & ~supported, supported); + err = -EINVAL; + } + + if (vma->page_sizes.phys != obj->mm.page_sizes.phys) { + pr_err("vma->page_sizes.phys(%u) != obj->mm.page_sizes.phys(%u)\n", + vma->page_sizes.phys, obj->mm.page_sizes.phys); + err = -EINVAL; + } + + if (vma->page_sizes.sg != obj->mm.page_sizes.sg) { + pr_err("vma->page_sizes.sg(%u) != obj->mm.page_sizes.sg(%u)\n", + vma->page_sizes.sg, obj->mm.page_sizes.sg); + err = -EINVAL; + } + + if (obj->mm.page_sizes.gtt) { + pr_err("obj->page_sizes.gtt(%u) should never be set\n", + obj->mm.page_sizes.gtt); + err = -EINVAL; + } + + return err; +} + +static int igt_mock_exhaust_device_supported_pages(void *arg) +{ + struct i915_hw_ppgtt *ppgtt = arg; + struct drm_i915_private *i915 = ppgtt->base.i915; + unsigned int saved_mask = INTEL_INFO(i915)->page_sizes; + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + int i, j, single; + int err; + + /* + * Sanity check creating objects with every valid page support + * combination for our mock device. + */ + + for (i = 1; i < BIT(ARRAY_SIZE(page_sizes)); i++) { + unsigned int combination = 0; + + for (j = 0; j < ARRAY_SIZE(page_sizes); j++) { + if (i & BIT(j)) + combination |= page_sizes[j]; + } + + mkwrite_device_info(i915)->page_sizes = combination; + + for (single = 0; single <= 1; ++single) { + obj = fake_huge_pages_object(i915, combination, !!single); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out_device; + } + + if (obj->base.size != combination) { + pr_err("obj->base.size=%zu, expected=%u\n", + obj->base.size, combination); + err = -EINVAL; + goto out_put; + } + + vma = i915_vma_instance(obj, &ppgtt->base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_put; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + goto out_close; + + err = igt_check_page_sizes(vma); + + if (vma->page_sizes.sg != combination) { + pr_err("page_sizes.sg=%u, expected=%u\n", + vma->page_sizes.sg, combination); + err = -EINVAL; + } + + i915_vma_unpin(vma); + i915_vma_close(vma); + + i915_gem_object_put(obj); + + if (err) + goto out_device; + } + } + + goto out_device; + +out_close: + i915_vma_close(vma); +out_put: + i915_gem_object_put(obj); +out_device: + mkwrite_device_info(i915)->page_sizes = saved_mask; + + return err; +} + +static int igt_mock_ppgtt_misaligned_dma(void *arg) +{ + struct i915_hw_ppgtt *ppgtt = arg; + struct drm_i915_private *i915 = ppgtt->base.i915; + unsigned long supported = INTEL_INFO(i915)->page_sizes; + struct drm_i915_gem_object *obj; + int bit; + int err; + + /* + * Sanity check dma misalignment for huge pages -- the dma addresses we + * insert into the paging structures need to always respect the page + * size alignment. + */ + + bit = ilog2(I915_GTT_PAGE_SIZE_64K); + + for_each_set_bit_from(bit, &supported, + ilog2(I915_GTT_MAX_PAGE_SIZE) + 1) { + IGT_TIMEOUT(end_time); + unsigned int page_size = BIT(bit); + unsigned int flags = PIN_USER | PIN_OFFSET_FIXED; + unsigned int offset; + unsigned int size = + round_up(page_size, I915_GTT_PAGE_SIZE_2M) << 1; + struct i915_vma *vma; + + obj = fake_huge_pages_object(i915, size, true); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + if (obj->base.size != size) { + pr_err("obj->base.size=%zu, expected=%u\n", + obj->base.size, size); + err = -EINVAL; + goto out_put; + } + + err = i915_gem_object_pin_pages(obj); + if (err) + goto out_put; + + /* Force the page size for this object */ + obj->mm.page_sizes.sg = page_size; + + vma = i915_vma_instance(obj, &ppgtt->base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_unpin; + } + + err = i915_vma_pin(vma, 0, 0, flags); + if (err) { + i915_vma_close(vma); + goto out_unpin; + } + + + err = igt_check_page_sizes(vma); + + if (vma->page_sizes.gtt != page_size) { + pr_err("page_sizes.gtt=%u, expected %u\n", + vma->page_sizes.gtt, page_size); + err = -EINVAL; + } + + i915_vma_unpin(vma); + + if (err) { + i915_vma_close(vma); + goto out_unpin; + } + + /* + * Try all the other valid offsets until the next + * boundary -- should always fall back to using 4K + * pages. + */ + for (offset = 4096; offset < page_size; offset += 4096) { + err = i915_vma_unbind(vma); + if (err) { + i915_vma_close(vma); + goto out_unpin; + } + + err = i915_vma_pin(vma, 0, 0, flags | offset); + if (err) { + i915_vma_close(vma); + goto out_unpin; + } + + err = igt_check_page_sizes(vma); + + if (vma->page_sizes.gtt != I915_GTT_PAGE_SIZE_4K) { + pr_err("page_sizes.gtt=%u, expected %lu\n", + vma->page_sizes.gtt, I915_GTT_PAGE_SIZE_4K); + err = -EINVAL; + } + + i915_vma_unpin(vma); + + if (err) { + i915_vma_close(vma); + goto out_unpin; + } + + if (igt_timeout(end_time, + "%s timed out at offset %x with page-size %x\n", + __func__, offset, page_size)) + break; + } + + i915_vma_close(vma); + + i915_gem_object_unpin_pages(obj); + i915_gem_object_put(obj); + } + + return 0; + +out_unpin: + i915_gem_object_unpin_pages(obj); +out_put: + i915_gem_object_put(obj); + + return err; +} + +static void close_object_list(struct list_head *objects, + struct i915_hw_ppgtt *ppgtt) +{ + struct drm_i915_gem_object *obj, *on; + + list_for_each_entry_safe(obj, on, objects, st_link) { + struct i915_vma *vma; + + vma = i915_vma_instance(obj, &ppgtt->base, NULL); + if (!IS_ERR(vma)) + i915_vma_close(vma); + + list_del(&obj->st_link); + i915_gem_object_unpin_pages(obj); + i915_gem_object_put(obj); + } +} + +static int igt_mock_ppgtt_huge_fill(void *arg) +{ + struct i915_hw_ppgtt *ppgtt = arg; + struct drm_i915_private *i915 = ppgtt->base.i915; + unsigned long max_pages = ppgtt->base.total >> PAGE_SHIFT; + unsigned long page_num; + bool single = false; + LIST_HEAD(objects); + IGT_TIMEOUT(end_time); + int err = -ENODEV; + + for_each_prime_number_from(page_num, 1, max_pages) { + struct drm_i915_gem_object *obj; + u64 size = page_num << PAGE_SHIFT; + struct i915_vma *vma; + unsigned int expected_gtt = 0; + int i; + + obj = fake_huge_pages_object(i915, size, single); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + break; + } + + if (obj->base.size != size) { + pr_err("obj->base.size=%zd, expected=%llu\n", + obj->base.size, size); + i915_gem_object_put(obj); + err = -EINVAL; + break; + } + + err = i915_gem_object_pin_pages(obj); + if (err) { + i915_gem_object_put(obj); + break; + } + + list_add(&obj->st_link, &objects); + + vma = i915_vma_instance(obj, &ppgtt->base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + break; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + break; + + err = igt_check_page_sizes(vma); + if (err) { + i915_vma_unpin(vma); + break; + } + + /* + * Figure out the expected gtt page size knowing that we go from + * largest to smallest page size sg chunks, and that we align to + * the largest page size. + */ + for (i = 0; i < ARRAY_SIZE(page_sizes); ++i) { + unsigned int page_size = page_sizes[i]; + + if (HAS_PAGE_SIZES(i915, page_size) && + size >= page_size) { + expected_gtt |= page_size; + size &= page_size-1; + } + } + + GEM_BUG_ON(!expected_gtt); + GEM_BUG_ON(size); + + if (expected_gtt & I915_GTT_PAGE_SIZE_4K) + expected_gtt &= ~I915_GTT_PAGE_SIZE_64K; + + i915_vma_unpin(vma); + + if (vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) { + if (!IS_ALIGNED(vma->node.start, + I915_GTT_PAGE_SIZE_2M)) { + pr_err("node.start(%llx) not aligned to 2M\n", + vma->node.start); + err = -EINVAL; + break; + } + + if (!IS_ALIGNED(vma->node.size, + I915_GTT_PAGE_SIZE_2M)) { + pr_err("node.size(%llx) not aligned to 2M\n", + vma->node.size); + err = -EINVAL; + break; + } + } + + if (vma->page_sizes.gtt != expected_gtt) { + pr_err("gtt=%u, expected=%u, size=%zd, single=%s\n", + vma->page_sizes.gtt, expected_gtt, + obj->base.size, yesno(!!single)); + err = -EINVAL; + break; + } + + if (igt_timeout(end_time, + "%s timed out at size %zd\n", + __func__, obj->base.size)) + break; + + single = !single; + } + + close_object_list(&objects, ppgtt); + + if (err == -ENOMEM || err == -ENOSPC) + err = 0; + + return err; +} + +static int igt_mock_ppgtt_64K(void *arg) +{ + struct i915_hw_ppgtt *ppgtt = arg; + struct drm_i915_private *i915 = ppgtt->base.i915; + struct drm_i915_gem_object *obj; + const struct object_info { + unsigned int size; + unsigned int gtt; + unsigned int offset; + } objects[] = { + /* Cases with forced padding/alignment */ + { + .size = SZ_64K, + .gtt = I915_GTT_PAGE_SIZE_64K, + .offset = 0, + }, + { + .size = SZ_64K + SZ_4K, + .gtt = I915_GTT_PAGE_SIZE_4K, + .offset = 0, + }, + { + .size = SZ_64K - SZ_4K, + .gtt = I915_GTT_PAGE_SIZE_4K, + .offset = 0, + }, + { + .size = SZ_2M, + .gtt = I915_GTT_PAGE_SIZE_64K, + .offset = 0, + }, + { + .size = SZ_2M - SZ_4K, + .gtt = I915_GTT_PAGE_SIZE_4K, + .offset = 0, + }, + { + .size = SZ_2M + SZ_4K, + .gtt = I915_GTT_PAGE_SIZE_64K | I915_GTT_PAGE_SIZE_4K, + .offset = 0, + }, + { + .size = SZ_2M + SZ_64K, + .gtt = I915_GTT_PAGE_SIZE_64K, + .offset = 0, + }, + { + .size = SZ_2M - SZ_64K, + .gtt = I915_GTT_PAGE_SIZE_64K, + .offset = 0, + }, + /* Try without any forced padding/alignment */ + { + .size = SZ_64K, + .offset = SZ_2M, + .gtt = I915_GTT_PAGE_SIZE_4K, + }, + { + .size = SZ_128K, + .offset = SZ_2M - SZ_64K, + .gtt = I915_GTT_PAGE_SIZE_4K, + }, + }; + struct i915_vma *vma; + int i, single; + int err; + + /* + * Sanity check some of the trickiness with 64K pages -- either we can + * safely mark the whole page-table(2M block) as 64K, or we have to + * always fallback to 4K. + */ + + if (!HAS_PAGE_SIZES(i915, I915_GTT_PAGE_SIZE_64K)) + return 0; + + for (i = 0; i < ARRAY_SIZE(objects); ++i) { + unsigned int size = objects[i].size; + unsigned int expected_gtt = objects[i].gtt; + unsigned int offset = objects[i].offset; + unsigned int flags = PIN_USER; + + for (single = 0; single <= 1; single++) { + obj = fake_huge_pages_object(i915, size, !!single); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + err = i915_gem_object_pin_pages(obj); + if (err) + goto out_object_put; + + /* + * Disable 2M pages -- We only want to use 64K/4K pages + * for this test. + */ + obj->mm.page_sizes.sg &= ~I915_GTT_PAGE_SIZE_2M; + + vma = i915_vma_instance(obj, &ppgtt->base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_object_unpin; + } + + if (offset) + flags |= PIN_OFFSET_FIXED | offset; + + err = i915_vma_pin(vma, 0, 0, flags); + if (err) + goto out_vma_close; + + err = igt_check_page_sizes(vma); + if (err) + goto out_vma_unpin; + + if (!offset && vma->page_sizes.sg & I915_GTT_PAGE_SIZE_64K) { + if (!IS_ALIGNED(vma->node.start, + I915_GTT_PAGE_SIZE_2M)) { + pr_err("node.start(%llx) not aligned to 2M\n", + vma->node.start); + err = -EINVAL; + goto out_vma_unpin; + } + + if (!IS_ALIGNED(vma->node.size, + I915_GTT_PAGE_SIZE_2M)) { + pr_err("node.size(%llx) not aligned to 2M\n", + vma->node.size); + err = -EINVAL; + goto out_vma_unpin; + } + } + + if (vma->page_sizes.gtt != expected_gtt) { + pr_err("gtt=%u, expected=%u, i=%d, single=%s\n", + vma->page_sizes.gtt, expected_gtt, i, + yesno(!!single)); + err = -EINVAL; + goto out_vma_unpin; + } + + i915_vma_unpin(vma); + i915_vma_close(vma); + + i915_gem_object_unpin_pages(obj); + i915_gem_object_put(obj); + } + } + + return 0; + +out_vma_unpin: + i915_vma_unpin(vma); +out_vma_close: + i915_vma_close(vma); +out_object_unpin: + i915_gem_object_unpin_pages(obj); +out_object_put: + i915_gem_object_put(obj); + + return err; +} + +static struct i915_vma * +gpu_write_dw(struct i915_vma *vma, u64 offset, u32 val) +{ + struct drm_i915_private *i915 = to_i915(vma->obj->base.dev); + const int gen = INTEL_GEN(vma->vm->i915); + unsigned int count = vma->size >> PAGE_SHIFT; + struct drm_i915_gem_object *obj; + struct i915_vma *batch; + unsigned int size; + u32 *cmd; + int n; + int err; + + size = (1 + 4 * count) * sizeof(u32); + size = round_up(size, PAGE_SIZE); + obj = i915_gem_object_create_internal(i915, size); + if (IS_ERR(obj)) + return ERR_CAST(obj); + + cmd = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(cmd)) { + err = PTR_ERR(cmd); + goto err; + } + + offset += vma->node.start; + + for (n = 0; n < count; n++) { + if (gen >= 8) { + *cmd++ = MI_STORE_DWORD_IMM_GEN4; + *cmd++ = lower_32_bits(offset); + *cmd++ = upper_32_bits(offset); + *cmd++ = val; + } else if (gen >= 4) { + *cmd++ = MI_STORE_DWORD_IMM_GEN4 | + (gen < 6 ? 1 << 22 : 0); + *cmd++ = 0; + *cmd++ = offset; + *cmd++ = val; + } else { + *cmd++ = MI_STORE_DWORD_IMM | 1 << 22; + *cmd++ = offset; + *cmd++ = val; + } + + offset += PAGE_SIZE; + } + + *cmd = MI_BATCH_BUFFER_END; + + i915_gem_object_unpin_map(obj); + + err = i915_gem_object_set_to_gtt_domain(obj, false); + if (err) + goto err; + + batch = i915_vma_instance(obj, vma->vm, NULL); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto err; + } + + err = i915_vma_pin(batch, 0, 0, PIN_USER); + if (err) + goto err; + + return batch; + +err: + i915_gem_object_put(obj); + + return ERR_PTR(err); +} + +static int gpu_write(struct i915_vma *vma, + struct i915_gem_context *ctx, + struct intel_engine_cs *engine, + u32 dword, + u32 value) +{ + struct drm_i915_gem_request *rq; + struct i915_vma *batch; + int flags = 0; + int err; + + GEM_BUG_ON(!intel_engine_can_store_dword(engine)); + + err = i915_gem_object_set_to_gtt_domain(vma->obj, true); + if (err) + return err; + + rq = i915_gem_request_alloc(engine, ctx); + if (IS_ERR(rq)) + return PTR_ERR(rq); + + batch = gpu_write_dw(vma, dword * sizeof(u32), value); + if (IS_ERR(batch)) { + err = PTR_ERR(batch); + goto err_request; + } + + i915_vma_move_to_active(batch, rq, 0); + i915_gem_object_set_active_reference(batch->obj); + i915_vma_unpin(batch); + i915_vma_close(batch); + + err = rq->engine->emit_flush(rq, EMIT_INVALIDATE); + if (err) + goto err_request; + + err = i915_switch_context(rq); + if (err) + goto err_request; + + err = rq->engine->emit_bb_start(rq, + batch->node.start, batch->node.size, + flags); + if (err) + goto err_request; + + i915_vma_move_to_active(vma, rq, EXEC_OBJECT_WRITE); + + reservation_object_lock(vma->resv, NULL); + reservation_object_add_excl_fence(vma->resv, &rq->fence); + reservation_object_unlock(vma->resv); + +err_request: + __i915_add_request(rq, err == 0); + + return err; +} + +static int cpu_check(struct drm_i915_gem_object *obj, u32 dword, u32 val) +{ + unsigned int needs_flush; + unsigned long n; + int err; + + err = i915_gem_obj_prepare_shmem_read(obj, &needs_flush); + if (err) + return err; + + for (n = 0; n < obj->base.size >> PAGE_SHIFT; ++n) { + u32 *ptr = kmap_atomic(i915_gem_object_get_page(obj, n)); + + if (needs_flush & CLFLUSH_BEFORE) + drm_clflush_virt_range(ptr, PAGE_SIZE); + + if (ptr[dword] != val) { + pr_err("n=%lu ptr[%u]=%u, val=%u\n", + n, dword, ptr[dword], val); + kunmap_atomic(ptr); + err = -EINVAL; + break; + } + + kunmap_atomic(ptr); + } + + i915_gem_obj_finish_shmem_access(obj); + + return err; +} + +static int igt_write_huge(struct i915_gem_context *ctx, + struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + struct i915_address_space *vm = ctx->ppgtt ? &ctx->ppgtt->base : &i915->ggtt.base; + struct intel_engine_cs *engine; + struct i915_vma *vma; + unsigned int flags = PIN_USER | PIN_OFFSET_FIXED; + unsigned int max_page_size; + unsigned int id; + u64 max; + u64 num; + u64 size; + int err = 0; + + GEM_BUG_ON(!i915_gem_object_has_pinned_pages(obj)); + + size = obj->base.size; + if (obj->mm.page_sizes.sg & I915_GTT_PAGE_SIZE_64K) + size = round_up(size, I915_GTT_PAGE_SIZE_2M); + + max_page_size = rounddown_pow_of_two(obj->mm.page_sizes.sg); + max = div_u64((vm->total - size), max_page_size); + + vma = i915_vma_instance(obj, vm, NULL); + if (IS_ERR(vma)) + return PTR_ERR(vma); + + for_each_engine(engine, i915, id) { + IGT_TIMEOUT(end_time); + + if (!intel_engine_can_store_dword(engine)) { + pr_info("store-dword-imm not supported on engine=%u\n", + id); + continue; + } + + /* + * Try various offsets until we timeout -- we want to avoid + * issues hidden by effectively always using offset = 0. + */ + for_each_prime_number_from(num, 0, max) { + u64 offset = num * max_page_size; + u32 dword; + + err = i915_vma_unbind(vma); + if (err) + goto out_vma_close; + + err = i915_vma_pin(vma, size, max_page_size, flags | offset); + if (err) { + /* + * The ggtt may have some pages reserved so + * refrain from erroring out. + */ + if (err == -ENOSPC && i915_is_ggtt(vm)) { + err = 0; + continue; + } + + goto out_vma_close; + } + + err = igt_check_page_sizes(vma); + if (err) + goto out_vma_unpin; + + dword = offset_in_page(num) / 4; + + err = gpu_write(vma, ctx, engine, dword, num + 1); + if (err) { + pr_err("gpu-write failed at offset=%llx", offset); + goto out_vma_unpin; + } + + err = cpu_check(obj, dword, num + 1); + if (err) { + pr_err("cpu-check failed at offset=%llx", offset); + goto out_vma_unpin; + } + + i915_vma_unpin(vma); + + if (num > 0 && + igt_timeout(end_time, + "%s timed out on engine=%u at offset=%llx, max_page_size=%x\n", + __func__, id, offset, max_page_size)) + break; + } + } + +out_vma_unpin: + if (i915_vma_is_pinned(vma)) + i915_vma_unpin(vma); +out_vma_close: + i915_vma_close(vma); + + return err; +} + +static int igt_ppgtt_exhaust_huge(void *arg) +{ + struct i915_gem_context *ctx = arg; + struct drm_i915_private *i915 = ctx->i915; + unsigned long supported = INTEL_INFO(i915)->page_sizes; + static unsigned int pages[ARRAY_SIZE(page_sizes)]; + struct drm_i915_gem_object *obj; + unsigned int size_mask; + unsigned int page_mask; + int n, i; + int err = -ENODEV; + + /* + * Sanity check creating objects with a varying mix of page sizes -- + * ensuring that our writes lands in the right place. + */ + + n = 0; + for_each_set_bit(i, &supported, ilog2(I915_GTT_MAX_PAGE_SIZE) + 1) + pages[n++] = BIT(i); + + for (size_mask = 2; size_mask < BIT(n); size_mask++) { + unsigned int size = 0; + + for (i = 0; i < n; i++) { + if (size_mask & BIT(i)) + size |= pages[i]; + } + + /* + * For our page mask we want to enumerate all the page-size + * combinations which will fit into our chosen object size. + */ + for (page_mask = 2; page_mask <= size_mask; page_mask++) { + unsigned int page_sizes = 0; + + for (i = 0; i < n; i++) { + if (page_mask & BIT(i)) + page_sizes |= pages[i]; + } + + /* + * Ensure that we can actually fill the given object + * with our chosen page mask. + */ + if (!IS_ALIGNED(size, BIT(__ffs(page_sizes)))) + continue; + + obj = huge_pages_object(i915, size, page_sizes); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out_device; + } + + err = i915_gem_object_pin_pages(obj); + if (err) { + i915_gem_object_put(obj); + + if (err == -ENOMEM) { + pr_info("unable to get pages, size=%u, pages=%u\n", + size, page_sizes); + err = 0; + break; + } + + pr_err("pin_pages failed, size=%u, pages=%u\n", + size_mask, page_mask); + + goto out_device; + } + + /* Force the page-size for the gtt insertion */ + obj->mm.page_sizes.sg = page_sizes; + + err = igt_write_huge(ctx, obj); + if (err) { + pr_err("exhaust write-huge failed with size=%u\n", + size); + goto out_unpin; + } + + i915_gem_object_unpin_pages(obj); + i915_gem_object_put(obj); + } + } + + goto out_device; + +out_unpin: + i915_gem_object_unpin_pages(obj); + i915_gem_object_put(obj); +out_device: + mkwrite_device_info(i915)->page_sizes = supported; + + return err; +} + +static int igt_ppgtt_internal_huge(void *arg) +{ + struct i915_gem_context *ctx = arg; + struct drm_i915_private *i915 = ctx->i915; + struct drm_i915_gem_object *obj; + static const unsigned int sizes[] = { + SZ_64K, + SZ_128K, + SZ_256K, + SZ_512K, + SZ_1M, + SZ_2M, + }; + int i; + int err; + + /* + * Sanity check that the HW uses huge pages correctly through internal + * -- ensure that our writes land in the right place. + */ + + for (i = 0; i < ARRAY_SIZE(sizes); ++i) { + unsigned int size = sizes[i]; + + obj = i915_gem_object_create_internal(i915, size); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + err = i915_gem_object_pin_pages(obj); + if (err) + goto out_put; + + if (obj->mm.page_sizes.phys < I915_GTT_PAGE_SIZE_64K) { + pr_info("internal unable to allocate huge-page(s) with size=%u\n", + size); + goto out_unpin; + } + + err = igt_write_huge(ctx, obj); + if (err) { + pr_err("internal write-huge failed with size=%u\n", + size); + goto out_unpin; + } + + i915_gem_object_unpin_pages(obj); + i915_gem_object_put(obj); + } + + return 0; + +out_unpin: + i915_gem_object_unpin_pages(obj); +out_put: + i915_gem_object_put(obj); + + return err; +} + +static inline bool igt_can_allocate_thp(struct drm_i915_private *i915) +{ + return i915->mm.gemfs && has_transparent_hugepage(); +} + +static int igt_ppgtt_gemfs_huge(void *arg) +{ + struct i915_gem_context *ctx = arg; + struct drm_i915_private *i915 = ctx->i915; + struct drm_i915_gem_object *obj; + static const unsigned int sizes[] = { + SZ_2M, + SZ_4M, + SZ_8M, + SZ_16M, + SZ_32M, + }; + int i; + int err; + + /* + * Sanity check that the HW uses huge pages correctly through gemfs -- + * ensure that our writes land in the right place. + */ + + if (!igt_can_allocate_thp(i915)) { + pr_info("missing THP support, skipping\n"); + return 0; + } + + for (i = 0; i < ARRAY_SIZE(sizes); ++i) { + unsigned int size = sizes[i]; + + obj = i915_gem_object_create(i915, size); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + err = i915_gem_object_pin_pages(obj); + if (err) + goto out_put; + + if (obj->mm.page_sizes.phys < I915_GTT_PAGE_SIZE_2M) { + pr_info("finishing test early, gemfs unable to allocate huge-page(s) with size=%u\n", + size); + goto out_unpin; + } + + err = igt_write_huge(ctx, obj); + if (err) { + pr_err("gemfs write-huge failed with size=%u\n", + size); + goto out_unpin; + } + + i915_gem_object_unpin_pages(obj); + i915_gem_object_put(obj); + } + + return 0; + +out_unpin: + i915_gem_object_unpin_pages(obj); +out_put: + i915_gem_object_put(obj); + + return err; +} + +static int igt_ppgtt_pin_update(void *arg) +{ + struct i915_gem_context *ctx = arg; + struct drm_i915_private *dev_priv = ctx->i915; + unsigned long supported = INTEL_INFO(dev_priv)->page_sizes; + struct i915_hw_ppgtt *ppgtt = ctx->ppgtt; + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + unsigned int flags = PIN_USER | PIN_OFFSET_FIXED; + int first, last; + int err; + + /* + * Make sure there's no funny business when doing a PIN_UPDATE -- in the + * past we had a subtle issue with being able to incorrectly do multiple + * alloc va ranges on the same object when doing a PIN_UPDATE, which + * resulted in some pretty nasty bugs, though only when using + * huge-gtt-pages. + */ + + if (!USES_FULL_48BIT_PPGTT(dev_priv)) { + pr_info("48b PPGTT not supported, skipping\n"); + return 0; + } + + first = ilog2(I915_GTT_PAGE_SIZE_64K); + last = ilog2(I915_GTT_PAGE_SIZE_2M); + + for_each_set_bit_from(first, &supported, last + 1) { + unsigned int page_size = BIT(first); + + obj = i915_gem_object_create_internal(dev_priv, page_size); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + vma = i915_vma_instance(obj, &ppgtt->base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_put; + } + + err = i915_vma_pin(vma, SZ_2M, 0, flags); + if (err) + goto out_close; + + if (vma->page_sizes.sg < page_size) { + pr_info("Unable to allocate page-size %x, finishing test early\n", + page_size); + goto out_unpin; + } + + err = igt_check_page_sizes(vma); + if (err) + goto out_unpin; + + if (vma->page_sizes.gtt != page_size) { + dma_addr_t addr = i915_gem_object_get_dma_address(obj, 0); + + /* + * The only valid reason for this to ever fail would be + * if the dma-mapper screwed us over when we did the + * dma_map_sg(), since it has the final say over the dma + * address. + */ + if (IS_ALIGNED(addr, page_size)) { + pr_err("page_sizes.gtt=%u, expected=%u\n", + vma->page_sizes.gtt, page_size); + err = -EINVAL; + } else { + pr_info("dma address misaligned, finishing test early\n"); + } + + goto out_unpin; + } + + err = i915_vma_bind(vma, I915_CACHE_NONE, PIN_UPDATE); + if (err) + goto out_unpin; + + i915_vma_unpin(vma); + i915_vma_close(vma); + + i915_gem_object_put(obj); + } + + obj = i915_gem_object_create_internal(dev_priv, PAGE_SIZE); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + vma = i915_vma_instance(obj, &ppgtt->base, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_put; + } + + err = i915_vma_pin(vma, 0, 0, flags); + if (err) + goto out_close; + + /* + * Make sure we don't end up with something like where the pde is still + * pointing to the 2M page, and the pt we just filled-in is dangling -- + * we can check this by writing to the first page where it would then + * land in the now stale 2M page. + */ + + err = gpu_write(vma, ctx, dev_priv->engine[RCS], 0, 0xdeadbeaf); + if (err) + goto out_unpin; + + err = cpu_check(obj, 0, 0xdeadbeaf); + +out_unpin: + i915_vma_unpin(vma); +out_close: + i915_vma_close(vma); +out_put: + i915_gem_object_put(obj); + + return err; +} + +static int igt_tmpfs_fallback(void *arg) +{ + struct i915_gem_context *ctx = arg; + struct drm_i915_private *i915 = ctx->i915; + struct vfsmount *gemfs = i915->mm.gemfs; + struct i915_address_space *vm = ctx->ppgtt ? &ctx->ppgtt->base : &i915->ggtt.base; + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + u32 *vaddr; + int err = 0; + + /* + * Make sure that we don't burst into a ball of flames upon falling back + * to tmpfs, which we rely on if on the off-chance we encouter a failure + * when setting up gemfs. + */ + + i915->mm.gemfs = NULL; + + obj = i915_gem_object_create(i915, PAGE_SIZE); + if (IS_ERR(obj)) { + err = PTR_ERR(obj); + goto out_restore; + } + + vaddr = i915_gem_object_pin_map(obj, I915_MAP_WB); + if (IS_ERR(vaddr)) { + err = PTR_ERR(vaddr); + goto out_put; + } + *vaddr = 0xdeadbeaf; + + i915_gem_object_unpin_map(obj); + + vma = i915_vma_instance(obj, vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_put; + } + + err = i915_vma_pin(vma, 0, 0, PIN_USER); + if (err) + goto out_close; + + err = igt_check_page_sizes(vma); + + i915_vma_unpin(vma); +out_close: + i915_vma_close(vma); +out_put: + i915_gem_object_put(obj); +out_restore: + i915->mm.gemfs = gemfs; + + return err; +} + +static int igt_shrink_thp(void *arg) +{ + struct i915_gem_context *ctx = arg; + struct drm_i915_private *i915 = ctx->i915; + struct i915_address_space *vm = ctx->ppgtt ? &ctx->ppgtt->base : &i915->ggtt.base; + struct drm_i915_gem_object *obj; + struct i915_vma *vma; + unsigned int flags = PIN_USER; + int err; + + /* + * Sanity check shrinking huge-paged object -- make sure nothing blows + * up. + */ + + if (!igt_can_allocate_thp(i915)) { + pr_info("missing THP support, skipping\n"); + return 0; + } + + obj = i915_gem_object_create(i915, SZ_2M); + if (IS_ERR(obj)) + return PTR_ERR(obj); + + vma = i915_vma_instance(obj, vm, NULL); + if (IS_ERR(vma)) { + err = PTR_ERR(vma); + goto out_put; + } + + err = i915_vma_pin(vma, 0, 0, flags); + if (err) + goto out_close; + + if (obj->mm.page_sizes.phys < I915_GTT_PAGE_SIZE_2M) { + pr_info("failed to allocate THP, finishing test early\n"); + goto out_unpin; + } + + err = igt_check_page_sizes(vma); + if (err) + goto out_unpin; + + err = gpu_write(vma, ctx, i915->engine[RCS], 0, 0xdeadbeaf); + if (err) + goto out_unpin; + + i915_vma_unpin(vma); + + /* + * Now that the pages are *unpinned* shrink-all should invoke + * shmem to truncate our pages. + */ + i915_gem_shrink_all(i915); + if (!IS_ERR_OR_NULL(obj->mm.pages)) { + pr_err("shrink-all didn't truncate the pages\n"); + err = -EINVAL; + goto out_close; + } + + if (obj->mm.page_sizes.sg || obj->mm.page_sizes.phys) { + pr_err("residual page-size bits left\n"); + err = -EINVAL; + goto out_close; + } + + err = i915_vma_pin(vma, 0, 0, flags); + if (err) + goto out_close; + + err = cpu_check(obj, 0, 0xdeadbeaf); + +out_unpin: + i915_vma_unpin(vma); +out_close: + i915_vma_close(vma); +out_put: + i915_gem_object_put(obj); + + return err; +} + +int i915_gem_huge_page_mock_selftests(void) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_mock_exhaust_device_supported_pages), + SUBTEST(igt_mock_ppgtt_misaligned_dma), + SUBTEST(igt_mock_ppgtt_huge_fill), + SUBTEST(igt_mock_ppgtt_64K), + }; + int saved_ppgtt = i915_modparams.enable_ppgtt; + struct drm_i915_private *dev_priv; + struct pci_dev *pdev; + struct i915_hw_ppgtt *ppgtt; + int err; + + dev_priv = mock_gem_device(); + if (!dev_priv) + return -ENOMEM; + + /* Pretend to be a device which supports the 48b PPGTT */ + i915_modparams.enable_ppgtt = 3; + + pdev = dev_priv->drm.pdev; + dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(39)); + + mutex_lock(&dev_priv->drm.struct_mutex); + ppgtt = i915_ppgtt_create(dev_priv, ERR_PTR(-ENODEV), "mock"); + if (IS_ERR(ppgtt)) { + err = PTR_ERR(ppgtt); + goto out_unlock; + } + + if (!i915_vm_is_48bit(&ppgtt->base)) { + pr_err("failed to create 48b PPGTT\n"); + err = -EINVAL; + goto out_close; + } + + /* If we were ever hit this then it's time to mock the 64K scratch */ + if (!i915_vm_has_scratch_64K(&ppgtt->base)) { + pr_err("PPGTT missing 64K scratch page\n"); + err = -EINVAL; + goto out_close; + } + + err = i915_subtests(tests, ppgtt); + +out_close: + i915_ppgtt_close(&ppgtt->base); + i915_ppgtt_put(ppgtt); + +out_unlock: + mutex_unlock(&dev_priv->drm.struct_mutex); + + i915_modparams.enable_ppgtt = saved_ppgtt; + + drm_dev_unref(&dev_priv->drm); + + return err; +} + +int i915_gem_huge_page_live_selftests(struct drm_i915_private *dev_priv) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_shrink_thp), + SUBTEST(igt_ppgtt_pin_update), + SUBTEST(igt_tmpfs_fallback), + SUBTEST(igt_ppgtt_exhaust_huge), + SUBTEST(igt_ppgtt_gemfs_huge), + SUBTEST(igt_ppgtt_internal_huge), + }; + struct drm_file *file; + struct i915_gem_context *ctx; + int err; + + if (!USES_PPGTT(dev_priv)) { + pr_info("PPGTT not supported, skipping live-selftests\n"); + return 0; + } + + file = mock_file(dev_priv); + if (IS_ERR(file)) + return PTR_ERR(file); + + mutex_lock(&dev_priv->drm.struct_mutex); + + ctx = live_context(dev_priv, file); + if (IS_ERR(ctx)) { + err = PTR_ERR(ctx); + goto out_unlock; + } + + err = i915_subtests(tests, ctx); + +out_unlock: + mutex_unlock(&dev_priv->drm.struct_mutex); + + mock_file_free(dev_priv, file); + + return err; +} diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/selftests/i915_gem_context.c index fb0a58fc8348..def5052862ae 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_context.c @@ -417,7 +417,7 @@ static int fake_aliasing_ppgtt_enable(struct drm_i915_private *i915) if (err) return err; - list_for_each_entry(obj, &i915->mm.bound_list, global_link) { + list_for_each_entry(obj, &i915->mm.bound_list, mm.link) { struct i915_vma *vma; vma = i915_vma_instance(obj, &i915->ggtt.base, NULL); diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c index 5ea373221f49..f463105ff48d 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_evict.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_evict.c @@ -24,6 +24,9 @@ #include "../i915_selftest.h" +#include "lib_sw_fence.h" +#include "mock_context.h" +#include "mock_drm.h" #include "mock_gem_device.h" static int populate_ggtt(struct drm_i915_private *i915) @@ -47,7 +50,7 @@ static int populate_ggtt(struct drm_i915_private *i915) if (!list_empty(&i915->mm.unbound_list)) { size = 0; - list_for_each_entry(obj, &i915->mm.unbound_list, global_link) + list_for_each_entry(obj, &i915->mm.unbound_list, mm.link) size++; pr_err("Found %lld objects unbound!\n", size); @@ -74,10 +77,10 @@ static void cleanup_objects(struct drm_i915_private *i915) { struct drm_i915_gem_object *obj, *on; - list_for_each_entry_safe(obj, on, &i915->mm.unbound_list, global_link) + list_for_each_entry_safe(obj, on, &i915->mm.unbound_list, mm.link) i915_gem_object_put(obj); - list_for_each_entry_safe(obj, on, &i915->mm.bound_list, global_link) + list_for_each_entry_safe(obj, on, &i915->mm.bound_list, mm.link) i915_gem_object_put(obj); mutex_unlock(&i915->drm.struct_mutex); @@ -149,8 +152,6 @@ static int igt_overcommit(void *arg) goto cleanup; } - list_move(&obj->global_link, &i915->mm.unbound_list); - vma = i915_gem_object_ggtt_pin(obj, NULL, 0, 0, 0); if (!IS_ERR(vma) || PTR_ERR(vma) != -ENOSPC) { pr_err("Failed to evict+insert, i915_gem_object_ggtt_pin returned err=%d\n", (int)PTR_ERR(vma)); @@ -325,6 +326,148 @@ cleanup: return err; } +static int igt_evict_contexts(void *arg) +{ + const u64 PRETEND_GGTT_SIZE = 16ull << 20; + struct drm_i915_private *i915 = arg; + struct intel_engine_cs *engine; + enum intel_engine_id id; + struct reserved { + struct drm_mm_node node; + struct reserved *next; + } *reserved = NULL; + struct drm_mm_node hole; + unsigned long count; + int err; + + /* + * The purpose of this test is to verify that we will trigger an + * eviction in the GGTT when constructing a request that requires + * additional space in the GGTT for pinning the context. This space + * is not directly tied to the request so reclaiming it requires + * extra work. + * + * As such this test is only meaningful for full-ppgtt environments + * where the GTT space of the request is separate from the GGTT + * allocation required to build the request. + */ + if (!USES_FULL_PPGTT(i915)) + return 0; + + mutex_lock(&i915->drm.struct_mutex); + + /* Reserve a block so that we know we have enough to fit a few rq */ + memset(&hole, 0, sizeof(hole)); + err = i915_gem_gtt_insert(&i915->ggtt.base, &hole, + PRETEND_GGTT_SIZE, 0, I915_COLOR_UNEVICTABLE, + 0, i915->ggtt.base.total, + PIN_NOEVICT); + if (err) + goto out_locked; + + /* Make the GGTT appear small by filling it with unevictable nodes */ + count = 0; + do { + struct reserved *r; + + r = kcalloc(1, sizeof(*r), GFP_KERNEL); + if (!r) { + err = -ENOMEM; + goto out_locked; + } + + if (i915_gem_gtt_insert(&i915->ggtt.base, &r->node, + 1ul << 20, 0, I915_COLOR_UNEVICTABLE, + 0, i915->ggtt.base.total, + PIN_NOEVICT)) { + kfree(r); + break; + } + + r->next = reserved; + reserved = r; + + count++; + } while (1); + drm_mm_remove_node(&hole); + mutex_unlock(&i915->drm.struct_mutex); + pr_info("Filled GGTT with %lu 1MiB nodes\n", count); + + /* Overfill the GGTT with context objects and so try to evict one. */ + for_each_engine(engine, i915, id) { + struct i915_sw_fence fence; + struct drm_file *file; + + file = mock_file(i915); + if (IS_ERR(file)) + return PTR_ERR(file); + + count = 0; + mutex_lock(&i915->drm.struct_mutex); + onstack_fence_init(&fence); + do { + struct drm_i915_gem_request *rq; + struct i915_gem_context *ctx; + + ctx = live_context(i915, file); + if (!ctx) + break; + + /* We will need some GGTT space for the rq's context */ + igt_evict_ctl.fail_if_busy = true; + rq = i915_gem_request_alloc(engine, ctx); + igt_evict_ctl.fail_if_busy = false; + + if (IS_ERR(rq)) { + /* When full, fail_if_busy will trigger EBUSY */ + if (PTR_ERR(rq) != -EBUSY) { + pr_err("Unexpected error from request alloc (ctx hw id %u, on %s): %d\n", + ctx->hw_id, engine->name, + (int)PTR_ERR(rq)); + err = PTR_ERR(rq); + } + break; + } + + /* Keep every request/ctx pinned until we are full */ + err = i915_sw_fence_await_sw_fence_gfp(&rq->submit, + &fence, + GFP_KERNEL); + if (err < 0) + break; + + i915_add_request(rq); + count++; + err = 0; + } while(1); + mutex_unlock(&i915->drm.struct_mutex); + + onstack_fence_fini(&fence); + pr_info("Submitted %lu contexts/requests on %s\n", + count, engine->name); + + mock_file_free(i915, file); + if (err) + break; + } + + mutex_lock(&i915->drm.struct_mutex); +out_locked: + while (reserved) { + struct reserved *next = reserved->next; + + drm_mm_remove_node(&reserved->node); + kfree(reserved); + + reserved = next; + } + if (drm_mm_node_allocated(&hole)) + drm_mm_remove_node(&hole); + mutex_unlock(&i915->drm.struct_mutex); + + return err; +} + int i915_gem_evict_mock_selftests(void) { static const struct i915_subtest tests[] = { @@ -348,3 +491,12 @@ int i915_gem_evict_mock_selftests(void) drm_dev_unref(&i915->drm); return err; } + +int i915_gem_evict_live_selftests(struct drm_i915_private *i915) +{ + static const struct i915_subtest tests[] = { + SUBTEST(igt_evict_contexts), + }; + + return i915_subtests(tests, i915); +} diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 6b132caffa18..9da0c9f99916 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -39,25 +39,26 @@ static void fake_free_pages(struct drm_i915_gem_object *obj, kfree(pages); } -static struct sg_table * -fake_get_pages(struct drm_i915_gem_object *obj) +static int fake_get_pages(struct drm_i915_gem_object *obj) { #define GFP (GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY) #define PFN_BIAS 0x1000 struct sg_table *pages; struct scatterlist *sg; + unsigned int sg_page_sizes; typeof(obj->base.size) rem; pages = kmalloc(sizeof(*pages), GFP); if (!pages) - return ERR_PTR(-ENOMEM); + return -ENOMEM; rem = round_up(obj->base.size, BIT(31)) >> 31; if (sg_alloc_table(pages, rem, GFP)) { kfree(pages); - return ERR_PTR(-ENOMEM); + return -ENOMEM; } + sg_page_sizes = 0; rem = obj->base.size; for (sg = pages->sgl; sg; sg = sg_next(sg)) { unsigned long len = min_t(typeof(rem), rem, BIT(31)); @@ -66,13 +67,17 @@ fake_get_pages(struct drm_i915_gem_object *obj) sg_set_page(sg, pfn_to_page(PFN_BIAS), len, 0); sg_dma_address(sg) = page_to_phys(sg_page(sg)); sg_dma_len(sg) = len; + sg_page_sizes |= len; rem -= len; } GEM_BUG_ON(rem); obj->mm.madv = I915_MADV_DONTNEED; - return pages; + + __i915_gem_object_set_pages(obj, pages, sg_page_sizes); + + return 0; #undef GFP } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_object.c b/drivers/gpu/drm/i915/selftests/i915_gem_object.c index 8f011c447e41..1b8774a42e48 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_object.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_object.c @@ -251,14 +251,6 @@ static int check_partial_mapping(struct drm_i915_gem_object *obj, return PTR_ERR(io); } - err = i915_vma_get_fence(vma); - if (err) { - pr_err("Failed to get fence for partial view: offset=%lu\n", - page); - i915_vma_unpin_iomap(vma); - return err; - } - iowrite32(page, io + n * PAGE_SIZE/sizeof(*io)); i915_vma_unpin_iomap(vma); diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_request.c b/drivers/gpu/drm/i915/selftests/i915_gem_request.c index 6664cb2eb0b8..a999161e8db1 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_request.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_request.c @@ -215,7 +215,9 @@ static int igt_request_rewind(void *arg) } i915_gem_request_get(vip); i915_add_request(vip); + rcu_read_lock(); request->engine->submit_request(request); + rcu_read_unlock(); mutex_unlock(&i915->drm.struct_mutex); @@ -418,7 +420,10 @@ static struct i915_vma *empty_batch(struct drm_i915_private *i915) err = PTR_ERR(cmd); goto err; } + *cmd = MI_BATCH_BUFFER_END; + i915_gem_chipset_flush(i915); + i915_gem_object_unpin_map(obj); err = i915_gem_object_set_to_gtt_domain(obj, false); @@ -605,8 +610,8 @@ static struct i915_vma *recursive_batch(struct drm_i915_private *i915) *cmd++ = lower_32_bits(vma->node.start); } *cmd++ = MI_BATCH_BUFFER_END; /* terminate early in case of error */ + i915_gem_chipset_flush(i915); - wmb(); i915_gem_object_unpin_map(obj); return vma; @@ -625,7 +630,7 @@ static int recursive_batch_resolve(struct i915_vma *batch) return PTR_ERR(cmd); *cmd = MI_BATCH_BUFFER_END; - wmb(); + i915_gem_chipset_flush(batch->vm->i915); i915_gem_object_unpin_map(batch->obj); @@ -858,7 +863,8 @@ out_request: I915_MAP_WC); if (!IS_ERR(cmd)) { *cmd = MI_BATCH_BUFFER_END; - wmb(); + i915_gem_chipset_flush(i915); + i915_gem_object_unpin_map(request[id]->batch->obj); } diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c b/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c index 7a44dab631b8..4795877abe56 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_timeline.c @@ -121,7 +121,7 @@ out: static unsigned int random_engine(struct rnd_state *rnd) { - return ((u64)prandom_u32_state(rnd) * I915_NUM_ENGINES) >> 32; + return i915_prandom_u32_max_state(I915_NUM_ENGINES, rnd); } static int bench_sync(void *arg) diff --git a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h index 18b174d855ca..54a73534b37e 100644 --- a/drivers/gpu/drm/i915/selftests/i915_live_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_live_selftests.h @@ -15,5 +15,7 @@ selftest(objects, i915_gem_object_live_selftests) selftest(dmabuf, i915_gem_dmabuf_live_selftests) selftest(coherency, i915_gem_coherency_live_selftests) selftest(gtt, i915_gem_gtt_live_selftests) +selftest(evict, i915_gem_evict_live_selftests) +selftest(hugepages, i915_gem_huge_page_live_selftests) selftest(contexts, i915_gem_context_live_selftests) selftest(hangcheck, intel_hangcheck_live_selftests) diff --git a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h index fc74687501ba..9961b44f76ed 100644 --- a/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h +++ b/drivers/gpu/drm/i915/selftests/i915_mock_selftests.h @@ -21,3 +21,4 @@ selftest(dmabuf, i915_gem_dmabuf_mock_selftests) selftest(vma, i915_vma_mock_selftests) selftest(evict, i915_gem_evict_mock_selftests) selftest(gtt, i915_gem_gtt_mock_selftests) +selftest(hugepages, i915_gem_huge_page_mock_selftests) diff --git a/drivers/gpu/drm/i915/selftests/i915_random.c b/drivers/gpu/drm/i915/selftests/i915_random.c index 222c511bea49..b85872cc7fbe 100644 --- a/drivers/gpu/drm/i915/selftests/i915_random.c +++ b/drivers/gpu/drm/i915/selftests/i915_random.c @@ -41,11 +41,6 @@ u64 i915_prandom_u64_state(struct rnd_state *rnd) return x; } -static inline u32 i915_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state) -{ - return upper_32_bits((u64)prandom_u32_state(state) * ep_ro); -} - void i915_random_reorder(unsigned int *order, unsigned int count, struct rnd_state *state) { diff --git a/drivers/gpu/drm/i915/selftests/i915_random.h b/drivers/gpu/drm/i915/selftests/i915_random.h index 6c9379871384..7dffedc501ca 100644 --- a/drivers/gpu/drm/i915/selftests/i915_random.h +++ b/drivers/gpu/drm/i915/selftests/i915_random.h @@ -43,6 +43,11 @@ u64 i915_prandom_u64_state(struct rnd_state *rnd); +static inline u32 i915_prandom_u32_max_state(u32 ep_ro, struct rnd_state *state) +{ + return upper_32_bits(mul_u32_u32(prandom_u32_state(state), ep_ro)); +} + unsigned int *i915_random_order(unsigned int count, struct rnd_state *state); void i915_random_reorder(unsigned int *order, diff --git a/drivers/gpu/drm/i915/selftests/i915_sw_fence.c b/drivers/gpu/drm/i915/selftests/i915_sw_fence.c index 19d145d6bf52..ea01d0fe3ace 100644 --- a/drivers/gpu/drm/i915/selftests/i915_sw_fence.c +++ b/drivers/gpu/drm/i915/selftests/i915_sw_fence.c @@ -24,6 +24,7 @@ #include <linux/completion.h> #include <linux/delay.h> +#include <linux/prime_numbers.h> #include "../i915_selftest.h" @@ -565,6 +566,46 @@ err_in: return ret; } +static int test_timer(void *arg) +{ + unsigned long target, delay; + struct timed_fence tf; + + timed_fence_init(&tf, target = jiffies); + if (!i915_sw_fence_done(&tf.fence)) { + pr_err("Fence with immediate expiration not signaled\n"); + goto err; + } + timed_fence_fini(&tf); + + for_each_prime_number(delay, i915_selftest.timeout_jiffies/2) { + timed_fence_init(&tf, target = jiffies + delay); + if (i915_sw_fence_done(&tf.fence)) { + pr_err("Fence with future expiration (%lu jiffies) already signaled\n", delay); + goto err; + } + + i915_sw_fence_wait(&tf.fence); + if (!i915_sw_fence_done(&tf.fence)) { + pr_err("Fence not signaled after wait\n"); + goto err; + } + if (time_before(jiffies, target)) { + pr_err("Fence signaled too early, target=%lu, now=%lu\n", + target, jiffies); + goto err; + } + + timed_fence_fini(&tf); + } + + return 0; + +err: + timed_fence_fini(&tf); + return -EINVAL; +} + int i915_sw_fence_mock_selftests(void) { static const struct i915_subtest tests[] = { @@ -576,6 +617,7 @@ int i915_sw_fence_mock_selftests(void) SUBTEST(test_C_AB), SUBTEST(test_chain), SUBTEST(test_ipc), + SUBTEST(test_timer), }; return i915_subtests(tests, NULL); diff --git a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c index 02e52a146ed8..71ce06680d66 100644 --- a/drivers/gpu/drm/i915/selftests/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/selftests/intel_hangcheck.c @@ -165,6 +165,7 @@ static int emit_recurse_batch(struct hang *h, *batch++ = lower_32_bits(vma->node.start); } *batch++ = MI_BATCH_BUFFER_END; /* not reached */ + i915_gem_chipset_flush(h->i915); flags = 0; if (INTEL_GEN(vm->i915) <= 5) @@ -231,7 +232,7 @@ static u32 hws_seqno(const struct hang *h, static void hang_fini(struct hang *h) { *h->batch = MI_BATCH_BUFFER_END; - wmb(); + i915_gem_chipset_flush(h->i915); i915_gem_object_unpin_map(h->obj); i915_gem_object_put(h->obj); @@ -275,6 +276,8 @@ static int igt_hang_sanitycheck(void *arg) i915_gem_request_get(rq); *h.batch = MI_BATCH_BUFFER_END; + i915_gem_chipset_flush(i915); + __i915_add_request(rq, true); timeout = i915_wait_request(rq, @@ -621,7 +624,15 @@ static int igt_wait_reset(void *arg) __i915_add_request(rq, true); if (!wait_for_hang(&h, rq)) { - pr_err("Failed to start request %x\n", rq->fence.seqno); + struct drm_printer p = drm_info_printer(i915->drm.dev); + + pr_err("Failed to start request %x, at %x\n", + rq->fence.seqno, hws_seqno(&h, rq)); + intel_engine_dump(rq->engine, &p); + + i915_reset(i915, 0); + i915_gem_set_wedged(i915); + err = -EIO; goto out_rq; } @@ -708,10 +719,18 @@ static int igt_reset_queue(void *arg) __i915_add_request(rq, true); if (!wait_for_hang(&h, prev)) { - pr_err("Failed to start request %x\n", - prev->fence.seqno); + struct drm_printer p = drm_info_printer(i915->drm.dev); + + pr_err("Failed to start request %x, at %x\n", + prev->fence.seqno, hws_seqno(&h, prev)); + intel_engine_dump(rq->engine, &p); + i915_gem_request_put(rq); i915_gem_request_put(prev); + + i915_reset(i915, 0); + i915_gem_set_wedged(i915); + err = -EIO; goto fini; } @@ -756,7 +775,7 @@ static int igt_reset_queue(void *arg) pr_info("%s: Completed %d resets\n", engine->name, count); *h.batch = MI_BATCH_BUFFER_END; - wmb(); + i915_gem_chipset_flush(i915); i915_gem_request_put(prev); } @@ -806,7 +825,15 @@ static int igt_handle_error(void *arg) __i915_add_request(rq, true); if (!wait_for_hang(&h, rq)) { - pr_err("Failed to start request %x\n", rq->fence.seqno); + struct drm_printer p = drm_info_printer(i915->drm.dev); + + pr_err("Failed to start request %x, at %x\n", + rq->fence.seqno, hws_seqno(&h, rq)); + intel_engine_dump(rq->engine, &p); + + i915_reset(i915, 0); + i915_gem_set_wedged(i915); + err = -EIO; goto err_request; } @@ -843,17 +870,24 @@ err_unlock: int intel_hangcheck_live_selftests(struct drm_i915_private *i915) { static const struct i915_subtest tests[] = { + SUBTEST(igt_global_reset), /* attempt to recover GPU first */ SUBTEST(igt_hang_sanitycheck), - SUBTEST(igt_global_reset), SUBTEST(igt_reset_engine), SUBTEST(igt_reset_active_engines), SUBTEST(igt_wait_reset), SUBTEST(igt_reset_queue), SUBTEST(igt_handle_error), }; + int err; if (!intel_has_gpu_reset(i915)) return 0; - return i915_subtests(tests, i915); + intel_runtime_pm_get(i915); + + err = i915_subtests(tests, i915); + + intel_runtime_pm_put(i915); + + return err; } diff --git a/drivers/gpu/drm/i915/selftests/lib_sw_fence.c b/drivers/gpu/drm/i915/selftests/lib_sw_fence.c new file mode 100644 index 000000000000..3790fdf44a1a --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/lib_sw_fence.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2017 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION 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 "lib_sw_fence.h" + +/* Small library of different fence types useful for writing tests */ + +static int __i915_sw_fence_call +nop_fence_notify(struct i915_sw_fence *fence, enum i915_sw_fence_notify state) +{ + return NOTIFY_DONE; +} + +void __onstack_fence_init(struct i915_sw_fence *fence, + const char *name, + struct lock_class_key *key) +{ + debug_fence_init_onstack(fence); + + __init_waitqueue_head(&fence->wait, name, key); + atomic_set(&fence->pending, 1); + fence->flags = (unsigned long)nop_fence_notify; +} + +void onstack_fence_fini(struct i915_sw_fence *fence) +{ + i915_sw_fence_commit(fence); + i915_sw_fence_fini(fence); +} + +static void timed_fence_wake(unsigned long data) +{ + struct timed_fence *tf = (struct timed_fence *)data; + + i915_sw_fence_commit(&tf->fence); +} + +void timed_fence_init(struct timed_fence *tf, unsigned long expires) +{ + onstack_fence_init(&tf->fence); + + setup_timer_on_stack(&tf->timer, timed_fence_wake, (unsigned long)tf); + + if (time_after(expires, jiffies)) + mod_timer(&tf->timer, expires); + else + i915_sw_fence_commit(&tf->fence); +} + +void timed_fence_fini(struct timed_fence *tf) +{ + if (del_timer_sync(&tf->timer)) + i915_sw_fence_commit(&tf->fence); + + destroy_timer_on_stack(&tf->timer); + i915_sw_fence_fini(&tf->fence); +} diff --git a/drivers/gpu/drm/i915/selftests/lib_sw_fence.h b/drivers/gpu/drm/i915/selftests/lib_sw_fence.h new file mode 100644 index 000000000000..474aafb92ae1 --- /dev/null +++ b/drivers/gpu/drm/i915/selftests/lib_sw_fence.h @@ -0,0 +1,42 @@ +/* + * lib_sw_fence.h - library routines for testing N:M synchronisation points + * + * Copyright (C) 2017 Intel Corporation + * + * This file is released under the GPLv2. + * + */ + +#ifndef _LIB_SW_FENCE_H_ +#define _LIB_SW_FENCE_H_ + +#include <linux/timer.h> + +#include "../i915_sw_fence.h" + +#ifdef CONFIG_LOCKDEP +#define onstack_fence_init(fence) \ +do { \ + static struct lock_class_key __key; \ + \ + __onstack_fence_init((fence), #fence, &__key); \ +} while (0) +#else +#define onstack_fence_init(fence) \ + __onstack_fence_init((fence), NULL, NULL) +#endif + +void __onstack_fence_init(struct i915_sw_fence *fence, + const char *name, + struct lock_class_key *key); +void onstack_fence_fini(struct i915_sw_fence *fence); + +struct timed_fence { + struct i915_sw_fence fence; + struct timer_list timer; +}; + +void timed_fence_init(struct timed_fence *tf, unsigned long expires); +void timed_fence_fini(struct timed_fence *tf); + +#endif /* _LIB_SW_FENCE_H_ */ diff --git a/drivers/gpu/drm/i915/selftests/mock_context.c b/drivers/gpu/drm/i915/selftests/mock_context.c index 098ce643ad07..bbf80d42e793 100644 --- a/drivers/gpu/drm/i915/selftests/mock_context.c +++ b/drivers/gpu/drm/i915/selftests/mock_context.c @@ -73,11 +73,7 @@ err_put: void mock_context_close(struct i915_gem_context *ctx) { - i915_gem_context_set_closed(ctx); - - i915_ppgtt_close(&ctx->ppgtt->base); - - i915_gem_context_put(ctx); + context_close(ctx); } void mock_init_contexts(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/selftests/mock_engine.c b/drivers/gpu/drm/i915/selftests/mock_engine.c index fc0fd7498689..331c2b09869e 100644 --- a/drivers/gpu/drm/i915/selftests/mock_engine.c +++ b/drivers/gpu/drm/i915/selftests/mock_engine.c @@ -32,9 +32,9 @@ static struct mock_request *first_request(struct mock_engine *engine) link); } -static void hw_delay_complete(unsigned long data) +static void hw_delay_complete(struct timer_list *t) { - struct mock_engine *engine = (typeof(engine))data; + struct mock_engine *engine = from_timer(engine, t, hw_delay); struct mock_request *request; spin_lock(&engine->hw_lock); @@ -161,9 +161,7 @@ struct intel_engine_cs *mock_engine(struct drm_i915_private *i915, /* fake hw queue */ spin_lock_init(&engine->hw_lock); - setup_timer(&engine->hw_delay, - hw_delay_complete, - (unsigned long)engine); + timer_setup(&engine->hw_delay, hw_delay_complete, 0); INIT_LIST_HEAD(&engine->hw_queue); return &engine->base; diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 678723430d78..04eb9362f4f8 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -83,6 +83,8 @@ static void mock_device_release(struct drm_device *dev) kmem_cache_destroy(i915->vmas); kmem_cache_destroy(i915->objects); + i915_gemfs_fini(i915); + drm_dev_fini(&i915->drm); put_device(&i915->drm.pdev->dev); } @@ -146,6 +148,11 @@ struct drm_i915_private *mock_gem_device(void) dev_set_name(&pdev->dev, "mock"); dma_coerce_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); +#if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) + /* hack to disable iommu for the fake device; force identity mapping */ + pdev->dev.archdata.iommu = (void *)-1; +#endif + dev_pm_domain_set(&pdev->dev, &pm_domain); pm_runtime_enable(&pdev->dev); pm_runtime_dont_use_autosuspend(&pdev->dev); @@ -167,6 +174,11 @@ struct drm_i915_private *mock_gem_device(void) mkwrite_device_info(i915)->gen = -1; + mkwrite_device_info(i915)->page_sizes = + I915_GTT_PAGE_SIZE_4K | + I915_GTT_PAGE_SIZE_64K | + I915_GTT_PAGE_SIZE_2M; + spin_lock_init(&i915->mm.object_stat_lock); mock_uncore_init(i915); @@ -234,8 +246,16 @@ struct drm_i915_private *mock_gem_device(void) if (!i915->kernel_context) goto err_engine; + i915->preempt_context = mock_context(i915, NULL); + if (!i915->preempt_context) + goto err_kernel_context; + + WARN_ON(i915_gemfs_init(i915)); + return i915; +err_kernel_context: + i915_gem_context_put(i915->kernel_context); err_engine: for_each_engine(engine, i915, id) mock_engine_free(engine); diff --git a/drivers/gpu/drm/i915/selftests/mock_gtt.c b/drivers/gpu/drm/i915/selftests/mock_gtt.c index f2118cf535a0..336e1afb250f 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gtt.c +++ b/drivers/gpu/drm/i915/selftests/mock_gtt.c @@ -43,7 +43,6 @@ static int mock_bind_ppgtt(struct i915_vma *vma, u32 flags) { GEM_BUG_ON(flags & I915_VMA_GLOBAL_BIND); - vma->pages = vma->obj->mm.pages; vma->flags |= I915_VMA_LOCAL_BIND; return 0; } @@ -84,6 +83,8 @@ mock_ppgtt(struct drm_i915_private *i915, ppgtt->base.insert_entries = mock_insert_entries; ppgtt->base.bind_vma = mock_bind_ppgtt; ppgtt->base.unbind_vma = mock_unbind_ppgtt; + ppgtt->base.set_pages = ppgtt_set_pages; + ppgtt->base.clear_pages = clear_pages; ppgtt->base.cleanup = mock_cleanup; return ppgtt; @@ -93,12 +94,6 @@ static int mock_bind_ggtt(struct i915_vma *vma, enum i915_cache_level cache_level, u32 flags) { - int err; - - err = i915_get_ggtt_vma_pages(vma); - if (err) - return err; - vma->flags |= I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND; return 0; } @@ -124,6 +119,8 @@ void mock_init_ggtt(struct drm_i915_private *i915) ggtt->base.insert_entries = mock_insert_entries; ggtt->base.bind_vma = mock_bind_ggtt; ggtt->base.unbind_vma = mock_unbind_ggtt; + ggtt->base.set_pages = ggtt_set_pages; + ggtt->base.clear_pages = clear_pages; ggtt->base.cleanup = mock_cleanup; i915_address_space_init(&ggtt->base, i915, "global"); diff --git a/drivers/gpu/drm/i915/selftests/scatterlist.c b/drivers/gpu/drm/i915/selftests/scatterlist.c index 1cc5d2931753..cd6d2a16071f 100644 --- a/drivers/gpu/drm/i915/selftests/scatterlist.c +++ b/drivers/gpu/drm/i915/selftests/scatterlist.c @@ -189,6 +189,20 @@ static unsigned int random(unsigned long n, return 1 + (prandom_u32_state(rnd) % 1024); } +static unsigned int random_page_size_pages(unsigned long n, + unsigned long count, + struct rnd_state *rnd) +{ + /* 4K, 64K, 2M */ + static unsigned int page_count[] = { + BIT(12) >> PAGE_SHIFT, + BIT(16) >> PAGE_SHIFT, + BIT(21) >> PAGE_SHIFT, + }; + + return page_count[(prandom_u32_state(rnd) % 3)]; +} + static inline bool page_contiguous(struct page *first, struct page *last, unsigned long npages) @@ -252,6 +266,7 @@ static const npages_fn_t npages_funcs[] = { grow, shrink, random, + random_page_size_pages, NULL, }; diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index 5e9cd4c0e8b6..68e5d9c94475 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -1670,7 +1670,7 @@ static struct drm_encoder *mga_connector_best_encoder(struct drm_connector int enc_id = connector->encoder_ids[0]; /* pick the encoder ids */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 33008fa1be9b..d0b26dd80076 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -8,6 +8,7 @@ msm-y := \ adreno/a4xx_gpu.o \ adreno/a5xx_gpu.o \ adreno/a5xx_power.o \ + adreno/a5xx_preempt.o \ hdmi/hdmi.o \ hdmi/hdmi_audio.o \ hdmi/hdmi_bridge.o \ @@ -57,7 +58,8 @@ msm-y := \ msm_iommu.o \ msm_perf.o \ msm_rd.o \ - msm_ringbuffer.o + msm_ringbuffer.o \ + msm_submitqueue.o msm-$(CONFIG_DRM_FBDEV_EMULATION) += msm_fbdev.o msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c index 7791313405b5..4baef2738178 100644 --- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c @@ -44,7 +44,7 @@ static bool a3xx_idle(struct msm_gpu *gpu); static bool a3xx_me_init(struct msm_gpu *gpu) { - struct msm_ringbuffer *ring = gpu->rb; + struct msm_ringbuffer *ring = gpu->rb[0]; OUT_PKT3(ring, CP_ME_INIT, 17); OUT_RING(ring, 0x000003f7); @@ -65,7 +65,7 @@ static bool a3xx_me_init(struct msm_gpu *gpu) OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); - gpu->funcs->flush(gpu); + gpu->funcs->flush(gpu, ring); return a3xx_idle(gpu); } @@ -339,7 +339,7 @@ static void a3xx_destroy(struct msm_gpu *gpu) static bool a3xx_idle(struct msm_gpu *gpu) { /* wait for ringbuffer to drain: */ - if (!adreno_idle(gpu)) + if (!adreno_idle(gpu, gpu->rb[0])) return false; /* then wait for GPU to finish: */ @@ -444,9 +444,9 @@ static const struct adreno_gpu_funcs funcs = { .pm_suspend = msm_gpu_pm_suspend, .pm_resume = msm_gpu_pm_resume, .recover = a3xx_recover, - .last_fence = adreno_last_fence, .submit = adreno_submit, .flush = adreno_flush, + .active_ring = adreno_active_ring, .irq = a3xx_irq, .destroy = a3xx_destroy, #ifdef CONFIG_DEBUG_FS @@ -492,7 +492,7 @@ struct msm_gpu *a3xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = a3xx_registers; adreno_gpu->reg_offsets = a3xx_register_offsets; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c index 58341ef6f15b..8199a4b9f2fa 100644 --- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c @@ -116,7 +116,7 @@ static void a4xx_enable_hwcg(struct msm_gpu *gpu) static bool a4xx_me_init(struct msm_gpu *gpu) { - struct msm_ringbuffer *ring = gpu->rb; + struct msm_ringbuffer *ring = gpu->rb[0]; OUT_PKT3(ring, CP_ME_INIT, 17); OUT_RING(ring, 0x000003f7); @@ -137,7 +137,7 @@ static bool a4xx_me_init(struct msm_gpu *gpu) OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); - gpu->funcs->flush(gpu); + gpu->funcs->flush(gpu, ring); return a4xx_idle(gpu); } @@ -337,7 +337,7 @@ static void a4xx_destroy(struct msm_gpu *gpu) static bool a4xx_idle(struct msm_gpu *gpu) { /* wait for ringbuffer to drain: */ - if (!adreno_idle(gpu)) + if (!adreno_idle(gpu, gpu->rb[0])) return false; /* then wait for GPU to finish: */ @@ -532,9 +532,9 @@ static const struct adreno_gpu_funcs funcs = { .pm_suspend = a4xx_pm_suspend, .pm_resume = a4xx_pm_resume, .recover = a4xx_recover, - .last_fence = adreno_last_fence, .submit = adreno_submit, .flush = adreno_flush, + .active_ring = adreno_active_ring, .irq = a4xx_irq, .destroy = a4xx_destroy, #ifdef CONFIG_DEBUG_FS @@ -574,7 +574,7 @@ struct msm_gpu *a4xx_gpu_init(struct drm_device *dev) adreno_gpu->registers = a4xx_registers; adreno_gpu->reg_offsets = a4xx_register_offsets; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 1); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 17c59d839e6f..a1f4eeeb73e2 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -26,8 +26,9 @@ static void a5xx_dump(struct msm_gpu *gpu); #define GPU_PAS_ID 13 -static int zap_shader_load_mdt(struct device *dev, const char *fwname) +static int zap_shader_load_mdt(struct msm_gpu *gpu, const char *fwname) { + struct device *dev = &gpu->pdev->dev; const struct firmware *fw; struct device_node *np; struct resource r; @@ -55,10 +56,10 @@ static int zap_shader_load_mdt(struct device *dev, const char *fwname) mem_size = resource_size(&r); /* Request the MDT file for the firmware */ - ret = request_firmware(&fw, fwname, dev); - if (ret) { + fw = adreno_request_fw(to_adreno_gpu(gpu), fwname); + if (IS_ERR(fw)) { DRM_DEV_ERROR(dev, "Unable to load %s\n", fwname); - return ret; + return PTR_ERR(fw); } /* Figure out how much memory we need */ @@ -75,9 +76,26 @@ static int zap_shader_load_mdt(struct device *dev, const char *fwname) goto out; } - /* Load the rest of the MDT */ - ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID, mem_region, mem_phys, - mem_size); + /* + * Load the rest of the MDT + * + * Note that we could be dealing with two different paths, since + * with upstream linux-firmware it would be in a qcom/ subdir.. + * adreno_request_fw() handles this, but qcom_mdt_load() does + * not. But since we've already gotten thru adreno_request_fw() + * we know which of the two cases it is: + */ + if (to_adreno_gpu(gpu)->fwloc == FW_LOCATION_LEGACY) { + ret = qcom_mdt_load(dev, fw, fwname, GPU_PAS_ID, + mem_region, mem_phys, mem_size); + } else { + char newname[strlen("qcom/") + strlen(fwname) + 1]; + + sprintf(newname, "qcom/%s", fwname); + + ret = qcom_mdt_load(dev, fw, newname, GPU_PAS_ID, + mem_region, mem_phys, mem_size); + } if (ret) goto out; @@ -95,14 +113,65 @@ out: return ret; } +static void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + uint32_t wptr; + unsigned long flags; + + spin_lock_irqsave(&ring->lock, flags); + + /* Copy the shadow to the actual register */ + ring->cur = ring->next; + + /* Make sure to wrap wptr if we need to */ + wptr = get_wptr(ring); + + spin_unlock_irqrestore(&ring->lock, flags); + + /* Make sure everything is posted before making a decision */ + mb(); + + /* Update HW if this is the current ring and we are not in preempt */ + if (a5xx_gpu->cur_ring == ring && !a5xx_in_preempt(a5xx_gpu)) + gpu_write(gpu, REG_A5XX_CP_RB_WPTR, wptr); +} + static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, struct msm_file_private *ctx) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); struct msm_drm_private *priv = gpu->dev->dev_private; - struct msm_ringbuffer *ring = gpu->rb; + struct msm_ringbuffer *ring = submit->ring; unsigned int i, ibs = 0; + OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1); + OUT_RING(ring, 0x02); + + /* Turn off protected mode to write to special registers */ + OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); + OUT_RING(ring, 0); + + /* Set the save preemption record for the ring/command */ + OUT_PKT4(ring, REG_A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_LO, 2); + OUT_RING(ring, lower_32_bits(a5xx_gpu->preempt_iova[submit->ring->id])); + OUT_RING(ring, upper_32_bits(a5xx_gpu->preempt_iova[submit->ring->id])); + + /* Turn back on protected mode */ + OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); + OUT_RING(ring, 1); + + /* Enable local preemption for finegrain preemption */ + OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1); + OUT_RING(ring, 0x02); + + /* Allow CP_CONTEXT_SWITCH_YIELD packets in the IB2 */ + OUT_PKT7(ring, CP_YIELD_ENABLE, 1); + OUT_RING(ring, 0x02); + + /* Submit the commands */ for (i = 0; i < submit->nr_cmds; i++) { switch (submit->cmd[i].type) { case MSM_SUBMIT_CMD_IB_TARGET_BUF: @@ -120,16 +189,54 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, } } + /* + * Write the render mode to NULL (0) to indicate to the CP that the IBs + * are done rendering - otherwise a lucky preemption would start + * replaying from the last checkpoint + */ + OUT_PKT7(ring, CP_SET_RENDER_MODE, 5); + OUT_RING(ring, 0); + OUT_RING(ring, 0); + OUT_RING(ring, 0); + OUT_RING(ring, 0); + OUT_RING(ring, 0); + + /* Turn off IB level preemptions */ + OUT_PKT7(ring, CP_YIELD_ENABLE, 1); + OUT_RING(ring, 0x01); + + /* Write the fence to the scratch register */ OUT_PKT4(ring, REG_A5XX_CP_SCRATCH_REG(2), 1); - OUT_RING(ring, submit->fence->seqno); + OUT_RING(ring, submit->seqno); + /* + * Execute a CACHE_FLUSH_TS event. This will ensure that the + * timestamp is written to the memory and then triggers the interrupt + */ OUT_PKT7(ring, CP_EVENT_WRITE, 4); OUT_RING(ring, CACHE_FLUSH_TS | (1 << 31)); - OUT_RING(ring, lower_32_bits(rbmemptr(adreno_gpu, fence))); - OUT_RING(ring, upper_32_bits(rbmemptr(adreno_gpu, fence))); - OUT_RING(ring, submit->fence->seqno); + OUT_RING(ring, lower_32_bits(rbmemptr(ring, fence))); + OUT_RING(ring, upper_32_bits(rbmemptr(ring, fence))); + OUT_RING(ring, submit->seqno); - gpu->funcs->flush(gpu); + /* Yield the floor on command completion */ + OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4); + /* + * If dword[2:1] are non zero, they specify an address for the CP to + * write the value of dword[3] to on preemption complete. Write 0 to + * skip the write + */ + OUT_RING(ring, 0x00); + OUT_RING(ring, 0x00); + /* Data value - not used if the address above is 0 */ + OUT_RING(ring, 0x01); + /* Set bit 0 to trigger an interrupt on preempt complete */ + OUT_RING(ring, 0x01); + + a5xx_flush(gpu, ring); + + /* Check to see if we need to start preemption */ + a5xx_preempt_trigger(gpu); } static const struct { @@ -245,7 +352,7 @@ void a5xx_set_hwcg(struct msm_gpu *gpu, bool state) static int a5xx_me_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - struct msm_ringbuffer *ring = gpu->rb; + struct msm_ringbuffer *ring = gpu->rb[0]; OUT_PKT7(ring, CP_ME_INIT, 8); @@ -276,11 +383,54 @@ static int a5xx_me_init(struct msm_gpu *gpu) OUT_RING(ring, 0x00000000); OUT_RING(ring, 0x00000000); - gpu->funcs->flush(gpu); + gpu->funcs->flush(gpu, ring); + return a5xx_idle(gpu, ring) ? 0 : -EINVAL; +} + +static int a5xx_preempt_start(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + struct msm_ringbuffer *ring = gpu->rb[0]; + + if (gpu->nr_rings == 1) + return 0; + + /* Turn off protected mode to write to special registers */ + OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); + OUT_RING(ring, 0); + + /* Set the save preemption record for the ring/command */ + OUT_PKT4(ring, REG_A5XX_CP_CONTEXT_SWITCH_SAVE_ADDR_LO, 2); + OUT_RING(ring, lower_32_bits(a5xx_gpu->preempt_iova[ring->id])); + OUT_RING(ring, upper_32_bits(a5xx_gpu->preempt_iova[ring->id])); + + /* Turn back on protected mode */ + OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); + OUT_RING(ring, 1); + + OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1); + OUT_RING(ring, 0x00); + + OUT_PKT7(ring, CP_PREEMPT_ENABLE_LOCAL, 1); + OUT_RING(ring, 0x01); - return a5xx_idle(gpu) ? 0 : -EINVAL; + OUT_PKT7(ring, CP_YIELD_ENABLE, 1); + OUT_RING(ring, 0x01); + + /* Yield the floor on command completion */ + OUT_PKT7(ring, CP_CONTEXT_SWITCH_YIELD, 4); + OUT_RING(ring, 0x00); + OUT_RING(ring, 0x00); + OUT_RING(ring, 0x01); + OUT_RING(ring, 0x01); + + gpu->funcs->flush(gpu, ring); + + return a5xx_idle(gpu, ring) ? 0 : -EINVAL; } + static struct drm_gem_object *a5xx_ucode_load_bo(struct msm_gpu *gpu, const struct firmware *fw, u64 *iova) { @@ -381,7 +531,7 @@ static int a5xx_zap_shader_init(struct msm_gpu *gpu) return -ENODEV; } - ret = zap_shader_load_mdt(&pdev->dev, adreno_gpu->info->zapfw); + ret = zap_shader_load_mdt(gpu, adreno_gpu->info->zapfw); loaded = !ret; @@ -396,6 +546,7 @@ static int a5xx_zap_shader_init(struct msm_gpu *gpu) A5XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNC_OVERFLOW | \ A5XX_RBBM_INT_0_MASK_CP_HW_ERROR | \ A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT | \ + A5XX_RBBM_INT_0_MASK_CP_SW | \ A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS | \ A5XX_RBBM_INT_0_MASK_UCHE_OOB_ACCESS | \ A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP) @@ -536,13 +687,14 @@ static int a5xx_hw_init(struct msm_gpu *gpu) REG_A5XX_RBBM_SECVID_TSB_TRUSTED_BASE_HI, 0x00000000); gpu_write(gpu, REG_A5XX_RBBM_SECVID_TSB_TRUSTED_SIZE, 0x00000000); - /* Load the GPMU firmware before starting the HW init */ - a5xx_gpmu_ucode_init(gpu); - ret = adreno_hw_init(gpu); if (ret) return ret; + a5xx_preempt_hw_init(gpu); + + a5xx_gpmu_ucode_init(gpu); + ret = a5xx_ucode_init(gpu); if (ret) return ret; @@ -565,11 +717,11 @@ static int a5xx_hw_init(struct msm_gpu *gpu) * ticking correctly */ if (adreno_is_a530(adreno_gpu)) { - OUT_PKT7(gpu->rb, CP_EVENT_WRITE, 1); - OUT_RING(gpu->rb, 0x0F); + OUT_PKT7(gpu->rb[0], CP_EVENT_WRITE, 1); + OUT_RING(gpu->rb[0], 0x0F); - gpu->funcs->flush(gpu); - if (!a5xx_idle(gpu)) + gpu->funcs->flush(gpu, gpu->rb[0]); + if (!a5xx_idle(gpu, gpu->rb[0])) return -EINVAL; } @@ -582,11 +734,11 @@ static int a5xx_hw_init(struct msm_gpu *gpu) */ ret = a5xx_zap_shader_init(gpu); if (!ret) { - OUT_PKT7(gpu->rb, CP_SET_SECURE_MODE, 1); - OUT_RING(gpu->rb, 0x00000000); + OUT_PKT7(gpu->rb[0], CP_SET_SECURE_MODE, 1); + OUT_RING(gpu->rb[0], 0x00000000); - gpu->funcs->flush(gpu); - if (!a5xx_idle(gpu)) + gpu->funcs->flush(gpu, gpu->rb[0]); + if (!a5xx_idle(gpu, gpu->rb[0])) return -EINVAL; } else { /* Print a warning so if we die, we know why */ @@ -595,6 +747,9 @@ static int a5xx_hw_init(struct msm_gpu *gpu) gpu_write(gpu, REG_A5XX_RBBM_SECVID_TRUST_CNTL, 0x0); } + /* Last step - yield the ringbuffer */ + a5xx_preempt_start(gpu); + return 0; } @@ -625,6 +780,8 @@ static void a5xx_destroy(struct msm_gpu *gpu) DBG("%s", gpu->name); + a5xx_preempt_fini(gpu); + if (a5xx_gpu->pm4_bo) { if (a5xx_gpu->pm4_iova) msm_gem_put_iova(a5xx_gpu->pm4_bo, gpu->aspace); @@ -660,18 +817,27 @@ static inline bool _a5xx_check_idle(struct msm_gpu *gpu) A5XX_RBBM_INT_0_MASK_MISC_HANG_DETECT); } -bool a5xx_idle(struct msm_gpu *gpu) +bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring) { + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + + if (ring != a5xx_gpu->cur_ring) { + WARN(1, "Tried to idle a non-current ringbuffer\n"); + return false; + } + /* wait for CP to drain ringbuffer: */ - if (!adreno_idle(gpu)) + if (!adreno_idle(gpu, ring)) return false; if (spin_until(_a5xx_check_idle(gpu))) { - DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X\n", + DRM_ERROR("%s: %ps: timeout waiting for GPU to idle: status %8.8X irq %8.8X rptr/wptr %d/%d\n", gpu->name, __builtin_return_address(0), gpu_read(gpu, REG_A5XX_RBBM_STATUS), - gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS)); - + gpu_read(gpu, REG_A5XX_RBBM_INT_0_STATUS), + gpu_read(gpu, REG_A5XX_CP_RB_RPTR), + gpu_read(gpu, REG_A5XX_CP_RB_WPTR)); return false; } @@ -802,9 +968,10 @@ static void a5xx_fault_detect_irq(struct msm_gpu *gpu) { struct drm_device *dev = gpu->dev; struct msm_drm_private *priv = dev->dev_private; + struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu); - dev_err(dev->dev, "gpu fault fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n", - gpu->funcs->last_fence(gpu), + dev_err(dev->dev, "gpu fault ring %d fence %x status %8.8X rb %4.4x/%4.4x ib1 %16.16llX/%4.4x ib2 %16.16llX/%4.4x\n", + ring ? ring->id : -1, ring ? ring->seqno : 0, gpu_read(gpu, REG_A5XX_RBBM_STATUS), gpu_read(gpu, REG_A5XX_CP_RB_RPTR), gpu_read(gpu, REG_A5XX_CP_RB_WPTR), @@ -854,8 +1021,13 @@ static irqreturn_t a5xx_irq(struct msm_gpu *gpu) if (status & A5XX_RBBM_INT_0_MASK_GPMU_VOLTAGE_DROOP) a5xx_gpmu_err_irq(gpu); - if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) + if (status & A5XX_RBBM_INT_0_MASK_CP_CACHE_FLUSH_TS) { + a5xx_preempt_trigger(gpu); msm_gpu_retire(gpu); + } + + if (status & A5XX_RBBM_INT_0_MASK_CP_SW) + a5xx_preempt_irq(gpu); return IRQ_HANDLED; } @@ -985,6 +1157,14 @@ static void a5xx_show(struct msm_gpu *gpu, struct seq_file *m) } #endif +static struct msm_ringbuffer *a5xx_active_ring(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + + return a5xx_gpu->cur_ring; +} + static const struct adreno_gpu_funcs funcs = { .base = { .get_param = adreno_get_param, @@ -992,9 +1172,9 @@ static const struct adreno_gpu_funcs funcs = { .pm_suspend = a5xx_pm_suspend, .pm_resume = a5xx_pm_resume, .recover = a5xx_recover, - .last_fence = adreno_last_fence, .submit = a5xx_submit, - .flush = adreno_flush, + .flush = a5xx_flush, + .active_ring = a5xx_active_ring, .irq = a5xx_irq, .destroy = a5xx_destroy, #ifdef CONFIG_DEBUG_FS @@ -1030,7 +1210,7 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) a5xx_gpu->lm_leakage = 0x4E001A; - ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs); + ret = adreno_gpu_init(dev, pdev, adreno_gpu, &funcs, 4); if (ret) { a5xx_destroy(&(a5xx_gpu->base.base)); return ERR_PTR(ret); @@ -1039,5 +1219,8 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev) if (gpu->aspace) msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, a5xx_fault_handler); + /* Set up the preemption specific bits and pieces for each ringbuffer */ + a5xx_preempt_init(gpu); + return gpu; } diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h index e94451685bf8..6fb8c2f9b9e4 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.h +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2016 The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -35,10 +35,100 @@ struct a5xx_gpu { uint32_t gpmu_dwords; uint32_t lm_leakage; + + struct msm_ringbuffer *cur_ring; + struct msm_ringbuffer *next_ring; + + struct drm_gem_object *preempt_bo[MSM_GPU_MAX_RINGS]; + struct a5xx_preempt_record *preempt[MSM_GPU_MAX_RINGS]; + uint64_t preempt_iova[MSM_GPU_MAX_RINGS]; + + atomic_t preempt_state; + struct timer_list preempt_timer; }; #define to_a5xx_gpu(x) container_of(x, struct a5xx_gpu, base) +/* + * In order to do lockless preemption we use a simple state machine to progress + * through the process. + * + * PREEMPT_NONE - no preemption in progress. Next state START. + * PREEMPT_START - The trigger is evaulating if preemption is possible. Next + * states: TRIGGERED, NONE + * PREEMPT_ABORT - An intermediate state before moving back to NONE. Next + * state: NONE. + * PREEMPT_TRIGGERED: A preemption has been executed on the hardware. Next + * states: FAULTED, PENDING + * PREEMPT_FAULTED: A preemption timed out (never completed). This will trigger + * recovery. Next state: N/A + * PREEMPT_PENDING: Preemption complete interrupt fired - the callback is + * checking the success of the operation. Next state: FAULTED, NONE. + */ + +enum preempt_state { + PREEMPT_NONE = 0, + PREEMPT_START, + PREEMPT_ABORT, + PREEMPT_TRIGGERED, + PREEMPT_FAULTED, + PREEMPT_PENDING, +}; + +/* + * struct a5xx_preempt_record is a shared buffer between the microcode and the + * CPU to store the state for preemption. The record itself is much larger + * (64k) but most of that is used by the CP for storage. + * + * There is a preemption record assigned per ringbuffer. When the CPU triggers a + * preemption, it fills out the record with the useful information (wptr, ring + * base, etc) and the microcode uses that information to set up the CP following + * the preemption. When a ring is switched out, the CP will save the ringbuffer + * state back to the record. In this way, once the records are properly set up + * the CPU can quickly switch back and forth between ringbuffers by only + * updating a few registers (often only the wptr). + * + * These are the CPU aware registers in the record: + * @magic: Must always be 0x27C4BAFC + * @info: Type of the record - written 0 by the CPU, updated by the CP + * @data: Data field from SET_RENDER_MODE or a checkpoint. Written and used by + * the CP + * @cntl: Value of RB_CNTL written by CPU, save/restored by CP + * @rptr: Value of RB_RPTR written by CPU, save/restored by CP + * @wptr: Value of RB_WPTR written by CPU, save/restored by CP + * @rptr_addr: Value of RB_RPTR_ADDR written by CPU, save/restored by CP + * @rbase: Value of RB_BASE written by CPU, save/restored by CP + * @counter: GPU address of the storage area for the performance counters + */ +struct a5xx_preempt_record { + uint32_t magic; + uint32_t info; + uint32_t data; + uint32_t cntl; + uint32_t rptr; + uint32_t wptr; + uint64_t rptr_addr; + uint64_t rbase; + uint64_t counter; +}; + +/* Magic identifier for the preemption record */ +#define A5XX_PREEMPT_RECORD_MAGIC 0x27C4BAFCUL + +/* + * Even though the structure above is only a few bytes, we need a full 64k to + * store the entire preemption record from the CP + */ +#define A5XX_PREEMPT_RECORD_SIZE (64 * 1024) + +/* + * The preemption counter block is a storage area for the value of the + * preemption counters that are saved immediately before context switch. We + * append it on to the end of the allocation for the preemption record. + */ +#define A5XX_PREEMPT_COUNTER_SIZE (16 * 4) + + int a5xx_power_init(struct msm_gpu *gpu); void a5xx_gpmu_ucode_init(struct msm_gpu *gpu); @@ -55,7 +145,22 @@ static inline int spin_usecs(struct msm_gpu *gpu, uint32_t usecs, return -ETIMEDOUT; } -bool a5xx_idle(struct msm_gpu *gpu); +bool a5xx_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring); void a5xx_set_hwcg(struct msm_gpu *gpu, bool state); +void a5xx_preempt_init(struct msm_gpu *gpu); +void a5xx_preempt_hw_init(struct msm_gpu *gpu); +void a5xx_preempt_trigger(struct msm_gpu *gpu); +void a5xx_preempt_irq(struct msm_gpu *gpu); +void a5xx_preempt_fini(struct msm_gpu *gpu); + +/* Return true if we are in a preempt state */ +static inline bool a5xx_in_preempt(struct a5xx_gpu *a5xx_gpu) +{ + int preempt_state = atomic_read(&a5xx_gpu->preempt_state); + + return !(preempt_state == PREEMPT_NONE || + preempt_state == PREEMPT_ABORT); +} + #endif /* __A5XX_GPU_H__ */ diff --git a/drivers/gpu/drm/msm/adreno/a5xx_power.c b/drivers/gpu/drm/msm/adreno/a5xx_power.c index 04aab1dcae2b..e5700bbf09dd 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_power.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_power.c @@ -173,7 +173,7 @@ static int a5xx_gpmu_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); - struct msm_ringbuffer *ring = gpu->rb; + struct msm_ringbuffer *ring = gpu->rb[0]; if (!a5xx_gpu->gpmu_dwords) return 0; @@ -192,9 +192,9 @@ static int a5xx_gpmu_init(struct msm_gpu *gpu) OUT_PKT7(ring, CP_SET_PROTECTED_MODE, 1); OUT_RING(ring, 1); - gpu->funcs->flush(gpu); + gpu->funcs->flush(gpu, ring); - if (!a5xx_idle(gpu)) { + if (!a5xx_idle(gpu, ring)) { DRM_ERROR("%s: Unable to load GPMU firmware. GPMU will not be active\n", gpu->name); return -EINVAL; @@ -264,7 +264,8 @@ void a5xx_gpmu_ucode_init(struct msm_gpu *gpu) return; /* Get the firmware */ - if (request_firmware(&fw, adreno_gpu->info->gpmufw, drm->dev)) { + fw = adreno_request_fw(adreno_gpu, adreno_gpu->info->gpmufw); + if (IS_ERR(fw)) { DRM_ERROR("%s: Could not get GPMU firmware. GPMU will not be active\n", gpu->name); return; diff --git a/drivers/gpu/drm/msm/adreno/a5xx_preempt.c b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c new file mode 100644 index 000000000000..40f4840ef98e --- /dev/null +++ b/drivers/gpu/drm/msm/adreno/a5xx_preempt.c @@ -0,0 +1,305 @@ +/* Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "msm_gem.h" +#include "a5xx_gpu.h" + +/* + * Try to transition the preemption state from old to new. Return + * true on success or false if the original state wasn't 'old' + */ +static inline bool try_preempt_state(struct a5xx_gpu *a5xx_gpu, + enum preempt_state old, enum preempt_state new) +{ + enum preempt_state cur = atomic_cmpxchg(&a5xx_gpu->preempt_state, + old, new); + + return (cur == old); +} + +/* + * Force the preemption state to the specified state. This is used in cases + * where the current state is known and won't change + */ +static inline void set_preempt_state(struct a5xx_gpu *gpu, + enum preempt_state new) +{ + /* + * preempt_state may be read by other cores trying to trigger a + * preemption or in the interrupt handler so barriers are needed + * before... + */ + smp_mb__before_atomic(); + atomic_set(&gpu->preempt_state, new); + /* ... and after*/ + smp_mb__after_atomic(); +} + +/* Write the most recent wptr for the given ring into the hardware */ +static inline void update_wptr(struct msm_gpu *gpu, struct msm_ringbuffer *ring) +{ + unsigned long flags; + uint32_t wptr; + + if (!ring) + return; + + spin_lock_irqsave(&ring->lock, flags); + wptr = get_wptr(ring); + spin_unlock_irqrestore(&ring->lock, flags); + + gpu_write(gpu, REG_A5XX_CP_RB_WPTR, wptr); +} + +/* Return the highest priority ringbuffer with something in it */ +static struct msm_ringbuffer *get_next_ring(struct msm_gpu *gpu) +{ + unsigned long flags; + int i; + + for (i = 0; i < gpu->nr_rings; i++) { + bool empty; + struct msm_ringbuffer *ring = gpu->rb[i]; + + spin_lock_irqsave(&ring->lock, flags); + empty = (get_wptr(ring) == ring->memptrs->rptr); + spin_unlock_irqrestore(&ring->lock, flags); + + if (!empty) + return ring; + } + + return NULL; +} + +static void a5xx_preempt_timer(unsigned long data) +{ + struct a5xx_gpu *a5xx_gpu = (struct a5xx_gpu *) data; + struct msm_gpu *gpu = &a5xx_gpu->base.base; + struct drm_device *dev = gpu->dev; + struct msm_drm_private *priv = dev->dev_private; + + if (!try_preempt_state(a5xx_gpu, PREEMPT_TRIGGERED, PREEMPT_FAULTED)) + return; + + dev_err(dev->dev, "%s: preemption timed out\n", gpu->name); + queue_work(priv->wq, &gpu->recover_work); +} + +/* Try to trigger a preemption switch */ +void a5xx_preempt_trigger(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + unsigned long flags; + struct msm_ringbuffer *ring; + + if (gpu->nr_rings == 1) + return; + + /* + * Try to start preemption by moving from NONE to START. If + * unsuccessful, a preemption is already in flight + */ + if (!try_preempt_state(a5xx_gpu, PREEMPT_NONE, PREEMPT_START)) + return; + + /* Get the next ring to preempt to */ + ring = get_next_ring(gpu); + + /* + * If no ring is populated or the highest priority ring is the current + * one do nothing except to update the wptr to the latest and greatest + */ + if (!ring || (a5xx_gpu->cur_ring == ring)) { + /* + * Its possible that while a preemption request is in progress + * from an irq context, a user context trying to submit might + * fail to update the write pointer, because it determines + * that the preempt state is not PREEMPT_NONE. + * + * Close the race by introducing an intermediate + * state PREEMPT_ABORT to let the submit path + * know that the ringbuffer is not going to change + * and can safely update the write pointer. + */ + + set_preempt_state(a5xx_gpu, PREEMPT_ABORT); + update_wptr(gpu, a5xx_gpu->cur_ring); + set_preempt_state(a5xx_gpu, PREEMPT_NONE); + return; + } + + /* Make sure the wptr doesn't update while we're in motion */ + spin_lock_irqsave(&ring->lock, flags); + a5xx_gpu->preempt[ring->id]->wptr = get_wptr(ring); + spin_unlock_irqrestore(&ring->lock, flags); + + /* Set the address of the incoming preemption record */ + gpu_write64(gpu, REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_LO, + REG_A5XX_CP_CONTEXT_SWITCH_RESTORE_ADDR_HI, + a5xx_gpu->preempt_iova[ring->id]); + + a5xx_gpu->next_ring = ring; + + /* Start a timer to catch a stuck preemption */ + mod_timer(&a5xx_gpu->preempt_timer, jiffies + msecs_to_jiffies(10000)); + + /* Set the preemption state to triggered */ + set_preempt_state(a5xx_gpu, PREEMPT_TRIGGERED); + + /* Make sure everything is written before hitting the button */ + wmb(); + + /* And actually start the preemption */ + gpu_write(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL, 1); +} + +void a5xx_preempt_irq(struct msm_gpu *gpu) +{ + uint32_t status; + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + struct drm_device *dev = gpu->dev; + struct msm_drm_private *priv = dev->dev_private; + + if (!try_preempt_state(a5xx_gpu, PREEMPT_TRIGGERED, PREEMPT_PENDING)) + return; + + /* Delete the preemption watchdog timer */ + del_timer(&a5xx_gpu->preempt_timer); + + /* + * The hardware should be setting CP_CONTEXT_SWITCH_CNTL to zero before + * firing the interrupt, but there is a non zero chance of a hardware + * condition or a software race that could set it again before we have a + * chance to finish. If that happens, log and go for recovery + */ + status = gpu_read(gpu, REG_A5XX_CP_CONTEXT_SWITCH_CNTL); + if (unlikely(status)) { + set_preempt_state(a5xx_gpu, PREEMPT_FAULTED); + dev_err(dev->dev, "%s: Preemption failed to complete\n", + gpu->name); + queue_work(priv->wq, &gpu->recover_work); + return; + } + + a5xx_gpu->cur_ring = a5xx_gpu->next_ring; + a5xx_gpu->next_ring = NULL; + + update_wptr(gpu, a5xx_gpu->cur_ring); + + set_preempt_state(a5xx_gpu, PREEMPT_NONE); +} + +void a5xx_preempt_hw_init(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + int i; + + for (i = 0; i < gpu->nr_rings; i++) { + a5xx_gpu->preempt[i]->wptr = 0; + a5xx_gpu->preempt[i]->rptr = 0; + a5xx_gpu->preempt[i]->rbase = gpu->rb[i]->iova; + } + + /* Write a 0 to signal that we aren't switching pagetables */ + gpu_write64(gpu, REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_LO, + REG_A5XX_CP_CONTEXT_SWITCH_SMMU_INFO_HI, 0); + + /* Reset the preemption state */ + set_preempt_state(a5xx_gpu, PREEMPT_NONE); + + /* Always come up on rb 0 */ + a5xx_gpu->cur_ring = gpu->rb[0]; +} + +static int preempt_init_ring(struct a5xx_gpu *a5xx_gpu, + struct msm_ringbuffer *ring) +{ + struct adreno_gpu *adreno_gpu = &a5xx_gpu->base; + struct msm_gpu *gpu = &adreno_gpu->base; + struct a5xx_preempt_record *ptr; + struct drm_gem_object *bo = NULL; + u64 iova = 0; + + ptr = msm_gem_kernel_new(gpu->dev, + A5XX_PREEMPT_RECORD_SIZE + A5XX_PREEMPT_COUNTER_SIZE, + MSM_BO_UNCACHED, gpu->aspace, &bo, &iova); + + if (IS_ERR(ptr)) + return PTR_ERR(ptr); + + a5xx_gpu->preempt_bo[ring->id] = bo; + a5xx_gpu->preempt_iova[ring->id] = iova; + a5xx_gpu->preempt[ring->id] = ptr; + + /* Set up the defaults on the preemption record */ + + ptr->magic = A5XX_PREEMPT_RECORD_MAGIC; + ptr->info = 0; + ptr->data = 0; + ptr->cntl = MSM_GPU_RB_CNTL_DEFAULT; + ptr->rptr_addr = rbmemptr(ring, rptr); + ptr->counter = iova + A5XX_PREEMPT_RECORD_SIZE; + + return 0; +} + +void a5xx_preempt_fini(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + int i; + + for (i = 0; i < gpu->nr_rings; i++) { + if (!a5xx_gpu->preempt_bo[i]) + continue; + + msm_gem_put_vaddr(a5xx_gpu->preempt_bo[i]); + + if (a5xx_gpu->preempt_iova[i]) + msm_gem_put_iova(a5xx_gpu->preempt_bo[i], gpu->aspace); + + drm_gem_object_unreference(a5xx_gpu->preempt_bo[i]); + a5xx_gpu->preempt_bo[i] = NULL; + } +} + +void a5xx_preempt_init(struct msm_gpu *gpu) +{ + struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu); + int i; + + /* No preemption if we only have one ring */ + if (gpu->nr_rings <= 1) + return; + + for (i = 0; i < gpu->nr_rings; i++) { + if (preempt_init_ring(a5xx_gpu, gpu->rb[i])) { + /* + * On any failure our adventure is over. Clean up and + * set nr_rings to 1 to force preemption off + */ + a5xx_preempt_fini(gpu); + gpu->nr_rings = 1; + + return; + } + } + + setup_timer(&a5xx_gpu->preempt_timer, a5xx_preempt_timer, + (unsigned long) a5xx_gpu); +} diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c index c75c4df4bc39..05022ea2a007 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_device.c +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c @@ -125,51 +125,24 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev) { struct msm_drm_private *priv = dev->dev_private; struct platform_device *pdev = priv->gpu_pdev; - struct adreno_platform_config *config; - struct adreno_rev rev; - const struct adreno_info *info; - struct msm_gpu *gpu = NULL; + struct msm_gpu *gpu = platform_get_drvdata(priv->gpu_pdev); + int ret; - if (!pdev) { + if (!gpu) { dev_err(dev->dev, "no adreno device\n"); return NULL; } - config = pdev->dev.platform_data; - rev = config->rev; - info = adreno_info(config->rev); - - if (!info) { - dev_warn(dev->dev, "Unknown GPU revision: %u.%u.%u.%u\n", - rev.core, rev.major, rev.minor, rev.patchid); + pm_runtime_get_sync(&pdev->dev); + mutex_lock(&dev->struct_mutex); + ret = msm_gpu_hw_init(gpu); + mutex_unlock(&dev->struct_mutex); + pm_runtime_put_sync(&pdev->dev); + if (ret) { + dev_err(dev->dev, "gpu hw init failed: %d\n", ret); return NULL; } - DBG("Found GPU: %u.%u.%u.%u", rev.core, rev.major, - rev.minor, rev.patchid); - - gpu = info->init(dev); - if (IS_ERR(gpu)) { - dev_warn(dev->dev, "failed to load adreno gpu\n"); - gpu = NULL; - /* not fatal */ - } - - if (gpu) { - int ret; - - pm_runtime_get_sync(&pdev->dev); - mutex_lock(&dev->struct_mutex); - ret = msm_gpu_hw_init(gpu); - mutex_unlock(&dev->struct_mutex); - pm_runtime_put_sync(&pdev->dev); - if (ret) { - dev_err(dev->dev, "gpu hw init failed: %d\n", ret); - gpu->funcs->destroy(gpu); - gpu = NULL; - } - } - return gpu; } @@ -282,6 +255,9 @@ static int adreno_get_pwrlevels(struct device *dev, static int adreno_bind(struct device *dev, struct device *master, void *data) { static struct adreno_platform_config config = {}; + const struct adreno_info *info; + struct drm_device *drm = dev_get_drvdata(master); + struct msm_gpu *gpu; u32 val; int ret; @@ -302,13 +278,39 @@ static int adreno_bind(struct device *dev, struct device *master, void *data) return ret; dev->platform_data = &config; - set_gpu_pdev(dev_get_drvdata(master), to_platform_device(dev)); + set_gpu_pdev(drm, to_platform_device(dev)); + + info = adreno_info(config.rev); + + if (!info) { + dev_warn(drm->dev, "Unknown GPU revision: %u.%u.%u.%u\n", + config.rev.core, config.rev.major, + config.rev.minor, config.rev.patchid); + return -ENXIO; + } + + DBG("Found GPU: %u.%u.%u.%u", config.rev.core, config.rev.major, + config.rev.minor, config.rev.patchid); + + gpu = info->init(drm); + if (IS_ERR(gpu)) { + dev_warn(drm->dev, "failed to load adreno gpu\n"); + return PTR_ERR(gpu); + } + + dev_set_drvdata(dev, gpu); + return 0; } static void adreno_unbind(struct device *dev, struct device *master, void *data) { + struct msm_gpu *gpu = dev_get_drvdata(dev); + + gpu->funcs->pm_suspend(gpu); + gpu->funcs->destroy(gpu); + set_gpu_pdev(dev_get_drvdata(master), NULL); } diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c index c8b4ac254bb5..e2ffecce59a3 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c @@ -21,8 +21,6 @@ #include "msm_gem.h" #include "msm_mmu.h" -#define RB_SIZE SZ_32K -#define RB_BLKSIZE 32 int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) { @@ -58,72 +56,181 @@ int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value) return ret; } return -EINVAL; + case MSM_PARAM_NR_RINGS: + *value = gpu->nr_rings; + return 0; default: DBG("%s: invalid param: %u", gpu->name, param); return -EINVAL; } } +const struct firmware * +adreno_request_fw(struct adreno_gpu *adreno_gpu, const char *fwname) +{ + struct drm_device *drm = adreno_gpu->base.dev; + const struct firmware *fw = NULL; + char newname[strlen("qcom/") + strlen(fwname) + 1]; + int ret; + + sprintf(newname, "qcom/%s", fwname); + + /* + * Try first to load from qcom/$fwfile using a direct load (to avoid + * a potential timeout waiting for usermode helper) + */ + if ((adreno_gpu->fwloc == FW_LOCATION_UNKNOWN) || + (adreno_gpu->fwloc == FW_LOCATION_NEW)) { + + ret = request_firmware_direct(&fw, newname, drm->dev); + if (!ret) { + dev_info(drm->dev, "loaded %s from new location\n", + newname); + adreno_gpu->fwloc = FW_LOCATION_NEW; + return fw; + } else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) { + dev_err(drm->dev, "failed to load %s: %d\n", + newname, ret); + return ERR_PTR(ret); + } + } + + /* + * Then try the legacy location without qcom/ prefix + */ + if ((adreno_gpu->fwloc == FW_LOCATION_UNKNOWN) || + (adreno_gpu->fwloc == FW_LOCATION_LEGACY)) { + + ret = request_firmware_direct(&fw, fwname, drm->dev); + if (!ret) { + dev_info(drm->dev, "loaded %s from legacy location\n", + newname); + adreno_gpu->fwloc = FW_LOCATION_LEGACY; + return fw; + } else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) { + dev_err(drm->dev, "failed to load %s: %d\n", + fwname, ret); + return ERR_PTR(ret); + } + } + + /* + * Finally fall back to request_firmware() for cases where the + * usermode helper is needed (I think mainly android) + */ + if ((adreno_gpu->fwloc == FW_LOCATION_UNKNOWN) || + (adreno_gpu->fwloc == FW_LOCATION_HELPER)) { + + ret = request_firmware(&fw, newname, drm->dev); + if (!ret) { + dev_info(drm->dev, "loaded %s with helper\n", + newname); + adreno_gpu->fwloc = FW_LOCATION_HELPER; + return fw; + } else if (adreno_gpu->fwloc != FW_LOCATION_UNKNOWN) { + dev_err(drm->dev, "failed to load %s: %d\n", + newname, ret); + return ERR_PTR(ret); + } + } + + dev_err(drm->dev, "failed to load %s\n", fwname); + return ERR_PTR(-ENOENT); +} + +static int adreno_load_fw(struct adreno_gpu *adreno_gpu) +{ + const struct firmware *fw; + + if (adreno_gpu->pm4) + return 0; + + fw = adreno_request_fw(adreno_gpu, adreno_gpu->info->pm4fw); + if (IS_ERR(fw)) + return PTR_ERR(fw); + adreno_gpu->pm4 = fw; + + fw = adreno_request_fw(adreno_gpu, adreno_gpu->info->pfpfw); + if (IS_ERR(fw)) { + release_firmware(adreno_gpu->pm4); + adreno_gpu->pm4 = NULL; + return PTR_ERR(fw); + } + adreno_gpu->pfp = fw; + + return 0; +} + int adreno_hw_init(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - int ret; + int ret, i; DBG("%s", gpu->name); - ret = msm_gem_get_iova(gpu->rb->bo, gpu->aspace, &gpu->rb_iova); - if (ret) { - gpu->rb_iova = 0; - dev_err(gpu->dev->dev, "could not map ringbuffer: %d\n", ret); + ret = adreno_load_fw(adreno_gpu); + if (ret) return ret; - } - /* reset ringbuffer: */ - gpu->rb->cur = gpu->rb->start; + for (i = 0; i < gpu->nr_rings; i++) { + struct msm_ringbuffer *ring = gpu->rb[i]; + + if (!ring) + continue; + + ret = msm_gem_get_iova(ring->bo, gpu->aspace, &ring->iova); + if (ret) { + ring->iova = 0; + dev_err(gpu->dev->dev, + "could not map ringbuffer %d: %d\n", i, ret); + return ret; + } + + ring->cur = ring->start; + ring->next = ring->start; - /* reset completed fence seqno: */ - adreno_gpu->memptrs->fence = gpu->fctx->completed_fence; - adreno_gpu->memptrs->rptr = 0; + /* reset completed fence seqno: */ + ring->memptrs->fence = ring->seqno; + ring->memptrs->rptr = 0; + } - /* Setup REG_CP_RB_CNTL: */ + /* + * Setup REG_CP_RB_CNTL. The same value is used across targets (with + * the excpetion of A430 that disables the RPTR shadow) - the cacluation + * for the ringbuffer size and block size is moved to msm_gpu.h for the + * pre-processor to deal with and the A430 variant is ORed in here + */ adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_CNTL, - /* size is log2(quad-words): */ - AXXX_CP_RB_CNTL_BUFSZ(ilog2(gpu->rb->size / 8)) | - AXXX_CP_RB_CNTL_BLKSZ(ilog2(RB_BLKSIZE / 8)) | - (adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0)); + MSM_GPU_RB_CNTL_DEFAULT | + (adreno_is_a430(adreno_gpu) ? AXXX_CP_RB_CNTL_NO_UPDATE : 0)); - /* Setup ringbuffer address: */ + /* Setup ringbuffer address - use ringbuffer[0] for GPU init */ adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_BASE, - REG_ADRENO_CP_RB_BASE_HI, gpu->rb_iova); + REG_ADRENO_CP_RB_BASE_HI, gpu->rb[0]->iova); if (!adreno_is_a430(adreno_gpu)) { adreno_gpu_write64(adreno_gpu, REG_ADRENO_CP_RB_RPTR_ADDR, REG_ADRENO_CP_RB_RPTR_ADDR_HI, - rbmemptr(adreno_gpu, rptr)); + rbmemptr(gpu->rb[0], rptr)); } return 0; } -static uint32_t get_wptr(struct msm_ringbuffer *ring) -{ - return ring->cur - ring->start; -} - /* Use this helper to read rptr, since a430 doesn't update rptr in memory */ -static uint32_t get_rptr(struct adreno_gpu *adreno_gpu) +static uint32_t get_rptr(struct adreno_gpu *adreno_gpu, + struct msm_ringbuffer *ring) { if (adreno_is_a430(adreno_gpu)) - return adreno_gpu->memptrs->rptr = adreno_gpu_read( + return ring->memptrs->rptr = adreno_gpu_read( adreno_gpu, REG_ADRENO_CP_RB_RPTR); else - return adreno_gpu->memptrs->rptr; + return ring->memptrs->rptr; } -uint32_t adreno_last_fence(struct msm_gpu *gpu) +struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu) { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - return adreno_gpu->memptrs->fence; + return gpu->rb[0]; } void adreno_recover(struct msm_gpu *gpu) @@ -149,7 +256,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); struct msm_drm_private *priv = gpu->dev->dev_private; - struct msm_ringbuffer *ring = gpu->rb; + struct msm_ringbuffer *ring = submit->ring; unsigned i; for (i = 0; i < submit->nr_cmds; i++) { @@ -164,7 +271,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, case MSM_SUBMIT_CMD_BUF: OUT_PKT3(ring, adreno_is_a430(adreno_gpu) ? CP_INDIRECT_BUFFER_PFE : CP_INDIRECT_BUFFER_PFD, 2); - OUT_RING(ring, submit->cmd[i].iova); + OUT_RING(ring, lower_32_bits(submit->cmd[i].iova)); OUT_RING(ring, submit->cmd[i].size); OUT_PKT2(ring); break; @@ -172,7 +279,7 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, } OUT_PKT0(ring, REG_AXXX_CP_SCRATCH_REG2, 1); - OUT_RING(ring, submit->fence->seqno); + OUT_RING(ring, submit->seqno); if (adreno_is_a3xx(adreno_gpu) || adreno_is_a4xx(adreno_gpu)) { /* Flush HLSQ lazy updates to make sure there is nothing @@ -188,8 +295,8 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, OUT_PKT3(ring, CP_EVENT_WRITE, 3); OUT_RING(ring, CACHE_FLUSH_TS); - OUT_RING(ring, rbmemptr(adreno_gpu, fence)); - OUT_RING(ring, submit->fence->seqno); + OUT_RING(ring, rbmemptr(ring, fence)); + OUT_RING(ring, submit->seqno); /* we could maybe be clever and only CP_COND_EXEC the interrupt: */ OUT_PKT3(ring, CP_INTERRUPT, 1); @@ -215,20 +322,23 @@ void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, } #endif - gpu->funcs->flush(gpu); + gpu->funcs->flush(gpu, ring); } -void adreno_flush(struct msm_gpu *gpu) +void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); uint32_t wptr; + /* Copy the shadow to the actual register */ + ring->cur = ring->next; + /* * Mask wptr value that we calculate to fit in the HW range. This is * to account for the possibility that the last command fit exactly into * the ringbuffer and rb->next hasn't wrapped to zero yet */ - wptr = get_wptr(gpu->rb) & ((gpu->rb->size / 4) - 1); + wptr = get_wptr(ring); /* ensure writes to ringbuffer have hit system memory: */ mb(); @@ -236,17 +346,19 @@ void adreno_flush(struct msm_gpu *gpu) adreno_gpu_write(adreno_gpu, REG_ADRENO_CP_RB_WPTR, wptr); } -bool adreno_idle(struct msm_gpu *gpu) +bool adreno_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - uint32_t wptr = get_wptr(gpu->rb); + uint32_t wptr = get_wptr(ring); /* wait for CP to drain ringbuffer: */ - if (!spin_until(get_rptr(adreno_gpu) == wptr)) + if (!spin_until(get_rptr(adreno_gpu, ring) == wptr)) return true; /* TODO maybe we need to reset GPU here to recover from hang? */ - DRM_ERROR("%s: timeout waiting to drain ringbuffer!\n", gpu->name); + DRM_ERROR("%s: timeout waiting to drain ringbuffer %d rptr/wptr = %X/%X\n", + gpu->name, ring->id, get_rptr(adreno_gpu, ring), wptr); + return false; } @@ -261,10 +373,16 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m) adreno_gpu->rev.major, adreno_gpu->rev.minor, adreno_gpu->rev.patchid); - seq_printf(m, "fence: %d/%d\n", adreno_gpu->memptrs->fence, - gpu->fctx->last_fence); - seq_printf(m, "rptr: %d\n", get_rptr(adreno_gpu)); - seq_printf(m, "rb wptr: %d\n", get_wptr(gpu->rb)); + for (i = 0; i < gpu->nr_rings; i++) { + struct msm_ringbuffer *ring = gpu->rb[i]; + + seq_printf(m, "rb %d: fence: %d/%d\n", i, + ring->memptrs->fence, ring->seqno); + + seq_printf(m, " rptr: %d\n", + get_rptr(adreno_gpu, ring)); + seq_printf(m, "rb wptr: %d\n", get_wptr(ring)); + } /* dump these out in a form that can be parsed by demsm: */ seq_printf(m, "IO:region %s 00000000 00020000\n", gpu->name); @@ -290,16 +408,23 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m) void adreno_dump_info(struct msm_gpu *gpu) { struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); + int i; printk("revision: %d (%d.%d.%d.%d)\n", adreno_gpu->info->revn, adreno_gpu->rev.core, adreno_gpu->rev.major, adreno_gpu->rev.minor, adreno_gpu->rev.patchid); - printk("fence: %d/%d\n", adreno_gpu->memptrs->fence, - gpu->fctx->last_fence); - printk("rptr: %d\n", get_rptr(adreno_gpu)); - printk("rb wptr: %d\n", get_wptr(gpu->rb)); + for (i = 0; i < gpu->nr_rings; i++) { + struct msm_ringbuffer *ring = gpu->rb[i]; + + printk("rb %d: fence: %d/%d\n", i, + ring->memptrs->fence, + ring->seqno); + + printk("rptr: %d\n", get_rptr(adreno_gpu, ring)); + printk("rb wptr: %d\n", get_wptr(ring)); + } } /* would be nice to not have to duplicate the _show() stuff with printk(): */ @@ -322,28 +447,31 @@ void adreno_dump(struct msm_gpu *gpu) } } -static uint32_t ring_freewords(struct msm_gpu *gpu) +static uint32_t ring_freewords(struct msm_ringbuffer *ring) { - struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu); - uint32_t size = gpu->rb->size / 4; - uint32_t wptr = get_wptr(gpu->rb); - uint32_t rptr = get_rptr(adreno_gpu); + struct adreno_gpu *adreno_gpu = to_adreno_gpu(ring->gpu); + uint32_t size = MSM_GPU_RINGBUFFER_SZ >> 2; + /* Use ring->next to calculate free size */ + uint32_t wptr = ring->next - ring->start; + uint32_t rptr = get_rptr(adreno_gpu, ring); return (rptr + (size - 1) - wptr) % size; } -void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords) +void adreno_wait_ring(struct msm_ringbuffer *ring, uint32_t ndwords) { - if (spin_until(ring_freewords(gpu) >= ndwords)) - DRM_ERROR("%s: timeout waiting for ringbuffer space\n", gpu->name); + if (spin_until(ring_freewords(ring) >= ndwords)) + DRM_DEV_ERROR(ring->gpu->dev->dev, + "timeout waiting for space in ringubffer %d\n", + ring->id); } int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, - struct adreno_gpu *adreno_gpu, const struct adreno_gpu_funcs *funcs) + struct adreno_gpu *adreno_gpu, + const struct adreno_gpu_funcs *funcs, int nr_rings) { struct adreno_platform_config *config = pdev->dev.platform_data; struct msm_gpu_config adreno_gpu_config = { 0 }; struct msm_gpu *gpu = &adreno_gpu->base; - int ret; adreno_gpu->funcs = funcs; adreno_gpu->info = adreno_info(config->rev); @@ -366,59 +494,20 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, adreno_gpu_config.va_start = SZ_16M; adreno_gpu_config.va_end = 0xffffffff; - adreno_gpu_config.ringsz = RB_SIZE; + adreno_gpu_config.nr_rings = nr_rings; pm_runtime_set_autosuspend_delay(&pdev->dev, DRM_MSM_INACTIVE_PERIOD); pm_runtime_use_autosuspend(&pdev->dev); pm_runtime_enable(&pdev->dev); - ret = msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base, + return msm_gpu_init(drm, pdev, &adreno_gpu->base, &funcs->base, adreno_gpu->info->name, &adreno_gpu_config); - if (ret) - return ret; - - ret = request_firmware(&adreno_gpu->pm4, adreno_gpu->info->pm4fw, drm->dev); - if (ret) { - dev_err(drm->dev, "failed to load %s PM4 firmware: %d\n", - adreno_gpu->info->pm4fw, ret); - return ret; - } - - ret = request_firmware(&adreno_gpu->pfp, adreno_gpu->info->pfpfw, drm->dev); - if (ret) { - dev_err(drm->dev, "failed to load %s PFP firmware: %d\n", - adreno_gpu->info->pfpfw, ret); - return ret; - } - - adreno_gpu->memptrs = msm_gem_kernel_new(drm, - sizeof(*adreno_gpu->memptrs), MSM_BO_UNCACHED, gpu->aspace, - &adreno_gpu->memptrs_bo, &adreno_gpu->memptrs_iova); - - if (IS_ERR(adreno_gpu->memptrs)) { - ret = PTR_ERR(adreno_gpu->memptrs); - adreno_gpu->memptrs = NULL; - dev_err(drm->dev, "could not allocate memptrs: %d\n", ret); - } - - return ret; } void adreno_gpu_cleanup(struct adreno_gpu *adreno_gpu) { - struct msm_gpu *gpu = &adreno_gpu->base; - - if (adreno_gpu->memptrs_bo) { - if (adreno_gpu->memptrs) - msm_gem_put_vaddr(adreno_gpu->memptrs_bo); - - if (adreno_gpu->memptrs_iova) - msm_gem_put_iova(adreno_gpu->memptrs_bo, gpu->aspace); - - drm_gem_object_unreference_unlocked(adreno_gpu->memptrs_bo); - } release_firmware(adreno_gpu->pm4); release_firmware(adreno_gpu->pfp); - msm_gpu_cleanup(gpu); + msm_gpu_cleanup(&adreno_gpu->base); } diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h index 4d9165f29f43..28e3de6e5f94 100644 --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h @@ -2,7 +2,7 @@ * Copyright (C) 2013 Red Hat * Author: Rob Clark <robdclark@gmail.com> * - * Copyright (c) 2014 The Linux Foundation. All rights reserved. + * Copyright (c) 2014,2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by @@ -82,14 +82,6 @@ struct adreno_info { const struct adreno_info *adreno_info(struct adreno_rev rev); -#define rbmemptr(adreno_gpu, member) \ - ((adreno_gpu)->memptrs_iova + offsetof(struct adreno_rbmemptrs, member)) - -struct adreno_rbmemptrs { - volatile uint32_t rptr; - volatile uint32_t fence; -}; - struct adreno_gpu { struct msm_gpu base; struct adreno_rev rev; @@ -101,16 +93,30 @@ struct adreno_gpu { /* interesting register offsets to dump: */ const unsigned int *registers; + /* + * Are we loading fw from legacy path? Prior to addition + * of gpu firmware to linux-firmware, the fw files were + * placed in toplevel firmware directory, following qcom's + * android kernel. But linux-firmware preferred they be + * placed in a 'qcom' subdirectory. + * + * For backwards compatibility, we try first to load from + * the new path, using request_firmware_direct() to avoid + * any potential timeout waiting for usermode helper, then + * fall back to the old path (with direct load). And + * finally fall back to request_firmware() with the new + * path to allow the usermode helper. + */ + enum { + FW_LOCATION_UNKNOWN = 0, + FW_LOCATION_NEW, /* /lib/firmware/qcom/$fwfile */ + FW_LOCATION_LEGACY, /* /lib/firmware/$fwfile */ + FW_LOCATION_HELPER, + } fwloc; + /* firmware: */ const struct firmware *pm4, *pfp; - /* ringbuffer rptr/wptr: */ - // TODO should this be in msm_ringbuffer? I think it would be - // different for z180.. - struct adreno_rbmemptrs *memptrs; - struct drm_gem_object *memptrs_bo; - uint64_t memptrs_iova; - /* * Register offsets are different between some GPUs. * GPU specific offsets will be exported by GPU specific @@ -196,22 +202,25 @@ static inline int adreno_is_a530(struct adreno_gpu *gpu) } int adreno_get_param(struct msm_gpu *gpu, uint32_t param, uint64_t *value); +const struct firmware *adreno_request_fw(struct adreno_gpu *adreno_gpu, + const char *fwname); int adreno_hw_init(struct msm_gpu *gpu); -uint32_t adreno_last_fence(struct msm_gpu *gpu); void adreno_recover(struct msm_gpu *gpu); void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, struct msm_file_private *ctx); -void adreno_flush(struct msm_gpu *gpu); -bool adreno_idle(struct msm_gpu *gpu); +void adreno_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring); +bool adreno_idle(struct msm_gpu *gpu, struct msm_ringbuffer *ring); #ifdef CONFIG_DEBUG_FS void adreno_show(struct msm_gpu *gpu, struct seq_file *m); #endif void adreno_dump_info(struct msm_gpu *gpu); void adreno_dump(struct msm_gpu *gpu); -void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords); +void adreno_wait_ring(struct msm_ringbuffer *ring, uint32_t ndwords); +struct msm_ringbuffer *adreno_active_ring(struct msm_gpu *gpu); int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev, - struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs); + struct adreno_gpu *gpu, const struct adreno_gpu_funcs *funcs, + int nr_rings); void adreno_gpu_cleanup(struct adreno_gpu *gpu); @@ -220,7 +229,7 @@ void adreno_gpu_cleanup(struct adreno_gpu *gpu); static inline void OUT_PKT0(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt) { - adreno_wait_ring(ring->gpu, cnt+1); + adreno_wait_ring(ring, cnt+1); OUT_RING(ring, CP_TYPE0_PKT | ((cnt-1) << 16) | (regindx & 0x7FFF)); } @@ -228,14 +237,14 @@ OUT_PKT0(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt) static inline void OUT_PKT2(struct msm_ringbuffer *ring) { - adreno_wait_ring(ring->gpu, 1); + adreno_wait_ring(ring, 1); OUT_RING(ring, CP_TYPE2_PKT); } static inline void OUT_PKT3(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt) { - adreno_wait_ring(ring->gpu, cnt+1); + adreno_wait_ring(ring, cnt+1); OUT_RING(ring, CP_TYPE3_PKT | ((cnt-1) << 16) | ((opcode & 0xFF) << 8)); } @@ -257,14 +266,14 @@ static inline u32 PM4_PARITY(u32 val) static inline void OUT_PKT4(struct msm_ringbuffer *ring, uint16_t regindx, uint16_t cnt) { - adreno_wait_ring(ring->gpu, cnt + 1); + adreno_wait_ring(ring, cnt + 1); OUT_RING(ring, PKT4(regindx, cnt)); } static inline void OUT_PKT7(struct msm_ringbuffer *ring, uint8_t opcode, uint16_t cnt) { - adreno_wait_ring(ring->gpu, cnt + 1); + adreno_wait_ring(ring, cnt + 1); OUT_RING(ring, CP_TYPE7_PKT | (cnt << 0) | (PM4_PARITY(cnt) << 15) | ((opcode & 0x7F) << 16) | (PM4_PARITY(opcode) << 23)); } @@ -323,6 +332,11 @@ static inline void adreno_gpu_write64(struct adreno_gpu *gpu, adreno_gpu_write(gpu, hi, upper_32_bits(data)); } +static inline uint32_t get_wptr(struct msm_ringbuffer *ring) +{ + return (ring->cur - ring->start) % (MSM_GPU_RINGBUFFER_SZ >> 2); +} + /* * Given a register and a count, return a value to program into * REG_CP_PROTECT_REG(n) - this will block both reads and writes for _len diff --git a/drivers/gpu/drm/msm/dsi/dsi_cfg.c b/drivers/gpu/drm/msm/dsi/dsi_cfg.c index a5d75c9b3a73..65c1dfbbe019 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_cfg.c +++ b/drivers/gpu/drm/msm/dsi/dsi_cfg.c @@ -14,7 +14,7 @@ #include "dsi_cfg.h" static const char * const dsi_v2_bus_clk_names[] = { - "core_mmss_clk", "iface_clk", "bus_clk", + "core_mmss", "iface", "bus", }; static const struct msm_dsi_config apq8064_dsi_cfg = { @@ -34,7 +34,7 @@ static const struct msm_dsi_config apq8064_dsi_cfg = { }; static const char * const dsi_6g_bus_clk_names[] = { - "mdp_core_clk", "iface_clk", "bus_clk", "core_mmss_clk", + "mdp_core", "iface", "bus", "core_mmss", }; static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = { @@ -55,7 +55,7 @@ static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = { }; static const char * const dsi_8916_bus_clk_names[] = { - "mdp_core_clk", "iface_clk", "bus_clk", + "mdp_core", "iface", "bus", }; static const struct msm_dsi_config msm8916_dsi_cfg = { @@ -99,7 +99,7 @@ static const struct msm_dsi_config msm8994_dsi_cfg = { * without it too. Figure out why it doesn't enable and uncomment below */ static const char * const dsi_8996_bus_clk_names[] = { - "mdp_core_clk", "iface_clk", "bus_clk", /* "core_mmss_clk", */ + "mdp_core", "iface", "bus", /* "core_mmss", */ }; static const struct msm_dsi_config msm8996_dsi_cfg = { diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c index dbb31a014419..0f7324a686ca 100644 --- a/drivers/gpu/drm/msm/dsi/dsi_host.c +++ b/drivers/gpu/drm/msm/dsi/dsi_host.c @@ -248,7 +248,7 @@ disable_clks: clk_disable_unprepare(ahb_clk); disable_gdsc: regulator_disable(gdsc_reg); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); put_clk: clk_put(ahb_clk); put_gdsc: @@ -334,46 +334,46 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host) static int dsi_clk_init(struct msm_dsi_host *msm_host) { - struct device *dev = &msm_host->pdev->dev; + struct platform_device *pdev = msm_host->pdev; const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd; const struct msm_dsi_config *cfg = cfg_hnd->cfg; int i, ret = 0; /* get bus clocks */ for (i = 0; i < cfg->num_bus_clks; i++) { - msm_host->bus_clks[i] = devm_clk_get(dev, + msm_host->bus_clks[i] = msm_clk_get(pdev, cfg->bus_clk_names[i]); if (IS_ERR(msm_host->bus_clks[i])) { ret = PTR_ERR(msm_host->bus_clks[i]); - pr_err("%s: Unable to get %s, ret = %d\n", + pr_err("%s: Unable to get %s clock, ret = %d\n", __func__, cfg->bus_clk_names[i], ret); goto exit; } } /* get link and source clocks */ - msm_host->byte_clk = devm_clk_get(dev, "byte_clk"); + msm_host->byte_clk = msm_clk_get(pdev, "byte"); if (IS_ERR(msm_host->byte_clk)) { ret = PTR_ERR(msm_host->byte_clk); - pr_err("%s: can't find dsi_byte_clk. ret=%d\n", + pr_err("%s: can't find dsi_byte clock. ret=%d\n", __func__, ret); msm_host->byte_clk = NULL; goto exit; } - msm_host->pixel_clk = devm_clk_get(dev, "pixel_clk"); + msm_host->pixel_clk = msm_clk_get(pdev, "pixel"); if (IS_ERR(msm_host->pixel_clk)) { ret = PTR_ERR(msm_host->pixel_clk); - pr_err("%s: can't find dsi_pixel_clk. ret=%d\n", + pr_err("%s: can't find dsi_pixel clock. ret=%d\n", __func__, ret); msm_host->pixel_clk = NULL; goto exit; } - msm_host->esc_clk = devm_clk_get(dev, "core_clk"); + msm_host->esc_clk = msm_clk_get(pdev, "core"); if (IS_ERR(msm_host->esc_clk)) { ret = PTR_ERR(msm_host->esc_clk); - pr_err("%s: can't find dsi_esc_clk. ret=%d\n", + pr_err("%s: can't find dsi_esc clock. ret=%d\n", __func__, ret); msm_host->esc_clk = NULL; goto exit; @@ -382,22 +382,22 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) msm_host->byte_clk_src = clk_get_parent(msm_host->byte_clk); if (!msm_host->byte_clk_src) { ret = -ENODEV; - pr_err("%s: can't find byte_clk_src. ret=%d\n", __func__, ret); + pr_err("%s: can't find byte_clk clock. ret=%d\n", __func__, ret); goto exit; } msm_host->pixel_clk_src = clk_get_parent(msm_host->pixel_clk); if (!msm_host->pixel_clk_src) { ret = -ENODEV; - pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret); + pr_err("%s: can't find pixel_clk clock. ret=%d\n", __func__, ret); goto exit; } if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) { - msm_host->src_clk = devm_clk_get(dev, "src_clk"); + msm_host->src_clk = msm_clk_get(pdev, "src"); if (IS_ERR(msm_host->src_clk)) { ret = PTR_ERR(msm_host->src_clk); - pr_err("%s: can't find dsi_src_clk. ret=%d\n", + pr_err("%s: can't find src clock. ret=%d\n", __func__, ret); msm_host->src_clk = NULL; goto exit; @@ -406,7 +406,7 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) msm_host->esc_clk_src = clk_get_parent(msm_host->esc_clk); if (!msm_host->esc_clk_src) { ret = -ENODEV; - pr_err("%s: can't get esc_clk_src. ret=%d\n", + pr_err("%s: can't get esc clock parent. ret=%d\n", __func__, ret); goto exit; } @@ -414,7 +414,7 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host) msm_host->dsi_clk_src = clk_get_parent(msm_host->src_clk); if (!msm_host->dsi_clk_src) { ret = -ENODEV; - pr_err("%s: can't get dsi_clk_src. ret=%d\n", + pr_err("%s: can't get src clock parent. ret=%d\n", __func__, ret); } } diff --git a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c index 7c9bf91bc22b..790ca280cbfd 100644 --- a/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +++ b/drivers/gpu/drm/msm/dsi/phy/dsi_phy.c @@ -482,7 +482,7 @@ static int dsi_phy_driver_probe(struct platform_device *pdev) goto fail; } - phy->ahb_clk = devm_clk_get(dev, "iface_clk"); + phy->ahb_clk = msm_clk_get(pdev, "iface"); if (IS_ERR(phy->ahb_clk)) { dev_err(dev, "%s: Unable to get ahb clk\n", __func__); ret = PTR_ERR(phy->ahb_clk); diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c index e32a4a4f3797..7c72264101ff 100644 --- a/drivers/gpu/drm/msm/edp/edp_ctrl.c +++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c @@ -150,46 +150,46 @@ static const struct edp_pixel_clk_div clk_divs[2][EDP_PIXEL_CLK_NUM] = { static int edp_clk_init(struct edp_ctrl *ctrl) { - struct device *dev = &ctrl->pdev->dev; + struct platform_device *pdev = ctrl->pdev; int ret; - ctrl->aux_clk = devm_clk_get(dev, "core_clk"); + ctrl->aux_clk = msm_clk_get(pdev, "core"); if (IS_ERR(ctrl->aux_clk)) { ret = PTR_ERR(ctrl->aux_clk); - pr_err("%s: Can't find aux_clk, %d\n", __func__, ret); + pr_err("%s: Can't find core clock, %d\n", __func__, ret); ctrl->aux_clk = NULL; return ret; } - ctrl->pixel_clk = devm_clk_get(dev, "pixel_clk"); + ctrl->pixel_clk = msm_clk_get(pdev, "pixel"); if (IS_ERR(ctrl->pixel_clk)) { ret = PTR_ERR(ctrl->pixel_clk); - pr_err("%s: Can't find pixel_clk, %d\n", __func__, ret); + pr_err("%s: Can't find pixel clock, %d\n", __func__, ret); ctrl->pixel_clk = NULL; return ret; } - ctrl->ahb_clk = devm_clk_get(dev, "iface_clk"); + ctrl->ahb_clk = msm_clk_get(pdev, "iface"); if (IS_ERR(ctrl->ahb_clk)) { ret = PTR_ERR(ctrl->ahb_clk); - pr_err("%s: Can't find ahb_clk, %d\n", __func__, ret); + pr_err("%s: Can't find iface clock, %d\n", __func__, ret); ctrl->ahb_clk = NULL; return ret; } - ctrl->link_clk = devm_clk_get(dev, "link_clk"); + ctrl->link_clk = msm_clk_get(pdev, "link"); if (IS_ERR(ctrl->link_clk)) { ret = PTR_ERR(ctrl->link_clk); - pr_err("%s: Can't find link_clk, %d\n", __func__, ret); + pr_err("%s: Can't find link clock, %d\n", __func__, ret); ctrl->link_clk = NULL; return ret; } /* need mdp core clock to receive irq */ - ctrl->mdp_core_clk = devm_clk_get(dev, "mdp_core_clk"); + ctrl->mdp_core_clk = msm_clk_get(pdev, "mdp_core"); if (IS_ERR(ctrl->mdp_core_clk)) { ret = PTR_ERR(ctrl->mdp_core_clk); - pr_err("%s: Can't find mdp_core_clk, %d\n", __func__, ret); + pr_err("%s: Can't find mdp_core clock, %d\n", __func__, ret); ctrl->mdp_core_clk = NULL; return ret; } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 17e069a133a4..e63dc0fb55f8 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -208,7 +208,7 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) for (i = 0; i < config->hpd_clk_cnt; i++) { struct clk *clk; - clk = devm_clk_get(&pdev->dev, config->hpd_clk_names[i]); + clk = msm_clk_get(pdev, config->hpd_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get hpd clk: %s (%d)\n", @@ -228,7 +228,7 @@ static struct hdmi *msm_hdmi_init(struct platform_device *pdev) for (i = 0; i < config->pwr_clk_cnt; i++) { struct clk *clk; - clk = devm_clk_get(&pdev->dev, config->pwr_clk_names[i]); + clk = msm_clk_get(pdev, config->pwr_clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(&pdev->dev, "failed to get pwr clk: %s (%d)\n", @@ -361,7 +361,7 @@ static const char *hpd_reg_names_none[] = {}; static struct hdmi_platform_config hdmi_tx_8660_config; static const char *hpd_reg_names_8960[] = {"core-vdda", "hdmi-mux"}; -static const char *hpd_clk_names_8960[] = {"core_clk", "master_iface_clk", "slave_iface_clk"}; +static const char *hpd_clk_names_8960[] = {"core", "master_iface", "slave_iface"}; static struct hdmi_platform_config hdmi_tx_8960_config = { HDMI_CFG(hpd_reg, 8960), @@ -370,8 +370,8 @@ static struct hdmi_platform_config hdmi_tx_8960_config = { static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; static const char *hpd_reg_names_8x74[] = {"hpd-gdsc", "hpd-5v"}; -static const char *pwr_clk_names_8x74[] = {"extp_clk", "alt_iface_clk"}; -static const char *hpd_clk_names_8x74[] = {"iface_clk", "core_clk", "mdp_core_clk"}; +static const char *pwr_clk_names_8x74[] = {"extp", "alt_iface"}; +static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"}; static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0}; static struct hdmi_platform_config hdmi_tx_8974_config = { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c index 534ce5b49781..5e631392dc85 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c @@ -48,7 +48,7 @@ static int msm_hdmi_phy_resource_init(struct hdmi_phy *phy) for (i = 0; i < cfg->num_clks; i++) { struct clk *clk; - clk = devm_clk_get(dev, cfg->clk_names[i]); + clk = msm_clk_get(phy->pdev, cfg->clk_names[i]); if (IS_ERR(clk)) { ret = PTR_ERR(clk); dev_err(dev, "failed to get phy clock: %s (%d)\n", diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c index e6ee6b745ab7..0980da8ec966 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c @@ -48,7 +48,7 @@ static const char * const hdmi_phy_8960_reg_names[] = { }; static const char * const hdmi_phy_8960_clk_names[] = { - "slave_iface_clk", + "slave_iface", }; const struct hdmi_phy_cfg msm_hdmi_phy_8960_cfg = { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c index 1fb7645cc721..0df504c61833 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c @@ -758,9 +758,7 @@ static const char * const hdmi_phy_8996_reg_names[] = { }; static const char * const hdmi_phy_8996_clk_names[] = { - "mmagic_iface_clk", - "iface_clk", - "ref_clk", + "iface", "ref", }; const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c index c4a61e537851..4a8b8468586a 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c @@ -41,8 +41,7 @@ static const char * const hdmi_phy_8x74_reg_names[] = { }; static const char * const hdmi_phy_8x74_clk_names[] = { - "iface_clk", - "alt_iface_clk" + "iface", "alt_iface" }; const struct hdmi_phy_cfg msm_hdmi_phy_8x74_cfg = { diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c index 47fa2aba1983..14bd3bd3e040 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c @@ -290,6 +290,9 @@ static void mdp4_crtc_atomic_disable(struct drm_crtc *crtc, if (WARN_ON(!mdp4_crtc->enabled)) return; + /* Disable/save vblank irq handling before power is disabled */ + drm_crtc_vblank_off(crtc); + mdp_irq_unregister(&mdp4_kms->base, &mdp4_crtc->err); mdp4_disable(mdp4_kms); @@ -308,6 +311,10 @@ static void mdp4_crtc_atomic_enable(struct drm_crtc *crtc, return; mdp4_enable(mdp4_kms); + + /* Restore vblank irq handling after power is enabled */ + drm_crtc_vblank_on(crtc); + mdp_irq_register(&mdp4_kms->base, &mdp4_crtc->err); crtc_flush(crtc); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c index c2bdad88447e..824067d2d427 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cfg.c @@ -83,6 +83,8 @@ const struct mdp5_cfg_hw msm8x74v1_config = { .caps = MDP_LM_CAP_WB }, }, .nb_stages = 5, + .max_width = 2048, + .max_height = 0xFFFF, }, .dspp = { .count = 3, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c index 60790df91bfa..1abc7f5c345c 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c @@ -224,7 +224,7 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder, mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, MDP5_SPLIT_DPL_LOWER_SMART_PANEL); mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); return 0; } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c index 6fcb58ab718c..e414850dbbda 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c @@ -55,18 +55,23 @@ struct mdp5_crtc { struct completion pp_completion; + bool lm_cursor_enabled; + struct { /* protect REG_MDP5_LM_CURSOR* registers and cursor scanout_bo*/ spinlock_t lock; /* current cursor being scanned out: */ struct drm_gem_object *scanout_bo; + uint64_t iova; uint32_t width, height; uint32_t x, y; } cursor; }; #define to_mdp5_crtc(x) container_of(x, struct mdp5_crtc, base) +static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc); + static struct mdp5_kms *get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv = crtc->dev->dev_private; @@ -114,6 +119,8 @@ static u32 crtc_flush_all(struct drm_crtc *crtc) return 0; drm_atomic_crtc_for_each_plane(plane, crtc) { + if (!plane->state->visible) + continue; flush_mask |= mdp5_plane_get_flush(plane); } @@ -242,6 +249,9 @@ static void blend_setup(struct drm_crtc *crtc) drm_atomic_crtc_for_each_plane(plane, crtc) { enum mdp5_pipe right_pipe; + if (!plane->state->visible) + continue; + pstate = to_mdp5_plane_state(plane->state); pstates[pstate->stage] = pstate; stage[pstate->stage][PIPE_LEFT] = mdp5_plane_pipe(plane); @@ -422,11 +432,14 @@ static void mdp5_crtc_atomic_disable(struct drm_crtc *crtc, if (WARN_ON(!mdp5_crtc->enabled)) return; + /* Disable/save vblank irq handling before power is disabled */ + drm_crtc_vblank_off(crtc); + if (mdp5_cstate->cmd_mode) mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->pp_done); mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); mdp5_crtc->enabled = false; } @@ -446,6 +459,29 @@ static void mdp5_crtc_atomic_enable(struct drm_crtc *crtc, pm_runtime_get_sync(dev); + if (mdp5_crtc->lm_cursor_enabled) { + /* + * Restore LM cursor state, as it might have been lost + * with suspend: + */ + if (mdp5_crtc->cursor.iova) { + unsigned long flags; + + spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); + mdp5_crtc_restore_cursor(crtc); + spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); + + mdp5_ctl_set_cursor(mdp5_cstate->ctl, + &mdp5_cstate->pipeline, 0, true); + } else { + mdp5_ctl_set_cursor(mdp5_cstate->ctl, + &mdp5_cstate->pipeline, 0, false); + } + } + + /* Restore vblank irq handling after power is enabled */ + drm_crtc_vblank_on(crtc); + mdp5_crtc_mode_set_nofb(crtc); mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err); @@ -580,6 +616,9 @@ static int mdp5_crtc_atomic_check(struct drm_crtc *crtc, DBG("%s: check", crtc->name); drm_atomic_crtc_state_for_each_plane_state(plane, pstate, state) { + if (!pstate->visible) + continue; + pstates[cnt].plane = plane; pstates[cnt].state = to_mdp5_plane_state(pstate); @@ -723,6 +762,50 @@ static void get_roi(struct drm_crtc *crtc, uint32_t *roi_w, uint32_t *roi_h) mdp5_crtc->cursor.y); } +static void mdp5_crtc_restore_cursor(struct drm_crtc *crtc) +{ + struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); + struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); + struct mdp5_kms *mdp5_kms = get_kms(crtc); + const enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; + uint32_t blendcfg, stride; + uint32_t x, y, width, height; + uint32_t roi_w, roi_h; + int lm; + + assert_spin_locked(&mdp5_crtc->cursor.lock); + + lm = mdp5_cstate->pipeline.mixer->lm; + + x = mdp5_crtc->cursor.x; + y = mdp5_crtc->cursor.y; + width = mdp5_crtc->cursor.width; + height = mdp5_crtc->cursor.height; + + stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0); + + get_roi(crtc, &roi_w, &roi_h); + + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride); + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm), + MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888)); + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_IMG_SIZE(lm), + MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) | + MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width)); + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), + MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) | + MDP5_LM_CURSOR_SIZE_ROI_W(roi_w)); + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(lm), + MDP5_LM_CURSOR_START_XY_Y_START(y) | + MDP5_LM_CURSOR_START_XY_X_START(x)); + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), + mdp5_crtc->cursor.iova); + + blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN; + blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha); + mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg); +} + static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file, uint32_t handle, uint32_t width, uint32_t height) @@ -735,16 +818,18 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, struct platform_device *pdev = mdp5_kms->pdev; struct msm_kms *kms = &mdp5_kms->base.base; struct drm_gem_object *cursor_bo, *old_bo = NULL; - uint32_t blendcfg, stride; - uint64_t cursor_addr; struct mdp5_ctl *ctl; - int ret, lm; - enum mdp5_cursor_alpha cur_alpha = CURSOR_ALPHA_PER_PIXEL; + int ret; uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); - uint32_t roi_w, roi_h; bool cursor_enable = true; unsigned long flags; + if (!mdp5_crtc->lm_cursor_enabled) { + dev_warn(dev->dev, + "cursor_set is deprecated with cursor planes\n"); + return -EINVAL; + } + if ((width > CURSOR_WIDTH) || (height > CURSOR_HEIGHT)) { dev_err(dev->dev, "bad cursor size: %dx%d\n", width, height); return -EINVAL; @@ -761,6 +846,7 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, if (!handle) { DBG("Cursor off"); cursor_enable = false; + mdp5_crtc->cursor.iova = 0; pm_runtime_get_sync(&pdev->dev); goto set_cursor; } @@ -769,13 +855,11 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, if (!cursor_bo) return -ENOENT; - ret = msm_gem_get_iova(cursor_bo, kms->aspace, &cursor_addr); + ret = msm_gem_get_iova(cursor_bo, kms->aspace, + &mdp5_crtc->cursor.iova); if (ret) return -EINVAL; - lm = mdp5_cstate->pipeline.mixer->lm; - stride = width * drm_format_plane_cpp(DRM_FORMAT_ARGB8888, 0); - pm_runtime_get_sync(&pdev->dev); spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); @@ -785,27 +869,10 @@ static int mdp5_crtc_cursor_set(struct drm_crtc *crtc, mdp5_crtc->cursor.width = width; mdp5_crtc->cursor.height = height; - get_roi(crtc, &roi_w, &roi_h); - - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_STRIDE(lm), stride); - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_FORMAT(lm), - MDP5_LM_CURSOR_FORMAT_FORMAT(CURSOR_FMT_ARGB8888)); - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_IMG_SIZE(lm), - MDP5_LM_CURSOR_IMG_SIZE_SRC_H(height) | - MDP5_LM_CURSOR_IMG_SIZE_SRC_W(width)); - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), - MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) | - MDP5_LM_CURSOR_SIZE_ROI_W(roi_w)); - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BASE_ADDR(lm), cursor_addr); - - blendcfg = MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_EN; - blendcfg |= MDP5_LM_CURSOR_BLEND_CONFIG_BLEND_ALPHA_SEL(cur_alpha); - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_BLEND_CONFIG(lm), blendcfg); + mdp5_crtc_restore_cursor(crtc); spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); - pm_runtime_put_autosuspend(&pdev->dev); - set_cursor: ret = mdp5_ctl_set_cursor(ctl, pipeline, 0, cursor_enable); if (ret) { @@ -817,7 +884,7 @@ set_cursor: crtc_flush(crtc, flush_mask); end: - pm_runtime_put_autosuspend(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); if (old_bo) { drm_flip_work_queue(&mdp5_crtc->unref_cursor_work, old_bo); /* enable vblank to complete cursor work: */ @@ -831,12 +898,18 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) struct mdp5_kms *mdp5_kms = get_kms(crtc); struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc); struct mdp5_crtc_state *mdp5_cstate = to_mdp5_crtc_state(crtc->state); - uint32_t lm = mdp5_cstate->pipeline.mixer->lm; uint32_t flush_mask = mdp_ctl_flush_mask_cursor(0); + struct drm_device *dev = crtc->dev; uint32_t roi_w; uint32_t roi_h; unsigned long flags; + if (!mdp5_crtc->lm_cursor_enabled) { + dev_warn(dev->dev, + "cursor_move is deprecated with cursor planes\n"); + return -EINVAL; + } + /* don't support LM cursors when we we have source split enabled */ if (mdp5_cstate->pipeline.r_mixer) return -EINVAL; @@ -853,17 +926,12 @@ static int mdp5_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) pm_runtime_get_sync(&mdp5_kms->pdev->dev); spin_lock_irqsave(&mdp5_crtc->cursor.lock, flags); - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_SIZE(lm), - MDP5_LM_CURSOR_SIZE_ROI_H(roi_h) | - MDP5_LM_CURSOR_SIZE_ROI_W(roi_w)); - mdp5_write(mdp5_kms, REG_MDP5_LM_CURSOR_START_XY(lm), - MDP5_LM_CURSOR_START_XY_Y_START(y) | - MDP5_LM_CURSOR_START_XY_X_START(x)); + mdp5_crtc_restore_cursor(crtc); spin_unlock_irqrestore(&mdp5_crtc->cursor.lock, flags); crtc_flush(crtc, flush_mask); - pm_runtime_put_autosuspend(&mdp5_kms->pdev->dev); + pm_runtime_put_sync(&mdp5_kms->pdev->dev); return 0; } @@ -943,16 +1011,6 @@ static const struct drm_crtc_funcs mdp5_crtc_funcs = { .atomic_print_state = mdp5_crtc_atomic_print_state, }; -static const struct drm_crtc_funcs mdp5_crtc_no_lm_cursor_funcs = { - .set_config = drm_atomic_helper_set_config, - .destroy = mdp5_crtc_destroy, - .page_flip = drm_atomic_helper_page_flip, - .reset = mdp5_crtc_reset, - .atomic_duplicate_state = mdp5_crtc_duplicate_state, - .atomic_destroy_state = mdp5_crtc_destroy_state, - .atomic_print_state = mdp5_crtc_atomic_print_state, -}; - static const struct drm_crtc_helper_funcs mdp5_crtc_helper_funcs = { .mode_set_nofb = mdp5_crtc_mode_set_nofb, .atomic_check = mdp5_crtc_atomic_check, @@ -1121,12 +1179,10 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev, mdp5_crtc->err.irq = mdp5_crtc_err_irq; mdp5_crtc->pp_done.irq = mdp5_crtc_pp_done_irq; - if (cursor_plane) - drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane, - &mdp5_crtc_no_lm_cursor_funcs, NULL); - else - drm_crtc_init_with_planes(dev, crtc, plane, NULL, - &mdp5_crtc_funcs, NULL); + mdp5_crtc->lm_cursor_enabled = cursor_plane ? false : true; + + drm_crtc_init_with_planes(dev, crtc, plane, cursor_plane, + &mdp5_crtc_funcs, NULL); drm_flip_work_init(&mdp5_crtc->unref_cursor_work, "unref cursor", unref_cursor_worker); diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c index 5b851380d3f2..36ad3cbe5f79 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c @@ -384,7 +384,7 @@ int mdp5_vid_encoder_set_split_display(struct drm_encoder *encoder, mdp5_ctl_pair(mdp5_encoder->ctl, mdp5_slave_enc->ctl, true); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); return 0; } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c index bb5deb00c899..280e368bc9bb 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_irq.c @@ -54,7 +54,7 @@ void mdp5_irq_preinstall(struct msm_kms *kms) pm_runtime_get_sync(dev); mdp5_write(mdp5_kms, REG_MDP5_INTR_CLEAR, 0xffffffff); mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); } int mdp5_irq_postinstall(struct msm_kms *kms) @@ -72,7 +72,7 @@ int mdp5_irq_postinstall(struct msm_kms *kms) pm_runtime_get_sync(dev); mdp_irq_register(mdp_kms, error_handler); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); return 0; } @@ -84,7 +84,7 @@ void mdp5_irq_uninstall(struct msm_kms *kms) pm_runtime_get_sync(dev); mdp5_write(mdp5_kms, REG_MDP5_INTR_EN, 0x00000000); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); } irqreturn_t mdp5_irq(struct msm_kms *kms) @@ -119,7 +119,7 @@ int mdp5_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc) pm_runtime_get_sync(dev); mdp_update_vblank_mask(to_mdp_kms(kms), mdp5_crtc_vblank(crtc), true); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); return 0; } @@ -132,5 +132,5 @@ void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc) pm_runtime_get_sync(dev); mdp_update_vblank_mask(to_mdp_kms(kms), mdp5_crtc_vblank(crtc), false); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); } diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c index 7e829a8d1cb1..3e9bba4d6624 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c @@ -125,7 +125,7 @@ static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s if (mdp5_kms->smp) mdp5_smp_complete_commit(mdp5_kms->smp, &mdp5_kms->state->smp); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); } static void mdp5_wait_for_crtc_commit_done(struct msm_kms *kms, @@ -496,12 +496,12 @@ static void read_mdp_hw_revision(struct mdp5_kms *mdp5_kms, pm_runtime_get_sync(dev); version = mdp5_read(mdp5_kms, REG_MDP5_HW_VERSION); - pm_runtime_put_autosuspend(dev); + pm_runtime_put_sync(dev); *major = FIELD(version, MDP5_HW_VERSION_MAJOR); *minor = FIELD(version, MDP5_HW_VERSION_MINOR); - DBG("MDP5 version v%d.%d", *major, *minor); + dev_info(dev, "MDP5 version v%d.%d", *major, *minor); } static int get_clk(struct platform_device *pdev, struct clk **clkp, @@ -683,7 +683,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev) aspace = NULL;; } - pm_runtime_put_autosuspend(&pdev->dev); + pm_runtime_put_sync(&pdev->dev); ret = modeset_init(mdp5_kms); if (ret) { diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c index 2bfac3712685..ff52c49095f9 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.c @@ -17,19 +17,20 @@ #include "mdp5_kms.h" -struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s, - struct drm_plane *plane, uint32_t caps, uint32_t blkcfg) +int mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane, + uint32_t caps, uint32_t blkcfg, + struct mdp5_hw_pipe **hwpipe, + struct mdp5_hw_pipe **r_hwpipe) { struct msm_drm_private *priv = s->dev->dev_private; struct mdp5_kms *mdp5_kms = to_mdp5_kms(to_mdp_kms(priv->kms)); struct mdp5_state *state; struct mdp5_hw_pipe_state *old_state, *new_state; - struct mdp5_hw_pipe *hwpipe = NULL; - int i; + int i, j; state = mdp5_get_state(s); if (IS_ERR(state)) - return ERR_CAST(state); + return PTR_ERR(state); /* grab old_state after mdp5_get_state(), since now we hold lock: */ old_state = &mdp5_kms->state->hwpipe; @@ -64,31 +65,67 @@ struct mdp5_hw_pipe *mdp5_pipe_assign(struct drm_atomic_state *s, /* possible candidate, take the one with the * fewest unneeded caps bits set: */ - if (!hwpipe || (hweight_long(cur->caps & ~caps) < - hweight_long(hwpipe->caps & ~caps))) - hwpipe = cur; + if (!(*hwpipe) || (hweight_long(cur->caps & ~caps) < + hweight_long((*hwpipe)->caps & ~caps))) { + bool r_found = false; + + if (r_hwpipe) { + for (j = i + 1; j < mdp5_kms->num_hwpipes; + j++) { + struct mdp5_hw_pipe *r_cur = + mdp5_kms->hwpipes[j]; + + /* reject different types of hwpipes */ + if (r_cur->caps != cur->caps) + continue; + + /* respect priority, eg. VIG0 > VIG1 */ + if (cur->pipe > r_cur->pipe) + continue; + + *r_hwpipe = r_cur; + r_found = true; + break; + } + } + + if (!r_hwpipe || r_found) + *hwpipe = cur; + } } - if (!hwpipe) - return ERR_PTR(-ENOMEM); + if (!(*hwpipe)) + return -ENOMEM; + + if (r_hwpipe && !(*r_hwpipe)) + return -ENOMEM; if (mdp5_kms->smp) { int ret; - DBG("%s: alloc SMP blocks", hwpipe->name); + /* We don't support SMP and 2 hwpipes/plane together */ + WARN_ON(r_hwpipe); + + DBG("%s: alloc SMP blocks", (*hwpipe)->name); ret = mdp5_smp_assign(mdp5_kms->smp, &state->smp, - hwpipe->pipe, blkcfg); + (*hwpipe)->pipe, blkcfg); if (ret) - return ERR_PTR(-ENOMEM); + return -ENOMEM; - hwpipe->blkcfg = blkcfg; + (*hwpipe)->blkcfg = blkcfg; } DBG("%s: assign to plane %s for caps %x", - hwpipe->name, plane->name, caps); - new_state->hwpipe_to_plane[hwpipe->idx] = plane; + (*hwpipe)->name, plane->name, caps); + new_state->hwpipe_to_plane[(*hwpipe)->idx] = plane; - return hwpipe; + if (r_hwpipe) { + DBG("%s: assign to right of plane %s for caps %x", + (*r_hwpipe)->name, plane->name, caps); + new_state->hwpipe_to_plane[(*r_hwpipe)->idx] = plane; + } + + return 0; } void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe) diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h index 924c3e6f9517..bb2b0ac7aa2b 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_pipe.h @@ -44,9 +44,10 @@ struct mdp5_hw_pipe_state { struct drm_plane *hwpipe_to_plane[SSPP_MAX]; }; -struct mdp5_hw_pipe *__must_check -mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane, - uint32_t caps, uint32_t blkcfg); +int mdp5_pipe_assign(struct drm_atomic_state *s, struct drm_plane *plane, + uint32_t caps, uint32_t blkcfg, + struct mdp5_hw_pipe **hwpipe, + struct mdp5_hw_pipe **r_hwpipe); void mdp5_pipe_release(struct drm_atomic_state *s, struct mdp5_hw_pipe *hwpipe); struct mdp5_hw_pipe *mdp5_pipe_init(enum mdp5_pipe pipe, diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c index df3360acacca..ee41423baeb7 100644 --- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c @@ -31,15 +31,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, struct drm_crtc *crtc, struct drm_framebuffer *fb, struct drm_rect *src, struct drm_rect *dest); -static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane, - struct drm_crtc *crtc, - struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h, - struct drm_modeset_acquire_ctx *ctx); - static struct mdp5_kms *get_kms(struct drm_plane *plane) { struct msm_drm_private *priv = plane->dev->dev_private; @@ -254,18 +245,6 @@ static const struct drm_plane_funcs mdp5_plane_funcs = { .atomic_print_state = mdp5_plane_atomic_print_state, }; -static const struct drm_plane_funcs mdp5_cursor_plane_funcs = { - .update_plane = mdp5_update_cursor_plane_legacy, - .disable_plane = drm_atomic_helper_disable_plane, - .destroy = mdp5_plane_destroy, - .atomic_set_property = mdp5_plane_atomic_set_property, - .atomic_get_property = mdp5_plane_atomic_get_property, - .reset = mdp5_plane_reset, - .atomic_duplicate_state = mdp5_plane_duplicate_state, - .atomic_destroy_state = mdp5_plane_destroy_state, - .atomic_print_state = mdp5_plane_atomic_print_state, -}; - static int mdp5_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { @@ -415,31 +394,30 @@ static int mdp5_plane_atomic_check_with_state(struct drm_crtc_state *crtc_state, struct mdp5_hw_pipe *old_hwpipe = mdp5_state->hwpipe; struct mdp5_hw_pipe *old_right_hwpipe = mdp5_state->r_hwpipe; - - mdp5_state->hwpipe = mdp5_pipe_assign(state->state, - plane, caps, blkcfg); - if (IS_ERR(mdp5_state->hwpipe)) { - DBG("%s: failed to assign hwpipe!", plane->name); - return PTR_ERR(mdp5_state->hwpipe); + struct mdp5_hw_pipe *new_hwpipe = NULL; + struct mdp5_hw_pipe *new_right_hwpipe = NULL; + + ret = mdp5_pipe_assign(state->state, plane, caps, + blkcfg, &new_hwpipe, + need_right_hwpipe ? + &new_right_hwpipe : NULL); + if (ret) { + DBG("%s: failed to assign hwpipe(s)!", + plane->name); + return ret; } - if (need_right_hwpipe) { - mdp5_state->r_hwpipe = - mdp5_pipe_assign(state->state, plane, - caps, blkcfg); - if (IS_ERR(mdp5_state->r_hwpipe)) { - DBG("%s: failed to assign right hwpipe", - plane->name); - return PTR_ERR(mdp5_state->r_hwpipe); - } - } else { + mdp5_state->hwpipe = new_hwpipe; + if (need_right_hwpipe) + mdp5_state->r_hwpipe = new_right_hwpipe; + else /* * set it to NULL so that the driver knows we * don't have a right hwpipe when committing a * new state */ mdp5_state->r_hwpipe = NULL; - } + mdp5_pipe_release(state->state, old_hwpipe); mdp5_pipe_release(state->state, old_right_hwpipe); @@ -488,11 +466,99 @@ static void mdp5_plane_atomic_update(struct drm_plane *plane, } } +static int mdp5_plane_atomic_async_check(struct drm_plane *plane, + struct drm_plane_state *state) +{ + struct mdp5_plane_state *mdp5_state = to_mdp5_plane_state(state); + struct drm_crtc_state *crtc_state; + struct drm_rect clip; + int min_scale, max_scale; + int ret; + + crtc_state = drm_atomic_get_existing_crtc_state(state->state, + state->crtc); + if (WARN_ON(!crtc_state)) + return -EINVAL; + + if (!crtc_state->active) + return -EINVAL; + + mdp5_state = to_mdp5_plane_state(state); + + /* don't use fast path if we don't have a hwpipe allocated yet */ + if (!mdp5_state->hwpipe) + return -EINVAL; + + /* only allow changing of position(crtc x/y or src x/y) in fast path */ + if (plane->state->crtc != state->crtc || + plane->state->src_w != state->src_w || + plane->state->src_h != state->src_h || + plane->state->crtc_w != state->crtc_w || + plane->state->crtc_h != state->crtc_h || + !plane->state->fb || + plane->state->fb != state->fb) + return -EINVAL; + + clip.x1 = 0; + clip.y1 = 0; + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; + min_scale = FRAC_16_16(1, 8); + max_scale = FRAC_16_16(8, 1); + + ret = drm_atomic_helper_check_plane_state(state, crtc_state, &clip, + min_scale, max_scale, + true, true); + if (ret) + return ret; + + /* + * if the visibility of the plane changes (i.e, if the cursor is + * clipped out completely, we can't take the async path because + * we need to stage/unstage the plane from the Layer Mixer(s). We + * also assign/unassign the hwpipe(s) tied to the plane. We avoid + * taking the fast path for both these reasons. + */ + if (state->visible != plane->state->visible) + return -EINVAL; + + return 0; +} + +static void mdp5_plane_atomic_async_update(struct drm_plane *plane, + struct drm_plane_state *new_state) +{ + plane->state->src_x = new_state->src_x; + plane->state->src_y = new_state->src_y; + plane->state->crtc_x = new_state->crtc_x; + plane->state->crtc_y = new_state->crtc_y; + + if (plane_enabled(new_state)) { + struct mdp5_ctl *ctl; + struct mdp5_pipeline *pipeline = + mdp5_crtc_get_pipeline(plane->crtc); + int ret; + + ret = mdp5_plane_mode_set(plane, new_state->crtc, new_state->fb, + &new_state->src, &new_state->dst); + WARN_ON(ret < 0); + + ctl = mdp5_crtc_get_ctl(new_state->crtc); + + mdp5_ctl_commit(ctl, pipeline, mdp5_plane_get_flush(plane)); + } + + *to_mdp5_plane_state(plane->state) = + *to_mdp5_plane_state(new_state); +} + static const struct drm_plane_helper_funcs mdp5_plane_helper_funcs = { .prepare_fb = mdp5_plane_prepare_fb, .cleanup_fb = mdp5_plane_cleanup_fb, .atomic_check = mdp5_plane_atomic_check, .atomic_update = mdp5_plane_atomic_update, + .atomic_async_check = mdp5_plane_atomic_async_check, + .atomic_async_update = mdp5_plane_atomic_async_update, }; static void set_scanout_locked(struct mdp5_kms *mdp5_kms, @@ -997,84 +1063,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane, return ret; } -static int mdp5_update_cursor_plane_legacy(struct drm_plane *plane, - struct drm_crtc *crtc, struct drm_framebuffer *fb, - int crtc_x, int crtc_y, - unsigned int crtc_w, unsigned int crtc_h, - uint32_t src_x, uint32_t src_y, - uint32_t src_w, uint32_t src_h, - struct drm_modeset_acquire_ctx *ctx) -{ - struct drm_plane_state *plane_state, *new_plane_state; - struct mdp5_plane_state *mdp5_pstate; - struct drm_crtc_state *crtc_state = crtc->state; - int ret; - - if (!crtc_state->active || drm_atomic_crtc_needs_modeset(crtc_state)) - goto slow; - - plane_state = plane->state; - mdp5_pstate = to_mdp5_plane_state(plane_state); - - /* don't use fast path if we don't have a hwpipe allocated yet */ - if (!mdp5_pstate->hwpipe) - goto slow; - - /* only allow changing of position(crtc x/y or src x/y) in fast path */ - if (plane_state->crtc != crtc || - plane_state->src_w != src_w || - plane_state->src_h != src_h || - plane_state->crtc_w != crtc_w || - plane_state->crtc_h != crtc_h || - !plane_state->fb || - plane_state->fb != fb) - goto slow; - - new_plane_state = mdp5_plane_duplicate_state(plane); - if (!new_plane_state) - return -ENOMEM; - - new_plane_state->src_x = src_x; - new_plane_state->src_y = src_y; - new_plane_state->src_w = src_w; - new_plane_state->src_h = src_h; - new_plane_state->crtc_x = crtc_x; - new_plane_state->crtc_y = crtc_y; - new_plane_state->crtc_w = crtc_w; - new_plane_state->crtc_h = crtc_h; - - ret = mdp5_plane_atomic_check_with_state(crtc_state, new_plane_state); - if (ret) - goto slow_free; - - if (new_plane_state->visible) { - struct mdp5_ctl *ctl; - struct mdp5_pipeline *pipeline = mdp5_crtc_get_pipeline(crtc); - - ret = mdp5_plane_mode_set(plane, crtc, fb, - &new_plane_state->src, - &new_plane_state->dst); - WARN_ON(ret < 0); - - ctl = mdp5_crtc_get_ctl(crtc); - - mdp5_ctl_commit(ctl, pipeline, mdp5_plane_get_flush(plane)); - } - - *to_mdp5_plane_state(plane_state) = - *to_mdp5_plane_state(new_plane_state); - - mdp5_plane_destroy_state(plane, new_plane_state); - - return 0; -slow_free: - mdp5_plane_destroy_state(plane, new_plane_state); -slow: - return drm_atomic_helper_update_plane(plane, crtc, fb, - crtc_x, crtc_y, crtc_w, crtc_h, - src_x, src_y, src_w, src_h, ctx); -} - /* * Use this func and the one below only after the atomic state has been * successfully swapped @@ -1134,16 +1122,9 @@ struct drm_plane *mdp5_plane_init(struct drm_device *dev, mdp5_plane->nformats = mdp_get_formats(mdp5_plane->formats, ARRAY_SIZE(mdp5_plane->formats), false); - if (type == DRM_PLANE_TYPE_CURSOR) - ret = drm_universal_plane_init(dev, plane, 0xff, - &mdp5_cursor_plane_funcs, - mdp5_plane->formats, mdp5_plane->nformats, - NULL, type, NULL); - else - ret = drm_universal_plane_init(dev, plane, 0xff, - &mdp5_plane_funcs, - mdp5_plane->formats, mdp5_plane->nformats, - NULL, type, NULL); + ret = drm_universal_plane_init(dev, plane, 0xff, &mdp5_plane_funcs, + mdp5_plane->formats, mdp5_plane->nformats, + NULL, type, NULL); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index 025d454163b0..bf5f8c39f34d 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -146,35 +146,6 @@ static void commit_worker(struct work_struct *work) complete_commit(container_of(work, struct msm_commit, work), true); } -/* - * this func is identical to the drm_atomic_helper_check, but we keep this - * because we might eventually need to have a more finegrained check - * sequence without using the atomic helpers. - * - * In the past, we first called drm_atomic_helper_check_planes, and then - * drm_atomic_helper_check_modeset. We needed this because the MDP5 plane's - * ->atomic_check could update ->mode_changed for pixel format changes. - * This, however isn't needed now because if there is a pixel format change, - * we just assign a new hwpipe for it with a new SMP allocation. We might - * eventually hit a condition where we would need to do a full modeset if - * we run out of planes. There, we'd probably need to set mode_changed. - */ -int msm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) -{ - int ret; - - ret = drm_atomic_helper_check_modeset(dev, state); - if (ret) - return ret; - - ret = drm_atomic_helper_check_planes(dev, state); - if (ret) - return ret; - - return ret; -} - /** * drm_atomic_helper_commit - commit validated state object * @dev: DRM device @@ -202,6 +173,18 @@ int msm_atomic_commit(struct drm_device *dev, if (ret) return ret; + /* + * Note that plane->atomic_async_check() should fail if we need + * to re-assign hwpipe or anything that touches global atomic + * state, so we'll never go down the async update path in those + * cases. + */ + if (state->async_update) { + drm_atomic_helper_async_commit(dev, state); + drm_atomic_helper_cleanup_planes(dev, state); + return 0; + } + c = commit_init(state); if (!c) { ret = -ENOMEM; diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index 606df7bea97b..0a3ea3034e39 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -29,9 +29,12 @@ * - 1.0.0 - initial interface * - 1.1.0 - adds madvise, and support for submits with > 4 cmd buffers * - 1.2.0 - adds explicit fence support for submit ioctl + * - 1.3.0 - adds GMEM_BASE + NR_RINGS params, SUBMITQUEUE_NEW + + * SUBMITQUEUE_CLOSE ioctls, and MSM_INFO_IOVA flag for + * MSM_GEM_INFO ioctl. */ #define MSM_VERSION_MAJOR 1 -#define MSM_VERSION_MINOR 2 +#define MSM_VERSION_MINOR 3 #define MSM_VERSION_PATCHLEVEL 0 static void msm_fb_output_poll_changed(struct drm_device *dev) @@ -44,7 +47,7 @@ static void msm_fb_output_poll_changed(struct drm_device *dev) static const struct drm_mode_config_funcs mode_config_funcs = { .fb_create = msm_framebuffer_create, .output_poll_changed = msm_fb_output_poll_changed, - .atomic_check = msm_atomic_check, + .atomic_check = drm_atomic_helper_check, .atomic_commit = msm_atomic_commit, .atomic_state_alloc = msm_atomic_state_alloc, .atomic_state_clear = msm_atomic_state_clear, @@ -211,7 +214,6 @@ static int msm_drm_uninit(struct device *dev) struct drm_device *ddev = platform_get_drvdata(pdev); struct msm_drm_private *priv = ddev->dev_private; struct msm_kms *kms = priv->kms; - struct msm_gpu *gpu = priv->gpu; struct msm_vblank_ctrl *vbl_ctrl = &priv->vblank_ctrl; struct vblank_event *vbl_ev, *tmp; @@ -253,15 +255,6 @@ static int msm_drm_uninit(struct device *dev) if (kms && kms->funcs) kms->funcs->destroy(kms); - if (gpu) { - mutex_lock(&ddev->struct_mutex); - // XXX what do we do here? - //pm_runtime_enable(&pdev->dev); - gpu->funcs->pm_suspend(gpu); - mutex_unlock(&ddev->struct_mutex); - gpu->funcs->destroy(gpu); - } - if (priv->vram.paddr) { unsigned long attrs = DMA_ATTR_NO_KERNEL_MAPPING; drm_mm_takedown(&priv->vram.mm); @@ -514,24 +507,37 @@ static void load_gpu(struct drm_device *dev) mutex_unlock(&init_lock); } -static int msm_open(struct drm_device *dev, struct drm_file *file) +static int context_init(struct drm_device *dev, struct drm_file *file) { struct msm_file_private *ctx; - /* For now, load gpu on open.. to avoid the requirement of having - * firmware in the initrd. - */ - load_gpu(dev); - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) return -ENOMEM; + msm_submitqueue_init(dev, ctx); + file->driver_priv = ctx; return 0; } +static int msm_open(struct drm_device *dev, struct drm_file *file) +{ + /* For now, load gpu on open.. to avoid the requirement of having + * firmware in the initrd. + */ + load_gpu(dev); + + return context_init(dev, file); +} + +static void context_close(struct msm_file_private *ctx) +{ + msm_submitqueue_close(ctx); + kfree(ctx); +} + static void msm_postclose(struct drm_device *dev, struct drm_file *file) { struct msm_drm_private *priv = dev->dev_private; @@ -542,7 +548,7 @@ static void msm_postclose(struct drm_device *dev, struct drm_file *file) priv->lastctx = NULL; mutex_unlock(&dev->struct_mutex); - kfree(ctx); + context_close(ctx); } static void msm_lastclose(struct drm_device *dev) @@ -737,16 +743,27 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data, struct msm_drm_private *priv = dev->dev_private; struct drm_msm_wait_fence *args = data; ktime_t timeout = to_ktime(args->timeout); + struct msm_gpu_submitqueue *queue; + struct msm_gpu *gpu = priv->gpu; + int ret; if (args->pad) { DRM_ERROR("invalid pad: %08x\n", args->pad); return -EINVAL; } - if (!priv->gpu) + if (!gpu) return 0; - return msm_wait_fence(priv->gpu->fctx, args->fence, &timeout, true); + queue = msm_submitqueue_get(file->driver_priv, args->queueid); + if (!queue) + return -ENOENT; + + ret = msm_wait_fence(gpu->rb[queue->prio]->fctx, args->fence, &timeout, + true); + + msm_submitqueue_put(queue); + return ret; } static int msm_ioctl_gem_madvise(struct drm_device *dev, void *data, @@ -787,6 +804,28 @@ unlock: return ret; } + +static int msm_ioctl_submitqueue_new(struct drm_device *dev, void *data, + struct drm_file *file) +{ + struct drm_msm_submitqueue *args = data; + + if (args->flags & ~MSM_SUBMITQUEUE_FLAGS) + return -EINVAL; + + return msm_submitqueue_create(dev, file->driver_priv, args->prio, + args->flags, &args->id); +} + + +static int msm_ioctl_submitqueue_close(struct drm_device *dev, void *data, + struct drm_file *file) +{ + u32 id = *(u32 *) data; + + return msm_submitqueue_remove(file->driver_priv, id); +} + static const struct drm_ioctl_desc msm_ioctls[] = { DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW), @@ -796,6 +835,8 @@ static const struct drm_ioctl_desc msm_ioctls[] = { DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_AUTH|DRM_RENDER_ALLOW), }; static const struct vm_operations_struct vm_ops = { diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 5e8109c07560..c646843d8822 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -56,11 +56,9 @@ struct msm_gem_address_space; struct msm_gem_vma; struct msm_file_private { - /* currently we don't do anything useful with this.. but when - * per-context address spaces are supported we'd keep track of - * the context's page-tables here. - */ - int dummy; + rwlock_t queuelock; + struct list_head submitqueues; + int queueid; }; enum msm_mdp_plane_property { @@ -76,6 +74,8 @@ struct msm_vblank_ctrl { spinlock_t lock; }; +#define MSM_GPU_MAX_RINGS 4 + struct msm_drm_private { struct drm_device *dev; @@ -108,7 +108,8 @@ struct msm_drm_private { struct drm_fb_helper *fbdev; - struct msm_rd_state *rd; + struct msm_rd_state *rd; /* debugfs to dump all submits */ + struct msm_rd_state *hangrd; /* debugfs to dump hanging submits */ struct msm_perf_state *perf; /* list of GEM objects: */ @@ -154,20 +155,12 @@ struct msm_drm_private { struct shrinker shrinker; struct msm_vblank_ctrl vblank_ctrl; - - /* task holding struct_mutex.. currently only used in submit path - * to detect and reject faults from copy_from_user() for submit - * ioctl. - */ - struct task_struct *struct_mutex_task; }; struct msm_format { uint32_t pixel_format; }; -int msm_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state); int msm_atomic_commit(struct drm_device *dev, struct drm_atomic_state *state, bool nonblock); struct drm_atomic_state *msm_atomic_state_alloc(struct drm_device *dev); @@ -219,6 +212,7 @@ struct drm_gem_object *msm_gem_prime_import_sg_table(struct drm_device *dev, int msm_gem_prime_pin(struct drm_gem_object *obj); void msm_gem_prime_unpin(struct drm_gem_object *obj); void *msm_gem_get_vaddr(struct drm_gem_object *obj); +void *msm_gem_get_vaddr_active(struct drm_gem_object *obj); void msm_gem_put_vaddr(struct drm_gem_object *obj); int msm_gem_madvise(struct drm_gem_object *obj, unsigned madv); int msm_gem_sync_object(struct drm_gem_object *obj, @@ -303,7 +297,8 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m); int msm_debugfs_late_init(struct drm_device *dev); int msm_rd_debugfs_init(struct drm_minor *minor); void msm_rd_debugfs_cleanup(struct msm_drm_private *priv); -void msm_rd_dump_submit(struct msm_gem_submit *submit); +void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, + const char *fmt, ...); int msm_perf_debugfs_init(struct drm_minor *minor); void msm_perf_debugfs_cleanup(struct msm_drm_private *priv); #else @@ -319,6 +314,18 @@ void __iomem *msm_ioremap(struct platform_device *pdev, const char *name, void msm_writel(u32 data, void __iomem *addr); u32 msm_readl(const void __iomem *addr); +struct msm_gpu_submitqueue; +int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx); +struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, + u32 id); +int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, + u32 prio, u32 flags, u32 *id); +int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id); +void msm_submitqueue_close(struct msm_file_private *ctx); + +void msm_submitqueue_destroy(struct kref *kref); + + #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) diff --git a/drivers/gpu/drm/msm/msm_fence.c b/drivers/gpu/drm/msm/msm_fence.c index a2f89bac9c16..349c12f670eb 100644 --- a/drivers/gpu/drm/msm/msm_fence.c +++ b/drivers/gpu/drm/msm/msm_fence.c @@ -31,7 +31,7 @@ msm_fence_context_alloc(struct drm_device *dev, const char *name) return ERR_PTR(-ENOMEM); fctx->dev = dev; - fctx->name = name; + strncpy(fctx->name, name, sizeof(fctx->name)); fctx->context = dma_fence_context_alloc(1); init_waitqueue_head(&fctx->event); spin_lock_init(&fctx->spinlock); diff --git a/drivers/gpu/drm/msm/msm_fence.h b/drivers/gpu/drm/msm/msm_fence.h index 56061aa1959d..1aa6a4c6530c 100644 --- a/drivers/gpu/drm/msm/msm_fence.h +++ b/drivers/gpu/drm/msm/msm_fence.h @@ -22,7 +22,7 @@ struct msm_fence_context { struct drm_device *dev; - const char *name; + char name[32]; unsigned context; /* last_fence == completed_fence --> no pending work */ uint32_t last_fence; /* last assigned fence */ diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index f15821a0d900..81fe6d6740ce 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -470,14 +470,16 @@ fail: return ret; } -void *msm_gem_get_vaddr(struct drm_gem_object *obj) +static void *get_vaddr(struct drm_gem_object *obj, unsigned madv) { struct msm_gem_object *msm_obj = to_msm_bo(obj); int ret = 0; mutex_lock(&msm_obj->lock); - if (WARN_ON(msm_obj->madv != MSM_MADV_WILLNEED)) { + if (WARN_ON(msm_obj->madv > madv)) { + dev_err(obj->dev->dev, "Invalid madv state: %u vs %u\n", + msm_obj->madv, madv); mutex_unlock(&msm_obj->lock); return ERR_PTR(-EBUSY); } @@ -513,6 +515,22 @@ fail: return ERR_PTR(ret); } +void *msm_gem_get_vaddr(struct drm_gem_object *obj) +{ + return get_vaddr(obj, MSM_MADV_WILLNEED); +} + +/* + * Don't use this! It is for the very special case of dumping + * submits from GPU hangs or faults, were the bo may already + * be MSM_MADV_DONTNEED, but we know the buffer is still on the + * active list. + */ +void *msm_gem_get_vaddr_active(struct drm_gem_object *obj) +{ + return get_vaddr(obj, __MSM_MADV_PURGED); +} + void msm_gem_put_vaddr(struct drm_gem_object *obj) { struct msm_gem_object *msm_obj = to_msm_bo(obj); @@ -610,17 +628,6 @@ int msm_gem_sync_object(struct drm_gem_object *obj, struct dma_fence *fence; int i, ret; - if (!exclusive) { - /* NOTE: _reserve_shared() must happen before _add_shared_fence(), - * which makes this a slightly strange place to call it. OTOH this - * is a convenient can-fail point to hook it in. (And similar to - * how etnaviv and nouveau handle this.) - */ - ret = reservation_object_reserve_shared(msm_obj->resv); - if (ret) - return ret; - } - fobj = reservation_object_get_list(msm_obj->resv); if (!fobj || (fobj->shared_count == 0)) { fence = reservation_object_get_excl(msm_obj->resv); @@ -1045,10 +1052,10 @@ static void *_msm_gem_kernel_new(struct drm_device *dev, uint32_t size, } vaddr = msm_gem_get_vaddr(obj); - if (!vaddr) { + if (IS_ERR(vaddr)) { msm_gem_put_iova(obj, aspace); drm_gem_object_unreference(obj); - return ERR_PTR(-ENOMEM); + return ERR_CAST(vaddr); } if (bo) diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h index 91c210d2359c..9320e184b48d 100644 --- a/drivers/gpu/drm/msm/msm_gem.h +++ b/drivers/gpu/drm/msm/msm_gem.h @@ -138,12 +138,15 @@ void msm_gem_vunmap(struct drm_gem_object *obj, enum msm_gem_lock subclass); struct msm_gem_submit { struct drm_device *dev; struct msm_gpu *gpu; - struct list_head node; /* node in gpu submit_list */ + struct list_head node; /* node in ring submit list */ struct list_head bo_list; struct ww_acquire_ctx ticket; + uint32_t seqno; /* Sequence number of the submit on the ring */ struct dma_fence *fence; + struct msm_gpu_submitqueue *queue; struct pid *pid; /* submitting process */ bool valid; /* true if no cmdstream patching needed */ + struct msm_ringbuffer *ring; unsigned int nr_cmds; unsigned int nr_bos; struct { diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c index 5d0a75d4b249..b8dc8f96caf2 100644 --- a/drivers/gpu/drm/msm/msm_gem_submit.c +++ b/drivers/gpu/drm/msm/msm_gem_submit.c @@ -31,7 +31,8 @@ #define BO_PINNED 0x2000 static struct msm_gem_submit *submit_create(struct drm_device *dev, - struct msm_gpu *gpu, uint32_t nr_bos, uint32_t nr_cmds) + struct msm_gpu *gpu, struct msm_gpu_submitqueue *queue, + uint32_t nr_bos, uint32_t nr_cmds) { struct msm_gem_submit *submit; uint64_t sz = sizeof(*submit) + ((u64)nr_bos * sizeof(submit->bos[0])) + @@ -49,6 +50,8 @@ static struct msm_gem_submit *submit_create(struct drm_device *dev, submit->fence = NULL; submit->pid = get_pid(task_pid(current)); submit->cmd = (void *)&submit->bos[nr_bos]; + submit->queue = queue; + submit->ring = gpu->rb[queue->prio]; /* initially, until copy_from_user() and bo lookup succeeds: */ submit->nr_bos = 0; @@ -66,6 +69,8 @@ void msm_gem_submit_free(struct msm_gem_submit *submit) dma_fence_put(submit->fence); list_del(&submit->node); put_pid(submit->pid); + msm_submitqueue_put(submit->queue); + kfree(submit); } @@ -156,7 +161,8 @@ out: return ret; } -static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, int i) +static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, + int i, bool backoff) { struct msm_gem_object *msm_obj = submit->bos[i].obj; @@ -166,7 +172,7 @@ static void submit_unlock_unpin_bo(struct msm_gem_submit *submit, int i) if (submit->bos[i].flags & BO_LOCKED) ww_mutex_unlock(&msm_obj->resv->lock); - if (!(submit->bos[i].flags & BO_VALID)) + if (backoff && !(submit->bos[i].flags & BO_VALID)) submit->bos[i].iova = 0; submit->bos[i].flags &= ~(BO_LOCKED | BO_PINNED); @@ -201,10 +207,10 @@ retry: fail: for (; i >= 0; i--) - submit_unlock_unpin_bo(submit, i); + submit_unlock_unpin_bo(submit, i, true); if (slow_locked > 0) - submit_unlock_unpin_bo(submit, slow_locked); + submit_unlock_unpin_bo(submit, slow_locked, true); if (ret == -EDEADLK) { struct msm_gem_object *msm_obj = submit->bos[contended].obj; @@ -221,7 +227,7 @@ fail: return ret; } -static int submit_fence_sync(struct msm_gem_submit *submit) +static int submit_fence_sync(struct msm_gem_submit *submit, bool no_implicit) { int i, ret = 0; @@ -229,7 +235,22 @@ static int submit_fence_sync(struct msm_gem_submit *submit) struct msm_gem_object *msm_obj = submit->bos[i].obj; bool write = submit->bos[i].flags & MSM_SUBMIT_BO_WRITE; - ret = msm_gem_sync_object(&msm_obj->base, submit->gpu->fctx, write); + if (!write) { + /* NOTE: _reserve_shared() must happen before + * _add_shared_fence(), which makes this a slightly + * strange place to call it. OTOH this is a + * convenient can-fail point to hook it in. + */ + ret = reservation_object_reserve_shared(msm_obj->resv); + if (ret) + return ret; + } + + if (no_implicit) + continue; + + ret = msm_gem_sync_object(&msm_obj->base, submit->ring->fctx, + write); if (ret) break; } @@ -373,7 +394,7 @@ static void submit_cleanup(struct msm_gem_submit *submit) for (i = 0; i < submit->nr_bos; i++) { struct msm_gem_object *msm_obj = submit->bos[i].obj; - submit_unlock_unpin_bo(submit, i); + submit_unlock_unpin_bo(submit, i, false); list_del_init(&msm_obj->submit_entry); drm_gem_object_unreference(&msm_obj->base); } @@ -391,6 +412,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, struct msm_gpu *gpu = priv->gpu; struct dma_fence *in_fence = NULL; struct sync_file *sync_file = NULL; + struct msm_gpu_submitqueue *queue; + struct msm_ringbuffer *ring; int out_fence_fd = -1; unsigned i; int ret; @@ -407,6 +430,12 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS) return -EINVAL; + queue = msm_submitqueue_get(ctx, args->queueid); + if (!queue) + return -ENOENT; + + ring = gpu->rb[queue->prio]; + if (args->flags & MSM_SUBMIT_FENCE_FD_IN) { in_fence = sync_file_get_fence(args->fence_fd); @@ -417,7 +446,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, * Wait if the fence is from a foreign context, or if the fence * array contains any fence from a foreign context. */ - if (!dma_fence_match_context(in_fence, gpu->fctx->context)) { + if (!dma_fence_match_context(in_fence, ring->fctx->context)) { ret = dma_fence_wait(in_fence, true); if (ret) return ret; @@ -435,9 +464,8 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, goto out_unlock; } } - priv->struct_mutex_task = current; - submit = submit_create(dev, gpu, args->nr_bos, args->nr_cmds); + submit = submit_create(dev, gpu, queue, args->nr_bos, args->nr_cmds); if (!submit) { ret = -ENOMEM; goto out_unlock; @@ -451,11 +479,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, if (ret) goto out; - if (!(args->flags & MSM_SUBMIT_NO_IMPLICIT)) { - ret = submit_fence_sync(submit); - if (ret) - goto out; - } + ret = submit_fence_sync(submit, !!(args->flags & MSM_SUBMIT_NO_IMPLICIT)); + if (ret) + goto out; ret = submit_pin_objects(submit); if (ret) @@ -522,7 +548,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data, submit->nr_cmds = i; - submit->fence = msm_fence_alloc(gpu->fctx); + submit->fence = msm_fence_alloc(ring->fctx); if (IS_ERR(submit->fence)) { ret = PTR_ERR(submit->fence); submit->fence = NULL; @@ -555,7 +581,6 @@ out: out_unlock: if (ret && (out_fence_fd >= 0)) put_unused_fd(out_fence_fd); - priv->struct_mutex_task = NULL; mutex_unlock(&dev->struct_mutex); return ret; } diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index ffbff27600e0..8d4477818ec2 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -20,6 +20,8 @@ #include "msm_mmu.h" #include "msm_fence.h" +#include <linux/string_helpers.h> + /* * Power Management: @@ -221,33 +223,102 @@ int msm_gpu_hw_init(struct msm_gpu *gpu) * Hangcheck detection for locked gpu: */ +static void update_fences(struct msm_gpu *gpu, struct msm_ringbuffer *ring, + uint32_t fence) +{ + struct msm_gem_submit *submit; + + list_for_each_entry(submit, &ring->submits, node) { + if (submit->seqno > fence) + break; + + msm_update_fence(submit->ring->fctx, + submit->fence->seqno); + } +} + +static struct msm_gem_submit * +find_submit(struct msm_ringbuffer *ring, uint32_t fence) +{ + struct msm_gem_submit *submit; + + WARN_ON(!mutex_is_locked(&ring->gpu->dev->struct_mutex)); + + list_for_each_entry(submit, &ring->submits, node) + if (submit->seqno == fence) + return submit; + + return NULL; +} + static void retire_submits(struct msm_gpu *gpu); static void recover_worker(struct work_struct *work) { struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work); struct drm_device *dev = gpu->dev; + struct msm_drm_private *priv = dev->dev_private; struct msm_gem_submit *submit; - uint32_t fence = gpu->funcs->last_fence(gpu); - - msm_update_fence(gpu->fctx, fence + 1); + struct msm_ringbuffer *cur_ring = gpu->funcs->active_ring(gpu); + int i; mutex_lock(&dev->struct_mutex); dev_err(dev->dev, "%s: hangcheck recover!\n", gpu->name); - list_for_each_entry(submit, &gpu->submit_list, node) { - if (submit->fence->seqno == (fence + 1)) { - struct task_struct *task; - - rcu_read_lock(); - task = pid_task(submit->pid, PIDTYPE_PID); - if (task) { - dev_err(dev->dev, "%s: offending task: %s\n", - gpu->name, task->comm); - } - rcu_read_unlock(); - break; + + submit = find_submit(cur_ring, cur_ring->memptrs->fence + 1); + if (submit) { + struct task_struct *task; + + rcu_read_lock(); + task = pid_task(submit->pid, PIDTYPE_PID); + if (task) { + char *cmd; + + /* + * So slightly annoying, in other paths like + * mmap'ing gem buffers, mmap_sem is acquired + * before struct_mutex, which means we can't + * hold struct_mutex across the call to + * get_cmdline(). But submits are retired + * from the same in-order workqueue, so we can + * safely drop the lock here without worrying + * about the submit going away. + */ + mutex_unlock(&dev->struct_mutex); + cmd = kstrdup_quotable_cmdline(task, GFP_KERNEL); + mutex_lock(&dev->struct_mutex); + + dev_err(dev->dev, "%s: offending task: %s (%s)\n", + gpu->name, task->comm, cmd); + + msm_rd_dump_submit(priv->hangrd, submit, + "offending task: %s (%s)", task->comm, cmd); + } else { + msm_rd_dump_submit(priv->hangrd, submit, NULL); } + rcu_read_unlock(); + } + + + /* + * Update all the rings with the latest and greatest fence.. this + * needs to happen after msm_rd_dump_submit() to ensure that the + * bo's referenced by the offending submit are still around. + */ + for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { + struct msm_ringbuffer *ring = gpu->rb[i]; + + uint32_t fence = ring->memptrs->fence; + + /* + * For the current (faulting?) ring/submit advance the fence by + * one more to clear the faulting submit + */ + if (ring == cur_ring) + fence++; + + update_fences(gpu, ring, fence); } if (msm_gpu_active(gpu)) { @@ -258,9 +329,15 @@ static void recover_worker(struct work_struct *work) gpu->funcs->recover(gpu); pm_runtime_put_sync(&gpu->pdev->dev); - /* replay the remaining submits after the one that hung: */ - list_for_each_entry(submit, &gpu->submit_list, node) { - gpu->funcs->submit(gpu, submit, NULL); + /* + * Replay all remaining submits starting with highest priority + * ring + */ + for (i = 0; i < gpu->nr_rings; i++) { + struct msm_ringbuffer *ring = gpu->rb[i]; + + list_for_each_entry(submit, &ring->submits, node) + gpu->funcs->submit(gpu, submit, NULL); } } @@ -281,25 +358,27 @@ static void hangcheck_handler(unsigned long data) struct msm_gpu *gpu = (struct msm_gpu *)data; struct drm_device *dev = gpu->dev; struct msm_drm_private *priv = dev->dev_private; - uint32_t fence = gpu->funcs->last_fence(gpu); + struct msm_ringbuffer *ring = gpu->funcs->active_ring(gpu); + uint32_t fence = ring->memptrs->fence; - if (fence != gpu->hangcheck_fence) { + if (fence != ring->hangcheck_fence) { /* some progress has been made.. ya! */ - gpu->hangcheck_fence = fence; - } else if (fence < gpu->fctx->last_fence) { + ring->hangcheck_fence = fence; + } else if (fence < ring->seqno) { /* no progress and not done.. hung! */ - gpu->hangcheck_fence = fence; - dev_err(dev->dev, "%s: hangcheck detected gpu lockup!\n", - gpu->name); + ring->hangcheck_fence = fence; + dev_err(dev->dev, "%s: hangcheck detected gpu lockup rb %d!\n", + gpu->name, ring->id); dev_err(dev->dev, "%s: completed fence: %u\n", gpu->name, fence); dev_err(dev->dev, "%s: submitted fence: %u\n", - gpu->name, gpu->fctx->last_fence); + gpu->name, ring->seqno); + queue_work(priv->wq, &gpu->recover_work); } /* if still more pending work, reset the hangcheck timer: */ - if (gpu->fctx->last_fence > gpu->hangcheck_fence) + if (ring->seqno > ring->hangcheck_fence) hangcheck_timer_reset(gpu); /* workaround for missing irq: */ @@ -428,19 +507,18 @@ static void retire_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit) static void retire_submits(struct msm_gpu *gpu) { struct drm_device *dev = gpu->dev; + struct msm_gem_submit *submit, *tmp; + int i; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - while (!list_empty(&gpu->submit_list)) { - struct msm_gem_submit *submit; + /* Retire the commits starting with highest priority */ + for (i = 0; i < gpu->nr_rings; i++) { + struct msm_ringbuffer *ring = gpu->rb[i]; - submit = list_first_entry(&gpu->submit_list, - struct msm_gem_submit, node); - - if (dma_fence_is_signaled(submit->fence)) { - retire_submit(gpu, submit); - } else { - break; + list_for_each_entry_safe(submit, tmp, &ring->submits, node) { + if (dma_fence_is_signaled(submit->fence)) + retire_submit(gpu, submit); } } } @@ -449,9 +527,10 @@ static void retire_worker(struct work_struct *work) { struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work); struct drm_device *dev = gpu->dev; - uint32_t fence = gpu->funcs->last_fence(gpu); + int i; - msm_update_fence(gpu->fctx, fence); + for (i = 0; i < gpu->nr_rings; i++) + update_fences(gpu, gpu->rb[i], gpu->rb[i]->memptrs->fence); mutex_lock(&dev->struct_mutex); retire_submits(gpu); @@ -472,6 +551,7 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, { struct drm_device *dev = gpu->dev; struct msm_drm_private *priv = dev->dev_private; + struct msm_ringbuffer *ring = submit->ring; int i; WARN_ON(!mutex_is_locked(&dev->struct_mutex)); @@ -480,9 +560,11 @@ void msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, msm_gpu_hw_init(gpu); - list_add_tail(&submit->node, &gpu->submit_list); + submit->seqno = ++ring->seqno; - msm_rd_dump_submit(submit); + list_add_tail(&submit->node, &ring->submits); + + msm_rd_dump_submit(priv->rd, submit, NULL); update_sw_cntrs(gpu); @@ -605,7 +687,9 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, struct msm_gpu *gpu, const struct msm_gpu_funcs *funcs, const char *name, struct msm_gpu_config *config) { - int ret; + int i, ret, nr_rings = config->nr_rings; + void *memptrs; + uint64_t memptrs_iova; if (WARN_ON(gpu->num_perfcntrs > ARRAY_SIZE(gpu->last_cntrs))) gpu->num_perfcntrs = ARRAY_SIZE(gpu->last_cntrs); @@ -613,18 +697,11 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, gpu->dev = drm; gpu->funcs = funcs; gpu->name = name; - gpu->fctx = msm_fence_context_alloc(drm, name); - if (IS_ERR(gpu->fctx)) { - ret = PTR_ERR(gpu->fctx); - gpu->fctx = NULL; - goto fail; - } INIT_LIST_HEAD(&gpu->active_list); INIT_WORK(&gpu->retire_work, retire_worker); INIT_WORK(&gpu->recover_work, recover_worker); - INIT_LIST_HEAD(&gpu->submit_list); setup_timer(&gpu->hangcheck_timer, hangcheck_handler, (unsigned long)gpu); @@ -689,36 +766,79 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev, goto fail; } - /* Create ringbuffer: */ - gpu->rb = msm_ringbuffer_new(gpu, config->ringsz); - if (IS_ERR(gpu->rb)) { - ret = PTR_ERR(gpu->rb); - gpu->rb = NULL; - dev_err(drm->dev, "could not create ringbuffer: %d\n", ret); + memptrs = msm_gem_kernel_new(drm, sizeof(*gpu->memptrs_bo), + MSM_BO_UNCACHED, gpu->aspace, &gpu->memptrs_bo, + &memptrs_iova); + + if (IS_ERR(memptrs)) { + ret = PTR_ERR(memptrs); + dev_err(drm->dev, "could not allocate memptrs: %d\n", ret); goto fail; } + if (nr_rings > ARRAY_SIZE(gpu->rb)) { + DRM_DEV_INFO_ONCE(drm->dev, "Only creating %zu ringbuffers\n", + ARRAY_SIZE(gpu->rb)); + nr_rings = ARRAY_SIZE(gpu->rb); + } + + /* Create ringbuffer(s): */ + for (i = 0; i < nr_rings; i++) { + gpu->rb[i] = msm_ringbuffer_new(gpu, i, memptrs, memptrs_iova); + + if (IS_ERR(gpu->rb[i])) { + ret = PTR_ERR(gpu->rb[i]); + dev_err(drm->dev, + "could not create ringbuffer %d: %d\n", i, ret); + goto fail; + } + + memptrs += sizeof(struct msm_rbmemptrs); + memptrs_iova += sizeof(struct msm_rbmemptrs); + } + + gpu->nr_rings = nr_rings; + return 0; fail: + for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { + msm_ringbuffer_destroy(gpu->rb[i]); + gpu->rb[i] = NULL; + } + + if (gpu->memptrs_bo) { + msm_gem_put_vaddr(gpu->memptrs_bo); + msm_gem_put_iova(gpu->memptrs_bo, gpu->aspace); + drm_gem_object_unreference_unlocked(gpu->memptrs_bo); + } + platform_set_drvdata(pdev, NULL); return ret; } void msm_gpu_cleanup(struct msm_gpu *gpu) { + int i; + DBG("%s", gpu->name); WARN_ON(!list_empty(&gpu->active_list)); bs_fini(gpu); - if (gpu->rb) { - if (gpu->rb_iova) - msm_gem_put_iova(gpu->rb->bo, gpu->aspace); - msm_ringbuffer_destroy(gpu->rb); + for (i = 0; i < ARRAY_SIZE(gpu->rb); i++) { + msm_ringbuffer_destroy(gpu->rb[i]); + gpu->rb[i] = NULL; } - if (gpu->aspace) { + + if (gpu->memptrs_bo) { + msm_gem_put_vaddr(gpu->memptrs_bo); + msm_gem_put_iova(gpu->memptrs_bo, gpu->aspace); + drm_gem_object_unreference_unlocked(gpu->memptrs_bo); + } + + if (!IS_ERR_OR_NULL(gpu->aspace)) { gpu->aspace->mmu->funcs->detach(gpu->aspace->mmu, NULL, 0); msm_gem_address_space_put(gpu->aspace); diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h index df4e2771fb85..e113d64574d3 100644 --- a/drivers/gpu/drm/msm/msm_gpu.h +++ b/drivers/gpu/drm/msm/msm_gpu.h @@ -33,7 +33,7 @@ struct msm_gpu_config { const char *irqname; uint64_t va_start; uint64_t va_end; - unsigned int ringsz; + unsigned int nr_rings; }; /* So far, with hardware that I've seen to date, we can have: @@ -57,9 +57,9 @@ struct msm_gpu_funcs { int (*pm_resume)(struct msm_gpu *gpu); void (*submit)(struct msm_gpu *gpu, struct msm_gem_submit *submit, struct msm_file_private *ctx); - void (*flush)(struct msm_gpu *gpu); + void (*flush)(struct msm_gpu *gpu, struct msm_ringbuffer *ring); irqreturn_t (*irq)(struct msm_gpu *irq); - uint32_t (*last_fence)(struct msm_gpu *gpu); + struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu); void (*recover)(struct msm_gpu *gpu); void (*destroy)(struct msm_gpu *gpu); #ifdef CONFIG_DEBUG_FS @@ -86,16 +86,12 @@ struct msm_gpu { const struct msm_gpu_perfcntr *perfcntrs; uint32_t num_perfcntrs; - /* ringbuffer: */ - struct msm_ringbuffer *rb; - uint64_t rb_iova; + struct msm_ringbuffer *rb[MSM_GPU_MAX_RINGS]; + int nr_rings; /* list of GEM active objects: */ struct list_head active_list; - /* fencing: */ - struct msm_fence_context *fctx; - /* does gpu need hw_init? */ bool needs_hw_init; @@ -126,15 +122,31 @@ struct msm_gpu { #define DRM_MSM_HANGCHECK_PERIOD 500 /* in ms */ #define DRM_MSM_HANGCHECK_JIFFIES msecs_to_jiffies(DRM_MSM_HANGCHECK_PERIOD) struct timer_list hangcheck_timer; - uint32_t hangcheck_fence; struct work_struct recover_work; - struct list_head submit_list; + struct drm_gem_object *memptrs_bo; }; +/* It turns out that all targets use the same ringbuffer size */ +#define MSM_GPU_RINGBUFFER_SZ SZ_32K +#define MSM_GPU_RINGBUFFER_BLKSIZE 32 + +#define MSM_GPU_RB_CNTL_DEFAULT \ + (AXXX_CP_RB_CNTL_BUFSZ(ilog2(MSM_GPU_RINGBUFFER_SZ / 8)) | \ + AXXX_CP_RB_CNTL_BLKSZ(ilog2(MSM_GPU_RINGBUFFER_BLKSIZE / 8))) + static inline bool msm_gpu_active(struct msm_gpu *gpu) { - return gpu->fctx->last_fence > gpu->funcs->last_fence(gpu); + int i; + + for (i = 0; i < gpu->nr_rings; i++) { + struct msm_ringbuffer *ring = gpu->rb[i]; + + if (ring->seqno > ring->memptrs->fence) + return true; + } + + return false; } /* Perf-Counters: @@ -150,6 +162,15 @@ struct msm_gpu_perfcntr { const char *name; }; +struct msm_gpu_submitqueue { + int id; + u32 flags; + u32 prio; + int faults; + struct list_head node; + struct kref ref; +}; + static inline void gpu_write(struct msm_gpu *gpu, u32 reg, u32 data) { msm_writel(data, gpu->mmio + (reg << 2)); @@ -223,4 +244,10 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev); void __init adreno_register(void); void __exit adreno_unregister(void); +static inline void msm_submitqueue_put(struct msm_gpu_submitqueue *queue) +{ + if (queue) + kref_put(&queue->ref, msm_submitqueue_destroy); +} + #endif /* __MSM_GPU_H__ */ diff --git a/drivers/gpu/drm/msm/msm_rd.c b/drivers/gpu/drm/msm/msm_rd.c index 0366b8092f97..3aa8a8576abe 100644 --- a/drivers/gpu/drm/msm/msm_rd.c +++ b/drivers/gpu/drm/msm/msm_rd.c @@ -19,11 +19,17 @@ * * tail -f /sys/kernel/debug/dri/<minor>/rd > logfile.rd * - * To log the cmdstream in a format that is understood by freedreno/cffdump + * to log the cmdstream in a format that is understood by freedreno/cffdump * utility. By comparing the last successfully completed fence #, to the * cmdstream for the next fence, you can narrow down which process and submit * caused the gpu crash/lockup. * + * Additionally: + * + * tail -f /sys/kernel/debug/dri/<minor>/hangrd > logfile.rd + * + * will capture just the cmdstream from submits which triggered a GPU hang. + * * This bypasses drm_debugfs_create_files() mainly because we need to use * our own fops for a bit more control. In particular, we don't want to * do anything if userspace doesn't have the debugfs file open. @@ -111,10 +117,14 @@ static void rd_write(struct msm_rd_state *rd, const void *buf, int sz) wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0); + /* Note that smp_load_acquire() is not strictly required + * as CIRC_SPACE_TO_END() does not access the tail more + * than once. + */ n = min(sz, circ_space_to_end(&rd->fifo)); memcpy(fptr, ptr, n); - fifo->head = (fifo->head + n) & (BUF_SZ - 1); + smp_store_release(&fifo->head, (fifo->head + n) & (BUF_SZ - 1)); sz -= n; ptr += n; @@ -145,13 +155,17 @@ static ssize_t rd_read(struct file *file, char __user *buf, if (ret) goto out; + /* Note that smp_load_acquire() is not strictly required + * as CIRC_CNT_TO_END() does not access the head more than + * once. + */ n = min_t(int, sz, circ_count_to_end(&rd->fifo)); if (copy_to_user(buf, fptr, n)) { ret = -EFAULT; goto out; } - fifo->tail = (fifo->tail + n) & (BUF_SZ - 1); + smp_store_release(&fifo->tail, (fifo->tail + n) & (BUF_SZ - 1)); *ppos += n; wake_up_all(&rd->fifo_event); @@ -212,53 +226,89 @@ static const struct file_operations rd_debugfs_fops = { .release = rd_release, }; -int msm_rd_debugfs_init(struct drm_minor *minor) + +static void rd_cleanup(struct msm_rd_state *rd) +{ + if (!rd) + return; + + mutex_destroy(&rd->read_lock); + kfree(rd); +} + +static struct msm_rd_state *rd_init(struct drm_minor *minor, const char *name) { - struct msm_drm_private *priv = minor->dev->dev_private; struct msm_rd_state *rd; struct dentry *ent; - - /* only create on first minor: */ - if (priv->rd) - return 0; + int ret = 0; rd = kzalloc(sizeof(*rd), GFP_KERNEL); if (!rd) - return -ENOMEM; + return ERR_PTR(-ENOMEM); rd->dev = minor->dev; rd->fifo.buf = rd->buf; mutex_init(&rd->read_lock); - priv->rd = rd; init_waitqueue_head(&rd->fifo_event); - ent = debugfs_create_file("rd", S_IFREG | S_IRUGO, + ent = debugfs_create_file(name, S_IFREG | S_IRUGO, minor->debugfs_root, rd, &rd_debugfs_fops); if (!ent) { - DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/rd\n", - minor->debugfs_root); + DRM_ERROR("Cannot create /sys/kernel/debug/dri/%pd/%s\n", + minor->debugfs_root, name); + ret = -ENOMEM; + goto fail; + } + + return rd; + +fail: + rd_cleanup(rd); + return ERR_PTR(ret); +} + +int msm_rd_debugfs_init(struct drm_minor *minor) +{ + struct msm_drm_private *priv = minor->dev->dev_private; + struct msm_rd_state *rd; + int ret; + + /* only create on first minor: */ + if (priv->rd) + return 0; + + rd = rd_init(minor, "rd"); + if (IS_ERR(rd)) { + ret = PTR_ERR(rd); goto fail; } + priv->rd = rd; + + rd = rd_init(minor, "hangrd"); + if (IS_ERR(rd)) { + ret = PTR_ERR(rd); + goto fail; + } + + priv->hangrd = rd; + return 0; fail: msm_rd_debugfs_cleanup(priv); - return -1; + return ret; } void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) { - struct msm_rd_state *rd = priv->rd; - - if (!rd) - return; - + rd_cleanup(priv->rd); priv->rd = NULL; - mutex_destroy(&rd->read_lock); - kfree(rd); + + rd_cleanup(priv->hangrd); + priv->hangrd = NULL; } static void snapshot_buf(struct msm_rd_state *rd, @@ -268,10 +318,6 @@ static void snapshot_buf(struct msm_rd_state *rd, struct msm_gem_object *obj = submit->bos[idx].obj; const char *buf; - buf = msm_gem_get_vaddr(&obj->base); - if (IS_ERR(buf)) - return; - if (iova) { buf += iova - submit->bos[idx].iova; } else { @@ -279,20 +325,33 @@ static void snapshot_buf(struct msm_rd_state *rd, size = obj->base.size; } + /* + * Always write the GPUADDR header so can get a complete list of all the + * buffers in the cmd + */ rd_write_section(rd, RD_GPUADDR, (uint32_t[3]){ iova, size, iova >> 32 }, 12); + + /* But only dump the contents of buffers marked READ */ + if (!(submit->bos[idx].flags & MSM_SUBMIT_BO_READ)) + return; + + buf = msm_gem_get_vaddr_active(&obj->base); + if (IS_ERR(buf)) + return; + rd_write_section(rd, RD_BUFFER_CONTENTS, buf, size); msm_gem_put_vaddr(&obj->base); } /* called under struct_mutex */ -void msm_rd_dump_submit(struct msm_gem_submit *submit) +void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit, + const char *fmt, ...) { struct drm_device *dev = submit->dev; - struct msm_drm_private *priv = dev->dev_private; - struct msm_rd_state *rd = priv->rd; - char msg[128]; + struct task_struct *task; + char msg[256]; int i, n; if (!rd->open) @@ -303,23 +362,32 @@ void msm_rd_dump_submit(struct msm_gem_submit *submit) */ WARN_ON(!mutex_is_locked(&dev->struct_mutex)); - n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u", - TASK_COMM_LEN, current->comm, task_pid_nr(current), - submit->fence->seqno); + if (fmt) { + va_list args; - rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4)); + va_start(args, fmt); + n = vsnprintf(msg, sizeof(msg), fmt, args); + va_end(args); - if (rd_full) { - for (i = 0; i < submit->nr_bos; i++) { - /* buffers that are written to probably don't start out - * with anything interesting: - */ - if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE) - continue; + rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4)); + } - snapshot_buf(rd, submit, i, 0, 0); - } + rcu_read_lock(); + task = pid_task(submit->pid, PIDTYPE_PID); + if (task) { + n = snprintf(msg, sizeof(msg), "%.*s/%d: fence=%u", + TASK_COMM_LEN, task->comm, + pid_nr(submit->pid), submit->seqno); + } else { + n = snprintf(msg, sizeof(msg), "???/%d: fence=%u", + pid_nr(submit->pid), submit->seqno); } + rcu_read_unlock(); + + rd_write_section(rd, RD_CMD, msg, ALIGN(n, 4)); + + for (i = 0; rd_full && i < submit->nr_bos; i++) + snapshot_buf(rd, submit, i, 0, 0); for (i = 0; i < submit->nr_cmds; i++) { uint64_t iova = submit->cmd[i].iova; diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.c b/drivers/gpu/drm/msm/msm_ringbuffer.c index bf065a540130..6ca98da35f63 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.c +++ b/drivers/gpu/drm/msm/msm_ringbuffer.c @@ -18,13 +18,15 @@ #include "msm_ringbuffer.h" #include "msm_gpu.h" -struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size) +struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, + void *memptrs, uint64_t memptrs_iova) { struct msm_ringbuffer *ring; + char name[32]; int ret; - if (WARN_ON(!is_power_of_2(size))) - return ERR_PTR(-EINVAL); + /* We assume everwhere that MSM_GPU_RINGBUFFER_SZ is a power of 2 */ + BUILD_BUG_ON(!is_power_of_2(MSM_GPU_RINGBUFFER_SZ)); ring = kzalloc(sizeof(*ring), GFP_KERNEL); if (!ring) { @@ -33,32 +35,46 @@ struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size) } ring->gpu = gpu; - + ring->id = id; /* Pass NULL for the iova pointer - we will map it later */ - ring->start = msm_gem_kernel_new(gpu->dev, size, MSM_BO_WC, - gpu->aspace, &ring->bo, NULL); + ring->start = msm_gem_kernel_new(gpu->dev, MSM_GPU_RINGBUFFER_SZ, + MSM_BO_WC, gpu->aspace, &ring->bo, NULL); if (IS_ERR(ring->start)) { ret = PTR_ERR(ring->start); ring->start = 0; goto fail; } - ring->end = ring->start + (size / 4); + ring->end = ring->start + (MSM_GPU_RINGBUFFER_SZ >> 2); + ring->next = ring->start; ring->cur = ring->start; - ring->size = size; + ring->memptrs = memptrs; + ring->memptrs_iova = memptrs_iova; + + INIT_LIST_HEAD(&ring->submits); + spin_lock_init(&ring->lock); + + snprintf(name, sizeof(name), "gpu-ring-%d", ring->id); + + ring->fctx = msm_fence_context_alloc(gpu->dev, name); return ring; fail: - if (ring) - msm_ringbuffer_destroy(ring); + msm_ringbuffer_destroy(ring); return ERR_PTR(ret); } void msm_ringbuffer_destroy(struct msm_ringbuffer *ring) { + if (IS_ERR_OR_NULL(ring)) + return; + + msm_fence_context_free(ring->fctx); + if (ring->bo) { + msm_gem_put_iova(ring->bo, ring->gpu->aspace); msm_gem_put_vaddr(ring->bo); drm_gem_object_unreference_unlocked(ring->bo); } diff --git a/drivers/gpu/drm/msm/msm_ringbuffer.h b/drivers/gpu/drm/msm/msm_ringbuffer.h index 6e0e1049fa4f..cffce094aecb 100644 --- a/drivers/gpu/drm/msm/msm_ringbuffer.h +++ b/drivers/gpu/drm/msm/msm_ringbuffer.h @@ -20,14 +20,31 @@ #include "msm_drv.h" +#define rbmemptr(ring, member) \ + ((ring)->memptrs_iova + offsetof(struct msm_rbmemptrs, member)) + +struct msm_rbmemptrs { + volatile uint32_t rptr; + volatile uint32_t fence; +}; + struct msm_ringbuffer { struct msm_gpu *gpu; - int size; + int id; struct drm_gem_object *bo; - uint32_t *start, *end, *cur; + uint32_t *start, *end, *cur, *next; + struct list_head submits; + uint64_t iova; + uint32_t seqno; + uint32_t hangcheck_fence; + struct msm_rbmemptrs *memptrs; + uint64_t memptrs_iova; + struct msm_fence_context *fctx; + spinlock_t lock; }; -struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int size); +struct msm_ringbuffer *msm_ringbuffer_new(struct msm_gpu *gpu, int id, + void *memptrs, uint64_t memptrs_iova); void msm_ringbuffer_destroy(struct msm_ringbuffer *ring); /* ringbuffer helpers (the parts that are same for a3xx/a2xx/z180..) */ @@ -35,9 +52,13 @@ void msm_ringbuffer_destroy(struct msm_ringbuffer *ring); static inline void OUT_RING(struct msm_ringbuffer *ring, uint32_t data) { - if (ring->cur == ring->end) - ring->cur = ring->start; - *(ring->cur++) = data; + /* + * ring->next points to the current command being written - it won't be + * committed as ring->cur until the flush + */ + if (ring->next == ring->end) + ring->next = ring->start; + *(ring->next++) = data; } #endif /* __MSM_RINGBUFFER_H__ */ diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c b/drivers/gpu/drm/msm/msm_submitqueue.c new file mode 100644 index 000000000000..5115f75b5b7f --- /dev/null +++ b/drivers/gpu/drm/msm/msm_submitqueue.c @@ -0,0 +1,152 @@ +/* Copyright (c) 2017 The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <linux/kref.h> +#include "msm_gpu.h" + +void msm_submitqueue_destroy(struct kref *kref) +{ + struct msm_gpu_submitqueue *queue = container_of(kref, + struct msm_gpu_submitqueue, ref); + + kfree(queue); +} + +struct msm_gpu_submitqueue *msm_submitqueue_get(struct msm_file_private *ctx, + u32 id) +{ + struct msm_gpu_submitqueue *entry; + + if (!ctx) + return NULL; + + read_lock(&ctx->queuelock); + + list_for_each_entry(entry, &ctx->submitqueues, node) { + if (entry->id == id) { + kref_get(&entry->ref); + read_unlock(&ctx->queuelock); + + return entry; + } + } + + read_unlock(&ctx->queuelock); + return NULL; +} + +void msm_submitqueue_close(struct msm_file_private *ctx) +{ + struct msm_gpu_submitqueue *entry, *tmp; + + if (!ctx) + return; + + /* + * No lock needed in close and there won't + * be any more user ioctls coming our way + */ + list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node) + msm_submitqueue_put(entry); +} + +int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private *ctx, + u32 prio, u32 flags, u32 *id) +{ + struct msm_drm_private *priv = drm->dev_private; + struct msm_gpu_submitqueue *queue; + + if (!ctx) + return -ENODEV; + + queue = kzalloc(sizeof(*queue), GFP_KERNEL); + + if (!queue) + return -ENOMEM; + + kref_init(&queue->ref); + queue->flags = flags; + + if (priv->gpu) { + if (prio >= priv->gpu->nr_rings) + return -EINVAL; + + queue->prio = prio; + } + + write_lock(&ctx->queuelock); + + queue->id = ctx->queueid++; + + if (id) + *id = queue->id; + + list_add_tail(&queue->node, &ctx->submitqueues); + + write_unlock(&ctx->queuelock); + + return 0; +} + +int msm_submitqueue_init(struct drm_device *drm, struct msm_file_private *ctx) +{ + struct msm_drm_private *priv = drm->dev_private; + int default_prio; + + if (!ctx) + return 0; + + /* + * Select priority 2 as the "default priority" unless nr_rings is less + * than 2 and then pick the lowest pirority + */ + default_prio = priv->gpu ? + clamp_t(uint32_t, 2, 0, priv->gpu->nr_rings - 1) : 0; + + INIT_LIST_HEAD(&ctx->submitqueues); + + rwlock_init(&ctx->queuelock); + + return msm_submitqueue_create(drm, ctx, default_prio, 0, NULL); +} + +int msm_submitqueue_remove(struct msm_file_private *ctx, u32 id) +{ + struct msm_gpu_submitqueue *entry; + + if (!ctx) + return 0; + + /* + * id 0 is the "default" queue and can't be destroyed + * by the user + */ + if (!id) + return -ENOENT; + + write_lock(&ctx->queuelock); + + list_for_each_entry(entry, &ctx->submitqueues, node) { + if (entry->id == id) { + list_del(&entry->node); + write_unlock(&ctx->queuelock); + + msm_submitqueue_put(entry); + return 0; + } + } + + write_unlock(&ctx->queuelock); + return -ENOENT; +} + diff --git a/drivers/gpu/drm/nouveau/Kbuild b/drivers/gpu/drm/nouveau/Kbuild index 2e9ce53ae3a8..9c0c650655e9 100644 --- a/drivers/gpu/drm/nouveau/Kbuild +++ b/drivers/gpu/drm/nouveau/Kbuild @@ -30,9 +30,11 @@ nouveau-y += nouveau_vga.o # DRM - memory management nouveau-y += nouveau_bo.o nouveau-y += nouveau_gem.o +nouveau-y += nouveau_mem.o nouveau-y += nouveau_prime.o nouveau-y += nouveau_sgdma.o nouveau-y += nouveau_ttm.o +nouveau-y += nouveau_vmm.o # DRM - modesetting nouveau-$(CONFIG_DRM_NOUVEAU_BACKLIGHT) += nouveau_backlight.o diff --git a/drivers/gpu/drm/nouveau/Kconfig b/drivers/gpu/drm/nouveau/Kconfig index c02a13406a81..4b75ad40dd80 100644 --- a/drivers/gpu/drm/nouveau/Kconfig +++ b/drivers/gpu/drm/nouveau/Kconfig @@ -56,6 +56,13 @@ config NOUVEAU_DEBUG_DEFAULT help Selects the default debug level +config NOUVEAU_DEBUG_MMU + bool "Enable additional MMU debugging" + depends on DRM_NOUVEAU + default n + help + Say Y here if you want to enable verbose MMU debug output. + config DRM_NOUVEAU_BACKLIGHT bool "Support for backlight control" depends on DRM_NOUVEAU diff --git a/drivers/gpu/drm/nouveau/dispnv04/disp.c b/drivers/gpu/drm/nouveau/dispnv04/disp.c index 5b9d549aa791..501d2d290e9c 100644 --- a/drivers/gpu/drm/nouveau/dispnv04/disp.c +++ b/drivers/gpu/drm/nouveau/dispnv04/disp.c @@ -48,7 +48,7 @@ nv04_display_create(struct drm_device *dev) if (!disp) return -ENOMEM; - nvif_object_map(&drm->client.device.object); + nvif_object_map(&drm->client.device.object, NULL, 0); nouveau_display(dev)->priv = disp; nouveau_display(dev)->dtor = nv04_display_destroy; diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h index aa94b8cf9679..f50866011002 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl506e.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl506e.h @@ -5,7 +5,7 @@ struct nv50_channel_dma_v0 { __u8 version; __u8 chid; __u8 pad02[6]; - __u64 vm; + __u64 vmm; __u64 pushbuf; __u64 offset; }; diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h index 3b7101966de4..0e5bbb553158 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl506f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl506f.h @@ -8,6 +8,6 @@ struct nv50_channel_gpfifo_v0 { __u32 ilength; __u64 ioffset; __u64 pushbuf; - __u64 vm; + __u64 vmm; }; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h index 91e33db21a2f..7f6a8ce5a418 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl826e.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl826e.h @@ -5,7 +5,7 @@ struct g82_channel_dma_v0 { __u8 version; __u8 chid; __u8 pad02[6]; - __u64 vm; + __u64 vmm; __u64 pushbuf; __u64 offset; }; diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h index e34efd4ec537..c4d35522331a 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl826f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl826f.h @@ -8,7 +8,7 @@ struct g82_channel_gpfifo_v0 { __u32 ilength; __u64 ioffset; __u64 pushbuf; - __u64 vm; + __u64 vmm; }; #define NV826F_V0_NTFY_NON_STALL_INTERRUPT 0x00 diff --git a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h index a2d5410a491b..169161c1587f 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cl906f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cl906f.h @@ -7,7 +7,7 @@ struct fermi_channel_gpfifo_v0 { __u8 pad02[2]; __u32 ilength; __u64 ioffset; - __u64 vm; + __u64 vmm; }; #define NV906F_V0_NTFY_NON_STALL_INTERRUPT 0x00 diff --git a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h index 2efa3d048bb9..3e57089526e3 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/cla06f.h +++ b/drivers/gpu/drm/nouveau/include/nvif/cla06f.h @@ -22,7 +22,7 @@ struct kepler_channel_gpfifo_a_v0 { __u32 engines; __u32 ilength; __u64 ioffset; - __u64 vm; + __u64 vmm; }; #define NVA06F_V0_NTFY_NON_STALL_INTERRUPT 0x00 diff --git a/drivers/gpu/drm/nouveau/include/nvif/class.h b/drivers/gpu/drm/nouveau/include/nvif/class.h index d08da82ba7ed..56aade45067d 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/class.h +++ b/drivers/gpu/drm/nouveau/include/nvif/class.h @@ -14,6 +14,23 @@ #define NVIF_CLASS_SW_NV50 /* if0005.h */ -0x00000006 #define NVIF_CLASS_SW_GF100 /* if0005.h */ -0x00000007 +#define NVIF_CLASS_MMU /* if0008.h */ 0x80000008 +#define NVIF_CLASS_MMU_NV04 /* if0008.h */ 0x80000009 +#define NVIF_CLASS_MMU_NV50 /* if0008.h */ 0x80005009 +#define NVIF_CLASS_MMU_GF100 /* if0008.h */ 0x80009009 + +#define NVIF_CLASS_MEM /* if000a.h */ 0x8000000a +#define NVIF_CLASS_MEM_NV04 /* if000b.h */ 0x8000000b +#define NVIF_CLASS_MEM_NV50 /* if500b.h */ 0x8000500b +#define NVIF_CLASS_MEM_GF100 /* if900b.h */ 0x8000900b + +#define NVIF_CLASS_VMM /* if000c.h */ 0x8000000c +#define NVIF_CLASS_VMM_NV04 /* if000d.h */ 0x8000000d +#define NVIF_CLASS_VMM_NV50 /* if500d.h */ 0x8000500d +#define NVIF_CLASS_VMM_GF100 /* if900d.h */ 0x8000900d +#define NVIF_CLASS_VMM_GM200 /* ifb00d.h */ 0x8000b00d +#define NVIF_CLASS_VMM_GP100 /* ifc00d.h */ 0x8000c00d + /* the below match nvidia-assigned (either in hw, or sw) class numbers */ #define NV_NULL_CLASS 0x00000030 diff --git a/drivers/gpu/drm/nouveau/include/nvif/device.h b/drivers/gpu/drm/nouveau/include/nvif/device.h index bcb981711617..b579633b80c0 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/device.h +++ b/drivers/gpu/drm/nouveau/include/nvif/device.h @@ -38,7 +38,6 @@ u64 nvif_device_time(struct nvif_device *); /*XXX*/ #include <subdev/bios.h> #include <subdev/fb.h> -#include <subdev/mmu.h> #include <subdev/bar.h> #include <subdev/gpio.h> #include <subdev/clk.h> @@ -57,8 +56,6 @@ u64 nvif_device_time(struct nvif_device *); }) #define nvxx_bios(a) nvxx_device(a)->bios #define nvxx_fb(a) nvxx_device(a)->fb -#define nvxx_mmu(a) nvxx_device(a)->mmu -#define nvxx_bar(a) nvxx_device(a)->bar #define nvxx_gpio(a) nvxx_device(a)->gpio #define nvxx_clk(a) nvxx_device(a)->clk #define nvxx_i2c(a) nvxx_device(a)->i2c @@ -66,10 +63,8 @@ u64 nvif_device_time(struct nvif_device *); #define nvxx_therm(a) nvxx_device(a)->therm #define nvxx_volt(a) nvxx_device(a)->volt -#include <core/device.h> #include <engine/fifo.h> #include <engine/gr.h> -#include <engine/sw.h> #define nvxx_fifo(a) nvxx_device(a)->fifo #define nvxx_gr(a) nvxx_device(a)->gr diff --git a/drivers/gpu/drm/nouveau/include/nvif/if0008.h b/drivers/gpu/drm/nouveau/include/nvif/if0008.h new file mode 100644 index 000000000000..8450127420f5 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if0008.h @@ -0,0 +1,42 @@ +#ifndef __NVIF_IF0008_H__ +#define __NVIF_IF0008_H__ +struct nvif_mmu_v0 { + __u8 version; + __u8 dmabits; + __u8 heap_nr; + __u8 type_nr; + __u16 kind_nr; +}; + +#define NVIF_MMU_V0_HEAP 0x00 +#define NVIF_MMU_V0_TYPE 0x01 +#define NVIF_MMU_V0_KIND 0x02 + +struct nvif_mmu_heap_v0 { + __u8 version; + __u8 index; + __u8 pad02[6]; + __u64 size; +}; + +struct nvif_mmu_type_v0 { + __u8 version; + __u8 index; + __u8 heap; + __u8 vram; + __u8 host; + __u8 comp; + __u8 disp; + __u8 kind; + __u8 mappable; + __u8 coherent; + __u8 uncached; +}; + +struct nvif_mmu_kind_v0 { + __u8 version; + __u8 pad01[1]; + __u16 count; + __u8 data[]; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000a.h b/drivers/gpu/drm/nouveau/include/nvif/if000a.h new file mode 100644 index 000000000000..88d0938fbd5a --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if000a.h @@ -0,0 +1,22 @@ +#ifndef __NVIF_IF000A_H__ +#define __NVIF_IF000A_H__ +struct nvif_mem_v0 { + __u8 version; + __u8 type; + __u8 page; + __u8 pad03[5]; + __u64 size; + __u64 addr; + __u8 data[]; +}; + +struct nvif_mem_ram_vn { +}; + +struct nvif_mem_ram_v0 { + __u8 version; + __u8 pad01[7]; + dma_addr_t *dma; + struct scatterlist *sgl; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000b.h b/drivers/gpu/drm/nouveau/include/nvif/if000b.h new file mode 100644 index 000000000000..c677fb0293da --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if000b.h @@ -0,0 +1,11 @@ +#ifndef __NVIF_IF000B_H__ +#define __NVIF_IF000B_H__ +#include "if000a.h" + +struct nv04_mem_vn { + /* nvkm_mem_vX ... */ +}; + +struct nv04_mem_map_vn { +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000c.h b/drivers/gpu/drm/nouveau/include/nvif/if000c.h new file mode 100644 index 000000000000..2928ecd989ad --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if000c.h @@ -0,0 +1,64 @@ +#ifndef __NVIF_IF000C_H__ +#define __NVIF_IF000C_H__ +struct nvif_vmm_v0 { + __u8 version; + __u8 page_nr; + __u8 pad02[6]; + __u64 addr; + __u64 size; + __u8 data[]; +}; + +#define NVIF_VMM_V0_PAGE 0x00 +#define NVIF_VMM_V0_GET 0x01 +#define NVIF_VMM_V0_PUT 0x02 +#define NVIF_VMM_V0_MAP 0x03 +#define NVIF_VMM_V0_UNMAP 0x04 + +struct nvif_vmm_page_v0 { + __u8 version; + __u8 index; + __u8 shift; + __u8 sparse; + __u8 vram; + __u8 host; + __u8 comp; + __u8 pad07[1]; +}; + +struct nvif_vmm_get_v0 { + __u8 version; +#define NVIF_VMM_GET_V0_ADDR 0x00 +#define NVIF_VMM_GET_V0_PTES 0x01 +#define NVIF_VMM_GET_V0_LAZY 0x02 + __u8 type; + __u8 sparse; + __u8 page; + __u8 align; + __u8 pad05[3]; + __u64 size; + __u64 addr; +}; + +struct nvif_vmm_put_v0 { + __u8 version; + __u8 pad01[7]; + __u64 addr; +}; + +struct nvif_vmm_map_v0 { + __u8 version; + __u8 pad01[7]; + __u64 addr; + __u64 size; + __u64 memory; + __u64 offset; + __u8 data[]; +}; + +struct nvif_vmm_unmap_v0 { + __u8 version; + __u8 pad01[7]; + __u64 addr; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if000d.h b/drivers/gpu/drm/nouveau/include/nvif/if000d.h new file mode 100644 index 000000000000..516ec9401401 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if000d.h @@ -0,0 +1,12 @@ +#ifndef __NVIF_IF000D_H__ +#define __NVIF_IF000D_H__ +#include "if000c.h" + +struct nv04_vmm_vn { + /* nvif_vmm_vX ... */ +}; + +struct nv04_vmm_map_vn { + /* nvif_vmm_map_vX ... */ +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if500b.h b/drivers/gpu/drm/nouveau/include/nvif/if500b.h new file mode 100644 index 000000000000..c7c8431fb2ce --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if500b.h @@ -0,0 +1,25 @@ +#ifndef __NVIF_IF500B_H__ +#define __NVIF_IF500B_H__ +#include "if000a.h" + +struct nv50_mem_vn { + /* nvif_mem_vX ... */ +}; + +struct nv50_mem_v0 { + /* nvif_mem_vX ... */ + __u8 version; + __u8 bankswz; + __u8 contig; +}; + +struct nv50_mem_map_vn { +}; + +struct nv50_mem_map_v0 { + __u8 version; + __u8 ro; + __u8 kind; + __u8 comp; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if500d.h b/drivers/gpu/drm/nouveau/include/nvif/if500d.h new file mode 100644 index 000000000000..c29a7822b363 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if500d.h @@ -0,0 +1,21 @@ +#ifndef __NVIF_IF500D_H__ +#define __NVIF_IF500D_H__ +#include "if000c.h" + +struct nv50_vmm_vn { + /* nvif_vmm_vX ... */ +}; + +struct nv50_vmm_map_vn { + /* nvif_vmm_map_vX ... */ +}; + +struct nv50_vmm_map_v0 { + /* nvif_vmm_map_vX ... */ + __u8 version; + __u8 ro; + __u8 priv; + __u8 kind; + __u8 comp; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if900b.h b/drivers/gpu/drm/nouveau/include/nvif/if900b.h new file mode 100644 index 000000000000..9b164548eea8 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if900b.h @@ -0,0 +1,23 @@ +#ifndef __NVIF_IF900B_H__ +#define __NVIF_IF900B_H__ +#include "if000a.h" + +struct gf100_mem_vn { + /* nvif_mem_vX ... */ +}; + +struct gf100_mem_v0 { + /* nvif_mem_vX ... */ + __u8 version; + __u8 contig; +}; + +struct gf100_mem_map_vn { +}; + +struct gf100_mem_map_v0 { + __u8 version; + __u8 ro; + __u8 kind; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/if900d.h b/drivers/gpu/drm/nouveau/include/nvif/if900d.h new file mode 100644 index 000000000000..49aa50583c3d --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/if900d.h @@ -0,0 +1,21 @@ +#ifndef __NVIF_IF900D_H__ +#define __NVIF_IF900D_H__ +#include "if000c.h" + +struct gf100_vmm_vn { + /* nvif_vmm_vX ... */ +}; + +struct gf100_vmm_map_vn { + /* nvif_vmm_map_vX ... */ +}; + +struct gf100_vmm_map_v0 { + /* nvif_vmm_map_vX ... */ + __u8 version; + __u8 vol; + __u8 ro; + __u8 priv; + __u8 kind; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/ifb00d.h b/drivers/gpu/drm/nouveau/include/nvif/ifb00d.h new file mode 100644 index 000000000000..a0e419830595 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/ifb00d.h @@ -0,0 +1,27 @@ +#ifndef __NVIF_IFB00D_H__ +#define __NVIF_IFB00D_H__ +#include "if000c.h" + +struct gm200_vmm_vn { + /* nvif_vmm_vX ... */ +}; + +struct gm200_vmm_v0 { + /* nvif_vmm_vX ... */ + __u8 version; + __u8 bigpage; +}; + +struct gm200_vmm_map_vn { + /* nvif_vmm_map_vX ... */ +}; + +struct gm200_vmm_map_v0 { + /* nvif_vmm_map_vX ... */ + __u8 version; + __u8 vol; + __u8 ro; + __u8 priv; + __u8 kind; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/ifc00d.h b/drivers/gpu/drm/nouveau/include/nvif/ifc00d.h new file mode 100644 index 000000000000..1d9c637859f3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/ifc00d.h @@ -0,0 +1,21 @@ +#ifndef __NVIF_IFC00D_H__ +#define __NVIF_IFC00D_H__ +#include "if000c.h" + +struct gp100_vmm_vn { + /* nvif_vmm_vX ... */ +}; + +struct gp100_vmm_map_vn { + /* nvif_vmm_map_vX ... */ +}; + +struct gp100_vmm_map_v0 { + /* nvif_vmm_map_vX ... */ + __u8 version; + __u8 vol; + __u8 ro; + __u8 priv; + __u8 kind; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h index c5f5eb83a594..1886366457f1 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/ioctl.h +++ b/drivers/gpu/drm/nouveau/include/nvif/ioctl.h @@ -1,7 +1,7 @@ #ifndef __NVIF_IOCTL_H__ #define __NVIF_IOCTL_H__ -#define NVIF_VERSION_LATEST 0x0000000000000000ULL +#define NVIF_VERSION_LATEST 0x0000000000000100ULL struct nvif_ioctl_v0 { __u8 version; @@ -83,9 +83,13 @@ struct nvif_ioctl_wr_v0 { struct nvif_ioctl_map_v0 { /* nvif_ioctl ... */ __u8 version; - __u8 pad01[3]; - __u32 length; +#define NVIF_IOCTL_MAP_V0_IO 0x00 +#define NVIF_IOCTL_MAP_V0_VA 0x01 + __u8 type; + __u8 pad02[6]; __u64 handle; + __u64 length; + __u8 data[]; }; struct nvif_ioctl_unmap { diff --git a/drivers/gpu/drm/nouveau/include/nvif/mem.h b/drivers/gpu/drm/nouveau/include/nvif/mem.h new file mode 100644 index 000000000000..b542fe38398e --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/mem.h @@ -0,0 +1,18 @@ +#ifndef __NVIF_MEM_H__ +#define __NVIF_MEM_H__ +#include "mmu.h" + +struct nvif_mem { + struct nvif_object object; + u8 type; + u8 page; + u64 addr; + u64 size; +}; + +int nvif_mem_init_type(struct nvif_mmu *mmu, s32 oclass, int type, u8 page, + u64 size, void *argv, u32 argc, struct nvif_mem *); +int nvif_mem_init(struct nvif_mmu *mmu, s32 oclass, u8 type, u8 page, + u64 size, void *argv, u32 argc, struct nvif_mem *); +void nvif_mem_fini(struct nvif_mem *); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/mmu.h b/drivers/gpu/drm/nouveau/include/nvif/mmu.h new file mode 100644 index 000000000000..c8cd5b5b0688 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/mmu.h @@ -0,0 +1,56 @@ +#ifndef __NVIF_MMU_H__ +#define __NVIF_MMU_H__ +#include <nvif/object.h> + +struct nvif_mmu { + struct nvif_object object; + u8 dmabits; + u8 heap_nr; + u8 type_nr; + u16 kind_nr; + + struct { + u64 size; + } *heap; + + struct { +#define NVIF_MEM_VRAM 0x01 +#define NVIF_MEM_HOST 0x02 +#define NVIF_MEM_COMP 0x04 +#define NVIF_MEM_DISP 0x08 +#define NVIF_MEM_KIND 0x10 +#define NVIF_MEM_MAPPABLE 0x20 +#define NVIF_MEM_COHERENT 0x40 +#define NVIF_MEM_UNCACHED 0x80 + u8 type; + u8 heap; + } *type; + + u8 *kind; +}; + +int nvif_mmu_init(struct nvif_object *, s32 oclass, struct nvif_mmu *); +void nvif_mmu_fini(struct nvif_mmu *); + +static inline bool +nvif_mmu_kind_valid(struct nvif_mmu *mmu, u8 kind) +{ + const u8 invalid = mmu->kind_nr - 1; + if (kind) { + if (kind >= mmu->kind_nr || mmu->kind[kind] == invalid) + return false; + } + return true; +} + +static inline int +nvif_mmu_type(struct nvif_mmu *mmu, u8 mask) +{ + int i; + for (i = 0; i < mmu->type_nr; i++) { + if ((mmu->type[i].type & mask) == mask) + return i; + } + return -EINVAL; +} +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/object.h b/drivers/gpu/drm/nouveau/include/nvif/object.h index 9e58b305b020..0b54261bdefe 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/object.h +++ b/drivers/gpu/drm/nouveau/include/nvif/object.h @@ -16,7 +16,7 @@ struct nvif_object { void *priv; /*XXX: hack */ struct { void __iomem *ptr; - u32 size; + u64 size; } map; }; @@ -29,7 +29,10 @@ void nvif_object_sclass_put(struct nvif_sclass **); u32 nvif_object_rd(struct nvif_object *, int, u64); void nvif_object_wr(struct nvif_object *, int, u64, u32); int nvif_object_mthd(struct nvif_object *, u32, void *, u32); -int nvif_object_map(struct nvif_object *); +int nvif_object_map_handle(struct nvif_object *, void *, u32, + u64 *handle, u64 *length); +void nvif_object_unmap_handle(struct nvif_object *); +int nvif_object_map(struct nvif_object *, void *, u32); void nvif_object_unmap(struct nvif_object *); #define nvif_handle(a) (unsigned long)(void *)(a) diff --git a/drivers/gpu/drm/nouveau/include/nvif/os.h b/drivers/gpu/drm/nouveau/include/nvif/os.h index 9fcab67c8557..5efdf80d5abc 100644 --- a/drivers/gpu/drm/nouveau/include/nvif/os.h +++ b/drivers/gpu/drm/nouveau/include/nvif/os.h @@ -33,18 +33,4 @@ #include <soc/tegra/fuse.h> #include <soc/tegra/pmc.h> - -#ifndef ioread32_native -#ifdef __BIG_ENDIAN -#define ioread16_native ioread16be -#define iowrite16_native iowrite16be -#define ioread32_native ioread32be -#define iowrite32_native iowrite32be -#else /* def __BIG_ENDIAN */ -#define ioread16_native ioread16 -#define iowrite16_native iowrite16 -#define ioread32_native ioread32 -#define iowrite32_native iowrite32 -#endif /* def __BIG_ENDIAN else */ -#endif /* !ioread32_native */ #endif diff --git a/drivers/gpu/drm/nouveau/include/nvif/vmm.h b/drivers/gpu/drm/nouveau/include/nvif/vmm.h new file mode 100644 index 000000000000..c5db8a2e82df --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvif/vmm.h @@ -0,0 +1,42 @@ +#ifndef __NVIF_VMM_H__ +#define __NVIF_VMM_H__ +#include <nvif/object.h> +struct nvif_mem; +struct nvif_mmu; + +enum nvif_vmm_get { + ADDR, + PTES, + LAZY +}; + +struct nvif_vma { + u64 addr; + u64 size; +}; + +struct nvif_vmm { + struct nvif_object object; + u64 start; + u64 limit; + + struct { + u8 shift; + bool sparse:1; + bool vram:1; + bool host:1; + bool comp:1; + } *page; + int page_nr; +}; + +int nvif_vmm_init(struct nvif_mmu *, s32 oclass, u64 addr, u64 size, + void *argv, u32 argc, struct nvif_vmm *); +void nvif_vmm_fini(struct nvif_vmm *); +int nvif_vmm_get(struct nvif_vmm *, enum nvif_vmm_get, bool sparse, + u8 page, u8 align, u64 size, struct nvif_vma *); +void nvif_vmm_put(struct nvif_vmm *, struct nvif_vma *); +int nvif_vmm_map(struct nvif_vmm *, u64 addr, u64 size, void *argv, u32 argc, + struct nvif_mem *, u64 offset); +int nvif_vmm_unmap(struct nvif_vmm *, u64); +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h index e876634da10a..79624f6d0a2b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/client.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/client.h @@ -16,7 +16,8 @@ struct nvkm_client { void *data; int (*ntfy)(const void *, u32, const void *, u32); - struct nvkm_vm *vm; + struct list_head umem; + spinlock_t lock; }; int nvkm_client_new(const char *name, u64 device, const char *cfg, diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h index bb4c214f1046..5046e1db99ac 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/device.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/device.h @@ -1,7 +1,7 @@ #ifndef __NVKM_DEVICE_H__ #define __NVKM_DEVICE_H__ +#include <core/oclass.h> #include <core/event.h> -#include <core/object.h> enum nvkm_devidx { NVKM_SUBDEV_PCI, diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h index d4cd2fbfde88..7730499bfd95 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/engine.h @@ -15,6 +15,7 @@ struct nvkm_engine { struct nvkm_engine_func { void *(*dtor)(struct nvkm_engine *); + void (*preinit)(struct nvkm_engine *); int (*oneinit)(struct nvkm_engine *); int (*init)(struct nvkm_engine *); int (*fini)(struct nvkm_engine *, bool suspend); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h b/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h index c23da4f05929..51691667b813 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/gpuobj.h @@ -1,17 +1,16 @@ #ifndef __NVKM_GPUOBJ_H__ #define __NVKM_GPUOBJ_H__ -#include <core/object.h> #include <core/memory.h> #include <core/mm.h> -struct nvkm_vma; -struct nvkm_vm; #define NVOBJ_FLAG_ZERO_ALLOC 0x00000001 #define NVOBJ_FLAG_HEAP 0x00000004 struct nvkm_gpuobj { - struct nvkm_object object; - const struct nvkm_gpuobj_func *func; + union { + const struct nvkm_gpuobj_func *func; + const struct nvkm_gpuobj_func *ptrs; + }; struct nvkm_gpuobj *parent; struct nvkm_memory *memory; struct nvkm_mm_node *node; @@ -28,15 +27,14 @@ struct nvkm_gpuobj_func { void (*release)(struct nvkm_gpuobj *); u32 (*rd32)(struct nvkm_gpuobj *, u32 offset); void (*wr32)(struct nvkm_gpuobj *, u32 offset, u32 data); + int (*map)(struct nvkm_gpuobj *, u64 offset, struct nvkm_vmm *, + struct nvkm_vma *, void *argv, u32 argc); }; int nvkm_gpuobj_new(struct nvkm_device *, u32 size, int align, bool zero, struct nvkm_gpuobj *parent, struct nvkm_gpuobj **); void nvkm_gpuobj_del(struct nvkm_gpuobj **); int nvkm_gpuobj_wrap(struct nvkm_memory *, struct nvkm_gpuobj **); -int nvkm_gpuobj_map(struct nvkm_gpuobj *, struct nvkm_vm *, u32 access, - struct nvkm_vma *); -void nvkm_gpuobj_unmap(struct nvkm_vma *); void nvkm_gpuobj_memcpy_to(struct nvkm_gpuobj *dst, u32 dstoffset, void *src, u32 length); void nvkm_gpuobj_memcpy_from(void *dst, struct nvkm_gpuobj *src, u32 srcoffset, diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h index 33ca6769266a..13ebf4da2b96 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/memory.h @@ -3,7 +3,12 @@ #include <core/os.h> struct nvkm_device; struct nvkm_vma; -struct nvkm_vm; +struct nvkm_vmm; + +struct nvkm_tags { + struct nvkm_mm_node *mn; + refcount_t refcount; +}; enum nvkm_memory_target { NVKM_MEM_TARGET_INST, /* instance memory */ @@ -14,41 +19,84 @@ enum nvkm_memory_target { struct nvkm_memory { const struct nvkm_memory_func *func; + const struct nvkm_memory_ptrs *ptrs; + struct kref kref; + struct nvkm_tags *tags; }; struct nvkm_memory_func { void *(*dtor)(struct nvkm_memory *); enum nvkm_memory_target (*target)(struct nvkm_memory *); + u8 (*page)(struct nvkm_memory *); u64 (*addr)(struct nvkm_memory *); u64 (*size)(struct nvkm_memory *); - void (*boot)(struct nvkm_memory *, struct nvkm_vm *); + void (*boot)(struct nvkm_memory *, struct nvkm_vmm *); void __iomem *(*acquire)(struct nvkm_memory *); void (*release)(struct nvkm_memory *); + int (*map)(struct nvkm_memory *, u64 offset, struct nvkm_vmm *, + struct nvkm_vma *, void *argv, u32 argc); +}; + +struct nvkm_memory_ptrs { u32 (*rd32)(struct nvkm_memory *, u64 offset); void (*wr32)(struct nvkm_memory *, u64 offset, u32 data); - void (*map)(struct nvkm_memory *, struct nvkm_vma *, u64 offset); }; void nvkm_memory_ctor(const struct nvkm_memory_func *, struct nvkm_memory *); int nvkm_memory_new(struct nvkm_device *, enum nvkm_memory_target, u64 size, u32 align, bool zero, struct nvkm_memory **); -void nvkm_memory_del(struct nvkm_memory **); +struct nvkm_memory *nvkm_memory_ref(struct nvkm_memory *); +void nvkm_memory_unref(struct nvkm_memory **); +int nvkm_memory_tags_get(struct nvkm_memory *, struct nvkm_device *, u32 tags, + void (*clear)(struct nvkm_device *, u32, u32), + struct nvkm_tags **); +void nvkm_memory_tags_put(struct nvkm_memory *, struct nvkm_device *, + struct nvkm_tags **); + #define nvkm_memory_target(p) (p)->func->target(p) +#define nvkm_memory_page(p) (p)->func->page(p) #define nvkm_memory_addr(p) (p)->func->addr(p) #define nvkm_memory_size(p) (p)->func->size(p) #define nvkm_memory_boot(p,v) (p)->func->boot((p),(v)) -#define nvkm_memory_map(p,v,o) (p)->func->map((p),(v),(o)) +#define nvkm_memory_map(p,o,vm,va,av,ac) \ + (p)->func->map((p),(o),(vm),(va),(av),(ac)) /* accessor macros - kmap()/done() must bracket use of the other accessor * macros to guarantee correct behaviour across all chipsets */ #define nvkm_kmap(o) (o)->func->acquire(o) -#define nvkm_ro32(o,a) (o)->func->rd32((o), (a)) -#define nvkm_wo32(o,a,d) (o)->func->wr32((o), (a), (d)) +#define nvkm_done(o) (o)->func->release(o) + +#define nvkm_ro32(o,a) (o)->ptrs->rd32((o), (a)) +#define nvkm_wo32(o,a,d) (o)->ptrs->wr32((o), (a), (d)) #define nvkm_mo32(o,a,m,d) ({ \ u32 _addr = (a), _data = nvkm_ro32((o), _addr); \ nvkm_wo32((o), _addr, (_data & ~(m)) | (d)); \ _data; \ }) -#define nvkm_done(o) (o)->func->release(o) + +#define nvkm_wo64(o,a,d) do { \ + u64 __a = (a), __d = (d); \ + nvkm_wo32((o), __a + 0, lower_32_bits(__d)); \ + nvkm_wo32((o), __a + 4, upper_32_bits(__d)); \ +} while(0) + +#define nvkm_fill(t,s,o,a,d,c) do { \ + u64 _a = (a), _c = (c), _d = (d), _o = _a >> s, _s = _c << s; \ + u##t __iomem *_m = nvkm_kmap(o); \ + if (likely(_m)) { \ + if (_d) { \ + while (_c--) \ + iowrite##t##_native(_d, &_m[_o++]); \ + } else { \ + memset_io(&_m[_o], _d, _s); \ + } \ + } else { \ + for (; _c; _c--, _a += BIT(s)) \ + nvkm_wo##t((o), _a, _d); \ + } \ + nvkm_done(o); \ +} while(0) +#define nvkm_fo32(o,a,d,c) nvkm_fill(32, 2, (o), (a), (d), (c)) +#define nvkm_fo64(o,a,d,c) nvkm_fill(64, 3, (o), (a), (d), (c)) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h b/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h index 7bd4897a8a2a..5c1261351138 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/mm.h @@ -30,7 +30,7 @@ nvkm_mm_initialised(struct nvkm_mm *mm) return mm->heap_nodes; } -int nvkm_mm_init(struct nvkm_mm *, u32 offset, u32 length, u32 block); +int nvkm_mm_init(struct nvkm_mm *, u8 heap, u32 offset, u32 length, u32 block); int nvkm_mm_fini(struct nvkm_mm *); int nvkm_mm_head(struct nvkm_mm *, u8 heap, u8 type, u32 size_max, u32 size_min, u32 align, struct nvkm_mm_node **); @@ -39,9 +39,39 @@ int nvkm_mm_tail(struct nvkm_mm *, u8 heap, u8 type, u32 size_max, void nvkm_mm_free(struct nvkm_mm *, struct nvkm_mm_node **); void nvkm_mm_dump(struct nvkm_mm *, const char *); +static inline u32 +nvkm_mm_heap_size(struct nvkm_mm *mm, u8 heap) +{ + struct nvkm_mm_node *node; + u32 size = 0; + list_for_each_entry(node, &mm->nodes, nl_entry) { + if (node->heap == heap) + size += node->length; + } + return size; +} + static inline bool nvkm_mm_contiguous(struct nvkm_mm_node *node) { return !node->next; } + +static inline u32 +nvkm_mm_addr(struct nvkm_mm_node *node) +{ + if (WARN_ON(!nvkm_mm_contiguous(node))) + return 0; + return node->offset; +} + +static inline u32 +nvkm_mm_size(struct nvkm_mm_node *node) +{ + u32 size = 0; + do { + size += node->length; + } while ((node = node->next)); + return size; +} #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h index 96dda350ada3..916a4b76d430 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/object.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/object.h @@ -1,10 +1,8 @@ #ifndef __NVKM_OBJECT_H__ #define __NVKM_OBJECT_H__ -#include <core/os.h> -#include <core/debug.h> +#include <core/oclass.h> struct nvkm_event; struct nvkm_gpuobj; -struct nvkm_oclass; struct nvkm_object { const struct nvkm_object_func *func; @@ -21,13 +19,20 @@ struct nvkm_object { struct rb_node node; }; +enum nvkm_object_map { + NVKM_OBJECT_MAP_IO, + NVKM_OBJECT_MAP_VA +}; + struct nvkm_object_func { void *(*dtor)(struct nvkm_object *); int (*init)(struct nvkm_object *); int (*fini)(struct nvkm_object *, bool suspend); int (*mthd)(struct nvkm_object *, u32 mthd, void *data, u32 size); int (*ntfy)(struct nvkm_object *, u32 mthd, struct nvkm_event **); - int (*map)(struct nvkm_object *, u64 *addr, u32 *size); + int (*map)(struct nvkm_object *, void *argv, u32 argc, + enum nvkm_object_map *, u64 *addr, u64 *size); + int (*unmap)(struct nvkm_object *); int (*rd08)(struct nvkm_object *, u64 addr, u8 *data); int (*rd16)(struct nvkm_object *, u64 addr, u16 *data); int (*rd32)(struct nvkm_object *, u64 addr, u32 *data); @@ -52,7 +57,9 @@ int nvkm_object_init(struct nvkm_object *); int nvkm_object_fini(struct nvkm_object *, bool suspend); int nvkm_object_mthd(struct nvkm_object *, u32 mthd, void *data, u32 size); int nvkm_object_ntfy(struct nvkm_object *, u32 mthd, struct nvkm_event **); -int nvkm_object_map(struct nvkm_object *, u64 *addr, u32 *size); +int nvkm_object_map(struct nvkm_object *, void *argv, u32 argc, + enum nvkm_object_map *, u64 *addr, u64 *size); +int nvkm_object_unmap(struct nvkm_object *); int nvkm_object_rd08(struct nvkm_object *, u64 addr, u8 *data); int nvkm_object_rd16(struct nvkm_object *, u64 addr, u16 *data); int nvkm_object_rd32(struct nvkm_object *, u64 addr, u32 *data); @@ -66,28 +73,4 @@ bool nvkm_object_insert(struct nvkm_object *); void nvkm_object_remove(struct nvkm_object *); struct nvkm_object *nvkm_object_search(struct nvkm_client *, u64 object, const struct nvkm_object_func *); - -struct nvkm_sclass { - int minver; - int maxver; - s32 oclass; - const struct nvkm_object_func *func; - int (*ctor)(const struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); -}; - -struct nvkm_oclass { - int (*ctor)(const struct nvkm_oclass *, void *data, u32 size, - struct nvkm_object **); - struct nvkm_sclass base; - const void *priv; - const void *engn; - u32 handle; - u8 route; - u64 token; - u64 object; - struct nvkm_client *client; - struct nvkm_object *parent; - struct nvkm_engine *engine; -}; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h b/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h new file mode 100644 index 000000000000..8e1b945d38f3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/oclass.h @@ -0,0 +1,31 @@ +#ifndef __NVKM_OCLASS_H__ +#define __NVKM_OCLASS_H__ +#include <core/os.h> +#include <core/debug.h> +struct nvkm_oclass; +struct nvkm_object; + +struct nvkm_sclass { + int minver; + int maxver; + s32 oclass; + const struct nvkm_object_func *func; + int (*ctor)(const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); +}; + +struct nvkm_oclass { + int (*ctor)(const struct nvkm_oclass *, void *data, u32 size, + struct nvkm_object **); + struct nvkm_sclass base; + const void *priv; + const void *engn; + u32 handle; + u8 route; + u64 token; + u64 object; + struct nvkm_client *client; + struct nvkm_object *parent; + struct nvkm_engine *engine; +}; +#endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h index cd57e238ddd3..1f0108fdd24a 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/os.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/os.h @@ -1,4 +1,23 @@ #ifndef __NVKM_OS_H__ #define __NVKM_OS_H__ #include <nvif/os.h> + +#ifdef __BIG_ENDIAN +#define ioread16_native ioread16be +#define iowrite16_native iowrite16be +#define ioread32_native ioread32be +#define iowrite32_native iowrite32be +#else +#define ioread16_native ioread16 +#define iowrite16_native iowrite16 +#define ioread32_native ioread32 +#define iowrite32_native iowrite32 +#endif + +#define iowrite64_native(v,p) do { \ + u32 __iomem *_p = (u32 __iomem *)(p); \ + u64 _v = (v); \ + iowrite32_native(lower_32_bits(_v), &_p[0]); \ + iowrite32_native(upper_32_bits(_v), &_p[1]); \ +} while(0) #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h b/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h index 5ee6298991e2..8a48ca67f60d 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/ramht.h @@ -1,6 +1,7 @@ #ifndef __NVKM_RAMHT_H__ #define __NVKM_RAMHT_H__ #include <core/gpuobj.h> +struct nvkm_object; struct nvkm_ramht_data { struct nvkm_gpuobj *inst; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h index ca9ed3d68f44..a6c21be7537f 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/core/subdev.h @@ -33,7 +33,7 @@ void nvkm_subdev_intr(struct nvkm_subdev *); /* subdev logging */ #define nvkm_printk_(s,l,p,f,a...) do { \ const struct nvkm_subdev *_subdev = (s); \ - if (_subdev->debug >= (l)) { \ + if (CONFIG_NOUVEAU_DEBUG >= (l) && _subdev->debug >= (l)) { \ dev_##p(_subdev->device->dev, "%s: "f, \ nvkm_subdev_name[_subdev->index], ##a); \ } \ diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h index d2a6532ce3b9..b672a3b07f55 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/dma.h @@ -1,6 +1,7 @@ #ifndef __NVKM_DMA_H__ #define __NVKM_DMA_H__ #include <core/engine.h> +#include <core/object.h> struct nvkm_client; struct nvkm_dmaobj { diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h index e1a854e2ade1..f0024fb5a5af 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/falcon.h @@ -3,6 +3,7 @@ #define nvkm_falcon(p) container_of((p), struct nvkm_falcon, engine) #include <core/engine.h> struct nvkm_fifo_chan; +struct nvkm_gpuobj; enum nvkm_falcon_dmaidx { FALCON_DMAIDX_UCODE = 0, @@ -77,7 +78,7 @@ struct nvkm_falcon_func { void (*load_imem)(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); void (*load_dmem)(struct nvkm_falcon *, void *, u32, u32, u8); void (*read_dmem)(struct nvkm_falcon *, u32, u32, u8, void *); - void (*bind_context)(struct nvkm_falcon *, struct nvkm_gpuobj *); + void (*bind_context)(struct nvkm_falcon *, struct nvkm_memory *); int (*wait_for_halt)(struct nvkm_falcon *, u32); int (*clear_interrupt)(struct nvkm_falcon *, u32); void (*set_start_addr)(struct nvkm_falcon *, u32 start_addr); @@ -112,7 +113,7 @@ void nvkm_falcon_load_imem(struct nvkm_falcon *, void *, u32, u32, u16, u8, bool); void nvkm_falcon_load_dmem(struct nvkm_falcon *, void *, u32, u32, u8); void nvkm_falcon_read_dmem(struct nvkm_falcon *, u32, u32, u8, void *); -void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_gpuobj *); +void nvkm_falcon_bind_context(struct nvkm_falcon *, struct nvkm_memory *); void nvkm_falcon_set_start_addr(struct nvkm_falcon *, u32); void nvkm_falcon_start(struct nvkm_falcon *); int nvkm_falcon_wait_for_halt(struct nvkm_falcon *, u32); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h index f00527b36acc..e42d686fbd8b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/engine/fifo.h @@ -1,6 +1,7 @@ #ifndef __NVKM_FIFO_H__ #define __NVKM_FIFO_H__ #include <core/engine.h> +#include <core/object.h> #include <core/event.h> #define NVKM_FIFO_CHID_NR 4096 @@ -21,7 +22,7 @@ struct nvkm_fifo_chan { u16 chid; struct nvkm_gpuobj *inst; struct nvkm_gpuobj *push; - struct nvkm_vm *vm; + struct nvkm_vmm *vmm; void __iomem *user; u64 addr; u32 size; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h index d3071b5a4f98..ffa963939e15 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/bar.h @@ -8,17 +8,22 @@ struct nvkm_bar { struct nvkm_subdev subdev; spinlock_t lock; + bool bar2; /* whether the BAR supports to be ioremapped WC or should be uncached */ bool iomap_uncached; }; +struct nvkm_vmm *nvkm_bar_bar1_vmm(struct nvkm_device *); +void nvkm_bar_bar2_init(struct nvkm_device *); +void nvkm_bar_bar2_fini(struct nvkm_device *); +struct nvkm_vmm *nvkm_bar_bar2_vmm(struct nvkm_device *); void nvkm_bar_flush(struct nvkm_bar *); -struct nvkm_vm *nvkm_bar_kmap(struct nvkm_bar *); -int nvkm_bar_umap(struct nvkm_bar *, u64 size, int type, struct nvkm_vma *); int nv50_bar_new(struct nvkm_device *, int, struct nvkm_bar **); int g84_bar_new(struct nvkm_device *, int, struct nvkm_bar **); int gf100_bar_new(struct nvkm_device *, int, struct nvkm_bar **); int gk20a_bar_new(struct nvkm_device *, int, struct nvkm_bar **); +int gm107_bar_new(struct nvkm_device *, int, struct nvkm_bar **); +int gm20b_bar_new(struct nvkm_device *, int, struct nvkm_bar **); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h index 28d513fbf44c..a00fd2e59215 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h @@ -1,8 +1,7 @@ #ifndef __NVKM_FB_H__ #define __NVKM_FB_H__ #include <core/subdev.h> - -#include <subdev/mmu.h> +#include <core/mm.h> /* memory type/access flags, do not match hardware values */ #define NV_MEM_ACCESS_RO 1 @@ -21,22 +20,6 @@ #define NVKM_RAM_TYPE_VM 0x7f #define NV_MEM_COMP_VM 0x03 -struct nvkm_mem { - struct drm_device *dev; - - struct nvkm_vma bar_vma; - struct nvkm_vma vma[2]; - u8 page_shift; - - struct nvkm_mm_node *tag; - struct nvkm_mm_node *mem; - dma_addr_t *pages; - u32 memtype; - u64 offset; - u64 size; - struct sg_table *sg; -}; - struct nvkm_fb_tile { struct nvkm_mm_node *tag; u32 addr; @@ -50,6 +33,7 @@ struct nvkm_fb { struct nvkm_subdev subdev; struct nvkm_ram *ram; + struct nvkm_mm tags; struct { struct nvkm_fb_tile region[16]; @@ -62,7 +46,6 @@ struct nvkm_fb { struct nvkm_memory *mmu_wr; }; -bool nvkm_fb_memtype_valid(struct nvkm_fb *, u32 memtype); void nvkm_fb_tile_init(struct nvkm_fb *, int region, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *); void nvkm_fb_tile_fini(struct nvkm_fb *, int region, struct nvkm_fb_tile *); @@ -129,8 +112,11 @@ struct nvkm_ram { u64 size; #define NVKM_RAM_MM_SHIFT 12 +#define NVKM_RAM_MM_ANY (NVKM_MM_HEAP_ANY + 0) +#define NVKM_RAM_MM_NORMAL (NVKM_MM_HEAP_ANY + 1) +#define NVKM_RAM_MM_NOMAP (NVKM_MM_HEAP_ANY + 2) +#define NVKM_RAM_MM_MIXED (NVKM_MM_HEAP_ANY + 3) struct nvkm_mm vram; - struct nvkm_mm tags; u64 stolen; int ranks; @@ -147,6 +133,10 @@ struct nvkm_ram { struct nvkm_ram_data target; }; +int +nvkm_ram_get(struct nvkm_device *, u8 heap, u8 type, u8 page, u64 size, + bool contig, bool back, struct nvkm_memory **); + struct nvkm_ram_func { u64 upper; u32 (*probe_fbp)(const struct nvkm_ram_func *, struct nvkm_device *, @@ -157,14 +147,8 @@ struct nvkm_ram_func { void *(*dtor)(struct nvkm_ram *); int (*init)(struct nvkm_ram *); - int (*get)(struct nvkm_ram *, u64 size, u32 align, u32 size_nc, - u32 type, struct nvkm_mem **); - void (*put)(struct nvkm_ram *, struct nvkm_mem **); - int (*calc)(struct nvkm_ram *, u32 freq); int (*prog)(struct nvkm_ram *); void (*tidy)(struct nvkm_ram *); }; - -extern const u8 gf100_pte_storage_type_map[256]; #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h index 40f845e31272..8111c0c3c5ec 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/instmem.h @@ -9,6 +9,7 @@ struct nvkm_instmem { spinlock_t lock; struct list_head list; + struct list_head boot; u32 reserved; struct nvkm_memory *vbios; diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h index cd755baf9cab..4a224fd22e48 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/ltc.h @@ -14,8 +14,7 @@ struct nvkm_ltc { u32 num_tags; u32 tag_base; - struct nvkm_mm tags; - struct nvkm_mm_node *tag_ram; + struct nvkm_memory *tag_ram; int zbc_min; int zbc_max; @@ -23,9 +22,7 @@ struct nvkm_ltc { u32 zbc_depth[NVKM_LTC_MAX_ZBC_CNT]; }; -int nvkm_ltc_tags_alloc(struct nvkm_ltc *, u32 count, struct nvkm_mm_node **); -void nvkm_ltc_tags_free(struct nvkm_ltc *, struct nvkm_mm_node **); -void nvkm_ltc_tags_clear(struct nvkm_ltc *, u32 first, u32 count); +void nvkm_ltc_tags_clear(struct nvkm_device *, u32 first, u32 count); int nvkm_ltc_zbc_color_get(struct nvkm_ltc *, int index, const u32[4]); int nvkm_ltc_zbc_depth_get(struct nvkm_ltc *, int index, const u32); diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h index dcd3deff27a4..975c42f620a0 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/mmu.h @@ -1,68 +1,130 @@ #ifndef __NVKM_MMU_H__ #define __NVKM_MMU_H__ #include <core/subdev.h> -#include <core/mm.h> -struct nvkm_device; -struct nvkm_mem; - -struct nvkm_vm_pgt { - struct nvkm_memory *mem[2]; - u32 refcount[2]; -}; - -struct nvkm_vm_pgd { - struct list_head head; - struct nvkm_gpuobj *obj; -}; struct nvkm_vma { struct list_head head; - int refcount; - struct nvkm_vm *vm; - struct nvkm_mm_node *node; - u64 offset; - u32 access; + struct rb_node tree; + u64 addr; + u64 size:50; + bool mapref:1; /* PTs (de)referenced on (un)map (vs pre-allocated). */ + bool sparse:1; /* Unmapped PDEs/PTEs will not trigger MMU faults. */ +#define NVKM_VMA_PAGE_NONE 7 + u8 page:3; /* Requested page type (index, or NONE for automatic). */ + u8 refd:3; /* Current page type (index, or NONE for unreferenced). */ + bool used:1; /* Region allocated. */ + bool part:1; /* Region was split from an allocated region by map(). */ + bool user:1; /* Region user-allocated. */ + bool busy:1; /* Region busy (for temporarily preventing user access). */ + struct nvkm_memory *memory; /* Memory currently mapped into VMA. */ + struct nvkm_tags *tags; /* Compression tag reference. */ }; -struct nvkm_vm { +struct nvkm_vmm { + const struct nvkm_vmm_func *func; struct nvkm_mmu *mmu; - + const char *name; + u32 debug; + struct kref kref; struct mutex mutex; - struct nvkm_mm mm; - struct kref refcount; - struct list_head pgd_list; + u64 start; + u64 limit; + + struct nvkm_vmm_pt *pd; + struct list_head join; + + struct list_head list; + struct rb_root free; + struct rb_root root; + + bool bootstrapped; atomic_t engref[NVKM_SUBDEV_NR]; - struct nvkm_vm_pgt *pgt; - u32 fpde; - u32 lpde; + dma_addr_t null; + void *nullp; }; -int nvkm_vm_new(struct nvkm_device *, u64 offset, u64 length, u64 mm_offset, - struct lock_class_key *, struct nvkm_vm **); -int nvkm_vm_ref(struct nvkm_vm *, struct nvkm_vm **, struct nvkm_gpuobj *pgd); -int nvkm_vm_boot(struct nvkm_vm *, u64 size); -int nvkm_vm_get(struct nvkm_vm *, u64 size, u32 page_shift, u32 access, - struct nvkm_vma *); -void nvkm_vm_put(struct nvkm_vma *); -void nvkm_vm_map(struct nvkm_vma *, struct nvkm_mem *); -void nvkm_vm_map_at(struct nvkm_vma *, u64 offset, struct nvkm_mem *); -void nvkm_vm_unmap(struct nvkm_vma *); -void nvkm_vm_unmap_at(struct nvkm_vma *, u64 offset, u64 length); +int nvkm_vmm_new(struct nvkm_device *, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *, const char *name, struct nvkm_vmm **); +struct nvkm_vmm *nvkm_vmm_ref(struct nvkm_vmm *); +void nvkm_vmm_unref(struct nvkm_vmm **); +int nvkm_vmm_boot(struct nvkm_vmm *); +int nvkm_vmm_join(struct nvkm_vmm *, struct nvkm_memory *inst); +void nvkm_vmm_part(struct nvkm_vmm *, struct nvkm_memory *inst); +int nvkm_vmm_get(struct nvkm_vmm *, u8 page, u64 size, struct nvkm_vma **); +void nvkm_vmm_put(struct nvkm_vmm *, struct nvkm_vma **); + +struct nvkm_vmm_map { + struct nvkm_memory *memory; + u64 offset; + + struct nvkm_mm_node *mem; + struct scatterlist *sgl; + dma_addr_t *dma; + u64 off; + + const struct nvkm_vmm_page *page; + + struct nvkm_tags *tags; + u64 next; + u64 type; + u64 ctag; +}; + +int nvkm_vmm_map(struct nvkm_vmm *, struct nvkm_vma *, void *argv, u32 argc, + struct nvkm_vmm_map *); +void nvkm_vmm_unmap(struct nvkm_vmm *, struct nvkm_vma *); + +struct nvkm_memory *nvkm_umem_search(struct nvkm_client *, u64); +struct nvkm_vmm *nvkm_uvmm_search(struct nvkm_client *, u64 handle); struct nvkm_mmu { const struct nvkm_mmu_func *func; struct nvkm_subdev subdev; - u64 limit; u8 dma_bits; - u8 lpg_shift; + + int heap_nr; + struct { +#define NVKM_MEM_VRAM 0x01 +#define NVKM_MEM_HOST 0x02 +#define NVKM_MEM_COMP 0x04 +#define NVKM_MEM_DISP 0x08 + u8 type; + u64 size; + } heap[4]; + + int type_nr; + struct { +#define NVKM_MEM_KIND 0x10 +#define NVKM_MEM_MAPPABLE 0x20 +#define NVKM_MEM_COHERENT 0x40 +#define NVKM_MEM_UNCACHED 0x80 + u8 type; + u8 heap; + } type[16]; + + struct nvkm_vmm *vmm; + + struct { + struct mutex mutex; + struct list_head list; + } ptc, ptp; + + struct nvkm_device_oclass user; }; int nv04_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); int nv41_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); int nv44_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); int nv50_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int g84_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); int gf100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int gk104_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int gk20a_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int gm200_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int gm20b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int gp100_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); +int gp10b_mmu_new(struct nvkm_device *, int, struct nvkm_mmu **); #endif diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h index 1bfd93b85575..9841f076da2e 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h @@ -97,4 +97,5 @@ int gt215_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int gm200_therm_new(struct nvkm_device *, int, struct nvkm_therm **); +int gp100_therm_new(struct nvkm_device *, int, struct nvkm_therm **); #endif diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index f98f800cc011..ece650a0c5f9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -34,6 +34,7 @@ #include "nouveau_gem.h" #include "nouveau_chan.h" #include "nouveau_abi16.h" +#include "nouveau_vmm.h" static struct nouveau_abi16 * nouveau_abi16(struct drm_file *file_priv) @@ -134,7 +135,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, } if (chan->ntfy) { - nouveau_bo_vma_del(chan->ntfy, &chan->ntfy_vma); + nouveau_vma_del(&chan->ntfy_vma); nouveau_bo_unpin(chan->ntfy); drm_gem_object_unreference_unlocked(&chan->ntfy->gem); } @@ -184,29 +185,33 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) getparam->value = device->info.chipset; break; case NOUVEAU_GETPARAM_PCI_VENDOR: - if (nvxx_device(device)->func->pci) + if (device->info.platform != NV_DEVICE_INFO_V0_SOC) getparam->value = dev->pdev->vendor; else getparam->value = 0; break; case NOUVEAU_GETPARAM_PCI_DEVICE: - if (nvxx_device(device)->func->pci) + if (device->info.platform != NV_DEVICE_INFO_V0_SOC) getparam->value = dev->pdev->device; else getparam->value = 0; break; case NOUVEAU_GETPARAM_BUS_TYPE: - if (!nvxx_device(device)->func->pci) - getparam->value = 3; - else - if (pci_find_capability(dev->pdev, PCI_CAP_ID_AGP)) - getparam->value = 0; - else - if (!pci_is_pcie(dev->pdev)) - getparam->value = 1; - else - getparam->value = 2; - break; + switch (device->info.platform) { + case NV_DEVICE_INFO_V0_AGP : getparam->value = 0; break; + case NV_DEVICE_INFO_V0_PCI : getparam->value = 1; break; + case NV_DEVICE_INFO_V0_PCIE: getparam->value = 2; break; + case NV_DEVICE_INFO_V0_SOC : getparam->value = 3; break; + case NV_DEVICE_INFO_V0_IGP : + if (!pci_is_pcie(dev->pdev)) + getparam->value = 1; + else + getparam->value = 2; + break; + default: + WARN_ON(1); + break; + } case NOUVEAU_GETPARAM_FB_SIZE: getparam->value = drm->gem.vram_available; break; @@ -329,8 +334,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) goto done; if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { - ret = nouveau_bo_vma_add(chan->ntfy, cli->vm, - &chan->ntfy_vma); + ret = nouveau_vma_new(chan->ntfy, &cli->vmm, &chan->ntfy_vma); if (ret) goto done; } @@ -340,7 +344,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) if (ret) goto done; - ret = nvkm_mm_init(&chan->heap, 0, PAGE_SIZE, 1); + ret = nvkm_mm_init(&chan->heap, 0, 0, PAGE_SIZE, 1); done: if (ret) nouveau_abi16_chan_fini(abi16, chan); @@ -548,8 +552,8 @@ nouveau_abi16_ioctl_notifierobj_alloc(ABI16_IOCTL_ARGS) if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { args.target = NV_DMA_V0_TARGET_VM; args.access = NV_DMA_V0_ACCESS_VM; - args.start += chan->ntfy_vma.offset; - args.limit += chan->ntfy_vma.offset; + args.start += chan->ntfy_vma->addr; + args.limit += chan->ntfy_vma->addr; } else if (drm->agp.bridge) { args.target = NV_DMA_V0_TARGET_AGP; diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index 841cc556fad8..327747680324 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -23,7 +23,7 @@ struct nouveau_abi16_chan { struct nouveau_channel *chan; struct list_head notifiers; struct nouveau_bo *ntfy; - struct nvkm_vma ntfy_vma; + struct nouveau_vma *ntfy_vma; struct nvkm_mm heap; }; diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index dd6fba55ad5d..66bf2aff4a3e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c @@ -1478,9 +1478,13 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, case 1: entry->dpconf.link_bw = 270000; break; - default: + case 2: entry->dpconf.link_bw = 540000; break; + case 3: + default: + entry->dpconf.link_bw = 810000; + break; } switch ((conf & 0x0f000000) >> 24) { case 0xf: @@ -1964,7 +1968,7 @@ static int load_nv17_hw_sequencer_ucode(struct drm_device *dev, * The microcode entries are found by the "HWSQ" signature. */ - const uint8_t hwsq_signature[] = { 'H', 'W', 'S', 'Q' }; + static const uint8_t hwsq_signature[] = { 'H', 'W', 'S', 'Q' }; const int sz = sizeof(hwsq_signature); int hwsq_offset; @@ -1980,7 +1984,7 @@ uint8_t *nouveau_bios_embedded_edid(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvbios *bios = &drm->vbios; - const uint8_t edid_sig[] = { + static const uint8_t edid_sig[] = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }; uint16_t offset = 0; uint16_t newoffset; diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e427f80344c4..2615912430cc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -37,6 +37,12 @@ #include "nouveau_bo.h" #include "nouveau_ttm.h" #include "nouveau_gem.h" +#include "nouveau_mem.h" +#include "nouveau_vmm.h" + +#include <nvif/class.h> +#include <nvif/if500b.h> +#include <nvif/if900b.h> /* * NV10-NV40 tiling helpers @@ -48,8 +54,7 @@ nv10_bo_update_tile_region(struct drm_device *dev, struct nouveau_drm_tile *reg, { struct nouveau_drm *drm = nouveau_drm(dev); int i = reg - drm->tile.reg; - struct nvkm_device *device = nvxx_device(&drm->client.device); - struct nvkm_fb *fb = device->fb; + struct nvkm_fb *fb = nvxx_fb(&drm->client.device); struct nvkm_fb_tile *tile = &fb->tile.region[i]; nouveau_fence_unref(®->fence); @@ -97,7 +102,7 @@ nv10_bo_put_tile_region(struct drm_device *dev, struct nouveau_drm_tile *tile, static struct nouveau_drm_tile * nv10_bo_set_tiling(struct drm_device *dev, u32 addr, - u32 size, u32 pitch, u32 flags) + u32 size, u32 pitch, u32 zeta) { struct nouveau_drm *drm = nouveau_drm(dev); struct nvkm_fb *fb = nvxx_fb(&drm->client.device); @@ -120,8 +125,7 @@ nv10_bo_set_tiling(struct drm_device *dev, u32 addr, } if (found) - nv10_bo_update_tile_region(dev, found, addr, size, - pitch, flags); + nv10_bo_update_tile_region(dev, found, addr, size, pitch, zeta); return found; } @@ -155,27 +159,27 @@ nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags, struct nvif_device *device = &drm->client.device; if (device->info.family < NV_DEVICE_INFO_V0_TESLA) { - if (nvbo->tile_mode) { + if (nvbo->mode) { if (device->info.chipset >= 0x40) { *align = 65536; - *size = roundup_64(*size, 64 * nvbo->tile_mode); + *size = roundup_64(*size, 64 * nvbo->mode); } else if (device->info.chipset >= 0x30) { *align = 32768; - *size = roundup_64(*size, 64 * nvbo->tile_mode); + *size = roundup_64(*size, 64 * nvbo->mode); } else if (device->info.chipset >= 0x20) { *align = 16384; - *size = roundup_64(*size, 64 * nvbo->tile_mode); + *size = roundup_64(*size, 64 * nvbo->mode); } else if (device->info.chipset >= 0x10) { *align = 16384; - *size = roundup_64(*size, 32 * nvbo->tile_mode); + *size = roundup_64(*size, 32 * nvbo->mode); } } } else { - *size = roundup_64(*size, (1 << nvbo->page_shift)); - *align = max((1 << nvbo->page_shift), *align); + *size = roundup_64(*size, (1 << nvbo->page)); + *align = max((1 << nvbo->page), *align); } *size = roundup_64(*size, PAGE_SIZE); @@ -187,11 +191,13 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, struct sg_table *sg, struct reservation_object *robj, struct nouveau_bo **pnvbo) { - struct nouveau_drm *drm = nouveau_drm(cli->dev); + struct nouveau_drm *drm = cli->drm; struct nouveau_bo *nvbo; + struct nvif_mmu *mmu = &cli->mmu; + struct nvif_vmm *vmm = &cli->vmm.vmm; size_t acc_size; - int ret; int type = ttm_bo_type_device; + int ret, i, pi = -1; if (!size) { NV_WARN(drm, "skipped size %016llx\n", size); @@ -207,19 +213,80 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, INIT_LIST_HEAD(&nvbo->head); INIT_LIST_HEAD(&nvbo->entry); INIT_LIST_HEAD(&nvbo->vma_list); - nvbo->tile_mode = tile_mode; - nvbo->tile_flags = tile_flags; nvbo->bo.bdev = &drm->ttm.bdev; nvbo->cli = cli; - if (!nvxx_device(&drm->client.device)->func->cpu_coherent) - nvbo->force_coherent = flags & TTM_PL_FLAG_UNCACHED; + /* This is confusing, and doesn't actually mean we want an uncached + * mapping, but is what NOUVEAU_GEM_DOMAIN_COHERENT gets translated + * into in nouveau_gem_new(). + */ + if (flags & TTM_PL_FLAG_UNCACHED) { + /* Determine if we can get a cache-coherent map, forcing + * uncached mapping if we can't. + */ + if (mmu->type[drm->ttm.type_host].type & NVIF_MEM_UNCACHED) + nvbo->force_coherent = true; + } + + if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) { + nvbo->kind = (tile_flags & 0x0000ff00) >> 8; + if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { + kfree(nvbo); + return -EINVAL; + } + + nvbo->comp = mmu->kind[nvbo->kind] != nvbo->kind; + } else + if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) { + nvbo->kind = (tile_flags & 0x00007f00) >> 8; + nvbo->comp = (tile_flags & 0x00030000) >> 16; + if (!nvif_mmu_kind_valid(mmu, nvbo->kind)) { + kfree(nvbo); + return -EINVAL; + } + } else { + nvbo->zeta = (tile_flags & 0x00000007); + } + nvbo->mode = tile_mode; + nvbo->contig = !(tile_flags & NOUVEAU_GEM_TILE_NONCONTIG); + + /* Determine the desirable target GPU page size for the buffer. */ + for (i = 0; i < vmm->page_nr; i++) { + /* Because we cannot currently allow VMM maps to fail + * during buffer migration, we need to determine page + * size for the buffer up-front, and pre-allocate its + * page tables. + * + * Skip page sizes that can't support needed domains. + */ + if (cli->device.info.family > NV_DEVICE_INFO_V0_CURIE && + (flags & TTM_PL_FLAG_VRAM) && !vmm->page[i].vram) + continue; + if ((flags & TTM_PL_FLAG_TT ) && !vmm->page[i].host) + continue; + + /* Select this page size if it's the first that supports + * the potential memory domains, or when it's compatible + * with the requested compression settings. + */ + if (pi < 0 || !nvbo->comp || vmm->page[i].comp) + pi = i; + + /* Stop once the buffer is larger than the current page size. */ + if (size >= 1ULL << vmm->page[i].shift) + break; + } + + if (WARN_ON(pi < 0)) + return -EINVAL; - nvbo->page_shift = 12; - if (drm->client.vm) { - if (!(flags & TTM_PL_FLAG_TT) && size > 256 * 1024) - nvbo->page_shift = drm->client.vm->mmu->lpg_shift; + /* Disable compression if suitable settings couldn't be found. */ + if (nvbo->comp && !vmm->page[pi].comp) { + if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100) + nvbo->kind = mmu->kind[nvbo->kind]; + nvbo->comp = 0; } + nvbo->page = vmm->page[pi].shift; nouveau_bo_fixup_align(nvbo, flags, &align, &size); nvbo->bo.mem.num_pages = size >> PAGE_SHIFT; @@ -262,7 +329,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type) unsigned i, fpfn, lpfn; if (drm->client.device.info.family == NV_DEVICE_INFO_V0_CELSIUS && - nvbo->tile_mode && (type & TTM_PL_FLAG_VRAM) && + nvbo->mode && (type & TTM_PL_FLAG_VRAM) && nvbo->bo.mem.num_pages < vram_pages / 4) { /* * Make sure that the color and depth buffers are handled @@ -270,7 +337,7 @@ set_placement_range(struct nouveau_bo *nvbo, uint32_t type) * speed up when alpha-blending and depth-test are enabled * at the same time. */ - if (nvbo->tile_flags & NOUVEAU_GEM_TILE_ZETA) { + if (nvbo->zeta) { fpfn = vram_pages / 2; lpfn = ~0; } else { @@ -321,14 +388,10 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig) if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA && memtype == TTM_PL_FLAG_VRAM && contig) { - if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) { - if (bo->mem.mem_type == TTM_PL_VRAM) { - struct nvkm_mem *mem = bo->mem.mm_node; - if (!nvkm_mm_contiguous(mem->mem)) - evict = true; - } - nvbo->tile_flags &= ~NOUVEAU_GEM_TILE_NONCONTIG; + if (!nvbo->contig) { + nvbo->contig = true; force = true; + evict = true; } } @@ -376,7 +439,7 @@ nouveau_bo_pin(struct nouveau_bo *nvbo, uint32_t memtype, bool contig) out: if (force && ret) - nvbo->tile_flags |= NOUVEAU_GEM_TILE_NONCONTIG; + nvbo->contig = false; ttm_bo_unreserve(bo); return ret; } @@ -446,7 +509,6 @@ void nouveau_bo_sync_for_device(struct nouveau_bo *nvbo) { struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); - struct nvkm_device *device = nvxx_device(&drm->client.device); struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm; int i; @@ -458,7 +520,8 @@ nouveau_bo_sync_for_device(struct nouveau_bo *nvbo) return; for (i = 0; i < ttm_dma->ttm.num_pages; i++) - dma_sync_single_for_device(device->dev, ttm_dma->dma_address[i], + dma_sync_single_for_device(drm->dev->dev, + ttm_dma->dma_address[i], PAGE_SIZE, DMA_TO_DEVICE); } @@ -466,7 +529,6 @@ void nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo) { struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); - struct nvkm_device *device = nvxx_device(&drm->client.device); struct ttm_dma_tt *ttm_dma = (struct ttm_dma_tt *)nvbo->bo.ttm; int i; @@ -478,7 +540,7 @@ nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo) return; for (i = 0; i < ttm_dma->ttm.num_pages; i++) - dma_sync_single_for_cpu(device->dev, ttm_dma->dma_address[i], + dma_sync_single_for_cpu(drm->dev->dev, ttm_dma->dma_address[i], PAGE_SIZE, DMA_FROM_DEVICE); } @@ -568,6 +630,7 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, struct ttm_mem_type_manager *man) { struct nouveau_drm *drm = nouveau_bdev(bdev); + struct nvif_mmu *mmu = &drm->client.mmu; switch (type) { case TTM_PL_SYSTEM: @@ -584,7 +647,8 @@ nouveau_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type, if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { /* Some BARs do not support being ioremapped WC */ - if (nvxx_bar(&drm->client.device)->iomap_uncached) { + const u8 type = mmu->type[drm->ttm.type_vram].type; + if (type & NVIF_MEM_UNCACHED) { man->available_caching = TTM_PL_FLAG_UNCACHED; man->default_caching = TTM_PL_FLAG_UNCACHED; } @@ -659,14 +723,14 @@ static int nve0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) { - struct nvkm_mem *mem = old_reg->mm_node; + struct nouveau_mem *mem = nouveau_mem(old_reg); int ret = RING_SPACE(chan, 10); if (ret == 0) { BEGIN_NVC0(chan, NvSubCopy, 0x0400, 8); - OUT_RING (chan, upper_32_bits(mem->vma[0].offset)); - OUT_RING (chan, lower_32_bits(mem->vma[0].offset)); - OUT_RING (chan, upper_32_bits(mem->vma[1].offset)); - OUT_RING (chan, lower_32_bits(mem->vma[1].offset)); + OUT_RING (chan, upper_32_bits(mem->vma[0].addr)); + OUT_RING (chan, lower_32_bits(mem->vma[0].addr)); + OUT_RING (chan, upper_32_bits(mem->vma[1].addr)); + OUT_RING (chan, lower_32_bits(mem->vma[1].addr)); OUT_RING (chan, PAGE_SIZE); OUT_RING (chan, PAGE_SIZE); OUT_RING (chan, PAGE_SIZE); @@ -691,9 +755,9 @@ static int nvc0_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) { - struct nvkm_mem *mem = old_reg->mm_node; - u64 src_offset = mem->vma[0].offset; - u64 dst_offset = mem->vma[1].offset; + struct nouveau_mem *mem = nouveau_mem(old_reg); + u64 src_offset = mem->vma[0].addr; + u64 dst_offset = mem->vma[1].addr; u32 page_count = new_reg->num_pages; int ret; @@ -729,9 +793,9 @@ static int nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) { - struct nvkm_mem *mem = old_reg->mm_node; - u64 src_offset = mem->vma[0].offset; - u64 dst_offset = mem->vma[1].offset; + struct nouveau_mem *mem = nouveau_mem(old_reg); + u64 src_offset = mem->vma[0].addr; + u64 dst_offset = mem->vma[1].addr; u32 page_count = new_reg->num_pages; int ret; @@ -768,9 +832,9 @@ static int nva3_bo_move_copy(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) { - struct nvkm_mem *mem = old_reg->mm_node; - u64 src_offset = mem->vma[0].offset; - u64 dst_offset = mem->vma[1].offset; + struct nouveau_mem *mem = nouveau_mem(old_reg); + u64 src_offset = mem->vma[0].addr; + u64 dst_offset = mem->vma[1].addr; u32 page_count = new_reg->num_pages; int ret; @@ -806,14 +870,14 @@ static int nv98_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) { - struct nvkm_mem *mem = old_reg->mm_node; + struct nouveau_mem *mem = nouveau_mem(old_reg); int ret = RING_SPACE(chan, 7); if (ret == 0) { BEGIN_NV04(chan, NvSubCopy, 0x0320, 6); - OUT_RING (chan, upper_32_bits(mem->vma[0].offset)); - OUT_RING (chan, lower_32_bits(mem->vma[0].offset)); - OUT_RING (chan, upper_32_bits(mem->vma[1].offset)); - OUT_RING (chan, lower_32_bits(mem->vma[1].offset)); + OUT_RING (chan, upper_32_bits(mem->vma[0].addr)); + OUT_RING (chan, lower_32_bits(mem->vma[0].addr)); + OUT_RING (chan, upper_32_bits(mem->vma[1].addr)); + OUT_RING (chan, lower_32_bits(mem->vma[1].addr)); OUT_RING (chan, 0x00000000 /* COPY */); OUT_RING (chan, new_reg->num_pages << PAGE_SHIFT); } @@ -824,15 +888,15 @@ static int nv84_bo_move_exec(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) { - struct nvkm_mem *mem = old_reg->mm_node; + struct nouveau_mem *mem = nouveau_mem(old_reg); int ret = RING_SPACE(chan, 7); if (ret == 0) { BEGIN_NV04(chan, NvSubCopy, 0x0304, 6); OUT_RING (chan, new_reg->num_pages << PAGE_SHIFT); - OUT_RING (chan, upper_32_bits(mem->vma[0].offset)); - OUT_RING (chan, lower_32_bits(mem->vma[0].offset)); - OUT_RING (chan, upper_32_bits(mem->vma[1].offset)); - OUT_RING (chan, lower_32_bits(mem->vma[1].offset)); + OUT_RING (chan, upper_32_bits(mem->vma[0].addr)); + OUT_RING (chan, lower_32_bits(mem->vma[0].addr)); + OUT_RING (chan, upper_32_bits(mem->vma[1].addr)); + OUT_RING (chan, lower_32_bits(mem->vma[1].addr)); OUT_RING (chan, 0x00000000 /* MODE_COPY, QUERY_NONE */); } return ret; @@ -858,12 +922,12 @@ static int nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, struct ttm_mem_reg *old_reg, struct ttm_mem_reg *new_reg) { - struct nvkm_mem *mem = old_reg->mm_node; + struct nouveau_mem *mem = nouveau_mem(old_reg); u64 length = (new_reg->num_pages << PAGE_SHIFT); - u64 src_offset = mem->vma[0].offset; - u64 dst_offset = mem->vma[1].offset; - int src_tiled = !!mem->memtype; - int dst_tiled = !!((struct nvkm_mem *)new_reg->mm_node)->memtype; + u64 src_offset = mem->vma[0].addr; + u64 dst_offset = mem->vma[1].addr; + int src_tiled = !!mem->kind; + int dst_tiled = !!nouveau_mem(new_reg)->kind; int ret; while (length) { @@ -1000,25 +1064,31 @@ static int nouveau_bo_move_prep(struct nouveau_drm *drm, struct ttm_buffer_object *bo, struct ttm_mem_reg *reg) { - struct nvkm_mem *old_mem = bo->mem.mm_node; - struct nvkm_mem *new_mem = reg->mm_node; - u64 size = (u64)reg->num_pages << PAGE_SHIFT; + struct nouveau_mem *old_mem = nouveau_mem(&bo->mem); + struct nouveau_mem *new_mem = nouveau_mem(reg); + struct nvif_vmm *vmm = &drm->client.vmm.vmm; int ret; - ret = nvkm_vm_get(drm->client.vm, size, old_mem->page_shift, - NV_MEM_ACCESS_RW, &old_mem->vma[0]); + ret = nvif_vmm_get(vmm, LAZY, false, old_mem->mem.page, 0, + old_mem->mem.size, &old_mem->vma[0]); if (ret) return ret; - ret = nvkm_vm_get(drm->client.vm, size, new_mem->page_shift, - NV_MEM_ACCESS_RW, &old_mem->vma[1]); + ret = nvif_vmm_get(vmm, LAZY, false, new_mem->mem.page, 0, + new_mem->mem.size, &old_mem->vma[1]); + if (ret) + goto done; + + ret = nouveau_mem_map(old_mem, vmm, &old_mem->vma[0]); + if (ret) + goto done; + + ret = nouveau_mem_map(new_mem, vmm, &old_mem->vma[1]); +done: if (ret) { - nvkm_vm_put(&old_mem->vma[0]); - return ret; + nvif_vmm_put(vmm, &old_mem->vma[1]); + nvif_vmm_put(vmm, &old_mem->vma[0]); } - - nvkm_vm_map(&old_mem->vma[0], old_mem); - nvkm_vm_map(&old_mem->vma[1], new_mem); return 0; } @@ -1200,21 +1270,23 @@ static void nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, bool evict, struct ttm_mem_reg *new_reg) { + struct nouveau_mem *mem = new_reg ? nouveau_mem(new_reg) : NULL; struct nouveau_bo *nvbo = nouveau_bo(bo); - struct nvkm_vma *vma; + struct nouveau_vma *vma; /* ttm can now (stupidly) pass the driver bos it didn't create... */ if (bo->destroy != nouveau_bo_del_ttm) return; - list_for_each_entry(vma, &nvbo->vma_list, head) { - if (new_reg && new_reg->mem_type != TTM_PL_SYSTEM && - (new_reg->mem_type == TTM_PL_VRAM || - nvbo->page_shift != vma->vm->mmu->lpg_shift)) { - nvkm_vm_map(vma, new_reg->mm_node); - } else { + if (mem && new_reg->mem_type != TTM_PL_SYSTEM && + mem->mem.page == nvbo->page) { + list_for_each_entry(vma, &nvbo->vma_list, head) { + nouveau_vma_map(vma, mem); + } + } else { + list_for_each_entry(vma, &nvbo->vma_list, head) { WARN_ON(ttm_bo_wait(bo, false, false)); - nvkm_vm_unmap(vma); + nouveau_vma_unmap(vma); } } } @@ -1234,8 +1306,7 @@ nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_reg, if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_CELSIUS) { *new_tile = nv10_bo_set_tiling(dev, offset, new_reg->size, - nvbo->tile_mode, - nvbo->tile_flags); + nvbo->mode, nvbo->zeta); } return 0; @@ -1331,8 +1402,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) struct ttm_mem_type_manager *man = &bdev->man[reg->mem_type]; struct nouveau_drm *drm = nouveau_bdev(bdev); struct nvkm_device *device = nvxx_device(&drm->client.device); - struct nvkm_mem *mem = reg->mm_node; - int ret; + struct nouveau_mem *mem = nouveau_mem(reg); reg->bus.addr = NULL; reg->bus.offset = 0; @@ -1353,7 +1423,7 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) reg->bus.is_iomem = !drm->agp.cma; } #endif - if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA || !mem->memtype) + if (drm->client.mem->oclass < NVIF_CLASS_MEM_NV50 || !mem->kind) /* untiled */ break; /* fallthrough, tiled memory */ @@ -1361,19 +1431,40 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) reg->bus.offset = reg->start << PAGE_SHIFT; reg->bus.base = device->func->resource_addr(device, 1); reg->bus.is_iomem = true; - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - struct nvkm_bar *bar = nvxx_bar(&drm->client.device); - int page_shift = 12; - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_FERMI) - page_shift = mem->page_shift; + if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) { + union { + struct nv50_mem_map_v0 nv50; + struct gf100_mem_map_v0 gf100; + } args; + u64 handle, length; + u32 argc = 0; + int ret; + + switch (mem->mem.object.oclass) { + case NVIF_CLASS_MEM_NV50: + args.nv50.version = 0; + args.nv50.ro = 0; + args.nv50.kind = mem->kind; + args.nv50.comp = mem->comp; + break; + case NVIF_CLASS_MEM_GF100: + args.gf100.version = 0; + args.gf100.ro = 0; + args.gf100.kind = mem->kind; + break; + default: + WARN_ON(1); + break; + } - ret = nvkm_bar_umap(bar, mem->size << 12, page_shift, - &mem->bar_vma); - if (ret) - return ret; + ret = nvif_object_map_handle(&mem->mem.object, + &argc, argc, + &handle, &length); + if (ret != 1) + return ret ? ret : -EINVAL; - nvkm_vm_map(&mem->bar_vma, mem); - reg->bus.offset = mem->bar_vma.offset; + reg->bus.base = 0; + reg->bus.offset = handle; } break; default: @@ -1385,13 +1476,22 @@ nouveau_ttm_io_mem_reserve(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) static void nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *reg) { - struct nvkm_mem *mem = reg->mm_node; - - if (!mem->bar_vma.node) - return; + struct nouveau_drm *drm = nouveau_bdev(bdev); + struct nouveau_mem *mem = nouveau_mem(reg); - nvkm_vm_unmap(&mem->bar_vma); - nvkm_vm_put(&mem->bar_vma); + if (drm->client.mem->oclass >= NVIF_CLASS_MEM_NV50) { + switch (reg->mem_type) { + case TTM_PL_TT: + if (mem->kind) + nvif_object_unmap_handle(&mem->mem.object); + break; + case TTM_PL_VRAM: + nvif_object_unmap_handle(&mem->mem.object); + break; + default: + break; + } + } } static int @@ -1408,7 +1508,7 @@ nouveau_ttm_fault_reserve_notify(struct ttm_buffer_object *bo) */ if (bo->mem.mem_type != TTM_PL_VRAM) { if (drm->client.device.info.family < NV_DEVICE_INFO_V0_TESLA || - !nouveau_bo_tile_layout(nvbo)) + !nvbo->kind) return 0; if (bo->mem.mem_type == TTM_PL_SYSTEM) { @@ -1445,9 +1545,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) { struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; - struct nvkm_device *device; - struct drm_device *dev; - struct device *pdev; + struct device *dev; unsigned i; int r; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); @@ -1464,9 +1562,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) } drm = nouveau_bdev(ttm->bdev); - device = nvxx_device(&drm->client.device); - dev = drm->dev; - pdev = device->dev; + dev = drm->dev->dev; #if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) { @@ -1476,7 +1572,7 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) #if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86) if (swiotlb_nr_tbl()) { - return ttm_dma_populate((void *)ttm, dev->dev); + return ttm_dma_populate((void *)ttm, dev); } #endif @@ -1488,12 +1584,12 @@ nouveau_ttm_tt_populate(struct ttm_tt *ttm) for (i = 0; i < ttm->num_pages; i++) { dma_addr_t addr; - addr = dma_map_page(pdev, ttm->pages[i], 0, PAGE_SIZE, + addr = dma_map_page(dev, ttm->pages[i], 0, PAGE_SIZE, DMA_BIDIRECTIONAL); - if (dma_mapping_error(pdev, addr)) { + if (dma_mapping_error(dev, addr)) { while (i--) { - dma_unmap_page(pdev, ttm_dma->dma_address[i], + dma_unmap_page(dev, ttm_dma->dma_address[i], PAGE_SIZE, DMA_BIDIRECTIONAL); ttm_dma->dma_address[i] = 0; } @@ -1511,9 +1607,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) { struct ttm_dma_tt *ttm_dma = (void *)ttm; struct nouveau_drm *drm; - struct nvkm_device *device; - struct drm_device *dev; - struct device *pdev; + struct device *dev; unsigned i; bool slave = !!(ttm->page_flags & TTM_PAGE_FLAG_SG); @@ -1521,9 +1615,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) return; drm = nouveau_bdev(ttm->bdev); - device = nvxx_device(&drm->client.device); - dev = drm->dev; - pdev = device->dev; + dev = drm->dev->dev; #if IS_ENABLED(CONFIG_AGP) if (drm->agp.bridge) { @@ -1534,14 +1626,14 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) #if IS_ENABLED(CONFIG_SWIOTLB) && IS_ENABLED(CONFIG_X86) if (swiotlb_nr_tbl()) { - ttm_dma_unpopulate((void *)ttm, dev->dev); + ttm_dma_unpopulate((void *)ttm, dev); return; } #endif for (i = 0; i < ttm->num_pages; i++) { if (ttm_dma->dma_address[i]) { - dma_unmap_page(pdev, ttm_dma->dma_address[i], PAGE_SIZE, + dma_unmap_page(dev, ttm_dma->dma_address[i], PAGE_SIZE, DMA_BIDIRECTIONAL); } } @@ -1576,48 +1668,3 @@ struct ttm_bo_driver nouveau_bo_driver = { .io_mem_free = &nouveau_ttm_io_mem_free, .io_mem_pfn = ttm_bo_default_io_mem_pfn, }; - -struct nvkm_vma * -nouveau_bo_vma_find(struct nouveau_bo *nvbo, struct nvkm_vm *vm) -{ - struct nvkm_vma *vma; - list_for_each_entry(vma, &nvbo->vma_list, head) { - if (vma->vm == vm) - return vma; - } - - return NULL; -} - -int -nouveau_bo_vma_add(struct nouveau_bo *nvbo, struct nvkm_vm *vm, - struct nvkm_vma *vma) -{ - const u32 size = nvbo->bo.mem.num_pages << PAGE_SHIFT; - int ret; - - ret = nvkm_vm_get(vm, size, nvbo->page_shift, - NV_MEM_ACCESS_RW, vma); - if (ret) - return ret; - - if ( nvbo->bo.mem.mem_type != TTM_PL_SYSTEM && - (nvbo->bo.mem.mem_type == TTM_PL_VRAM || - nvbo->page_shift != vma->vm->mmu->lpg_shift)) - nvkm_vm_map(vma, nvbo->bo.mem.mm_node); - - list_add_tail(&vma->head, &nvbo->vma_list); - vma->refcount = 1; - return 0; -} - -void -nouveau_bo_vma_del(struct nouveau_bo *nvbo, struct nvkm_vma *vma) -{ - if (vma->node) { - if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM) - nvkm_vm_unmap(vma); - nvkm_vm_put(vma); - list_del(&vma->head); - } -} diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index b06a5385d6dd..23002bdd94a8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -24,12 +24,16 @@ struct nouveau_bo { bool validate_mapped; struct list_head vma_list; - unsigned page_shift; struct nouveau_cli *cli; - u32 tile_mode; - u32 tile_flags; + unsigned contig:1; + unsigned page:5; + unsigned kind:8; + unsigned comp:3; + unsigned zeta:3; + unsigned mode; + struct nouveau_drm_tile *tile; /* Only valid if allocated via nouveau_gem_new() and iff you hold a @@ -89,13 +93,6 @@ int nouveau_bo_validate(struct nouveau_bo *, bool interruptible, void nouveau_bo_sync_for_device(struct nouveau_bo *nvbo); void nouveau_bo_sync_for_cpu(struct nouveau_bo *nvbo); -struct nvkm_vma * -nouveau_bo_vma_find(struct nouveau_bo *, struct nvkm_vm *); - -int nouveau_bo_vma_add(struct nouveau_bo *, struct nvkm_vm *, - struct nvkm_vma *); -void nouveau_bo_vma_del(struct nouveau_bo *, struct nvkm_vma *); - /* TODO: submit equivalent to TTM generic API upstream? */ static inline void __iomem * nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.c b/drivers/gpu/drm/nouveau/nouveau_chan.c index dbc41fa86ee8..af1116655910 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.c +++ b/drivers/gpu/drm/nouveau/nouveau_chan.c @@ -40,6 +40,7 @@ #include "nouveau_chan.h" #include "nouveau_fence.h" #include "nouveau_abi16.h" +#include "nouveau_vmm.h" MODULE_PARM_DESC(vram_pushbuf, "Create DMA push buffers in VRAM"); int nouveau_vram_pushbuf; @@ -83,6 +84,14 @@ nouveau_channel_del(struct nouveau_channel **pchan) { struct nouveau_channel *chan = *pchan; if (chan) { + struct nouveau_cli *cli = (void *)chan->user.client; + bool super; + + if (cli) { + super = cli->base.super; + cli->base.super = true; + } + if (chan->fence) nouveau_fence(chan->drm)->context_del(chan); nvif_object_fini(&chan->nvsw); @@ -91,12 +100,15 @@ nouveau_channel_del(struct nouveau_channel **pchan) nvif_notify_fini(&chan->kill); nvif_object_fini(&chan->user); nvif_object_fini(&chan->push.ctxdma); - nouveau_bo_vma_del(chan->push.buffer, &chan->push.vma); + nouveau_vma_del(&chan->push.vma); nouveau_bo_unmap(chan->push.buffer); if (chan->push.buffer && chan->push.buffer->pin_refcnt) nouveau_bo_unpin(chan->push.buffer); nouveau_bo_ref(NULL, &chan->push.buffer); kfree(chan); + + if (cli) + cli->base.super = super; } *pchan = NULL; } @@ -106,7 +118,6 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, u32 size, struct nouveau_channel **pchan) { struct nouveau_cli *cli = (void *)device->object.client; - struct nvkm_mmu *mmu = nvxx_mmu(device); struct nv_dma_v0 args = {}; struct nouveau_channel *chan; u32 target; @@ -142,11 +153,11 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, * pushbuf lives in, this is because the GEM code requires that * we be able to call out to other (indirect) push buffers */ - chan->push.vma.offset = chan->push.buffer->bo.offset; + chan->push.addr = chan->push.buffer->bo.offset; if (device->info.family >= NV_DEVICE_INFO_V0_TESLA) { - ret = nouveau_bo_vma_add(chan->push.buffer, cli->vm, - &chan->push.vma); + ret = nouveau_vma_new(chan->push.buffer, &cli->vmm, + &chan->push.vma); if (ret) { nouveau_channel_del(pchan); return ret; @@ -155,7 +166,9 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, args.target = NV_DMA_V0_TARGET_VM; args.access = NV_DMA_V0_ACCESS_VM; args.start = 0; - args.limit = cli->vm->mmu->limit - 1; + args.limit = cli->vmm.vmm.limit - 1; + + chan->push.addr = chan->push.vma->addr; } else if (chan->push.buffer->bo.mem.mem_type == TTM_PL_VRAM) { if (device->info.family == NV_DEVICE_INFO_V0_TNT) { @@ -185,7 +198,7 @@ nouveau_channel_prep(struct nouveau_drm *drm, struct nvif_device *device, args.target = NV_DMA_V0_TARGET_VM; args.access = NV_DMA_V0_ACCESS_RDWR; args.start = 0; - args.limit = mmu->limit - 1; + args.limit = cli->vmm.vmm.limit - 1; } } @@ -203,6 +216,7 @@ static int nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, u32 engine, struct nouveau_channel **pchan) { + struct nouveau_cli *cli = (void *)device->object.client; static const u16 oclasses[] = { PASCAL_CHANNEL_GPFIFO_A, MAXWELL_CHANNEL_GPFIFO_A, KEPLER_CHANNEL_GPFIFO_B, @@ -233,22 +247,22 @@ nouveau_channel_ind(struct nouveau_drm *drm, struct nvif_device *device, args.kepler.version = 0; args.kepler.engines = engine; args.kepler.ilength = 0x02000; - args.kepler.ioffset = 0x10000 + chan->push.vma.offset; - args.kepler.vm = 0; + args.kepler.ioffset = 0x10000 + chan->push.addr; + args.kepler.vmm = nvif_handle(&cli->vmm.vmm.object); size = sizeof(args.kepler); } else if (oclass[0] >= FERMI_CHANNEL_GPFIFO) { args.fermi.version = 0; args.fermi.ilength = 0x02000; - args.fermi.ioffset = 0x10000 + chan->push.vma.offset; - args.fermi.vm = 0; + args.fermi.ioffset = 0x10000 + chan->push.addr; + args.fermi.vmm = nvif_handle(&cli->vmm.vmm.object); size = sizeof(args.fermi); } else { args.nv50.version = 0; args.nv50.ilength = 0x02000; - args.nv50.ioffset = 0x10000 + chan->push.vma.offset; + args.nv50.ioffset = 0x10000 + chan->push.addr; args.nv50.pushbuf = nvif_handle(&chan->push.ctxdma); - args.nv50.vm = 0; + args.nv50.vmm = nvif_handle(&cli->vmm.vmm.object); size = sizeof(args.nv50); } @@ -293,7 +307,7 @@ nouveau_channel_dma(struct nouveau_drm *drm, struct nvif_device *device, /* create channel object */ args.version = 0; args.pushbuf = nvif_handle(&chan->push.ctxdma); - args.offset = chan->push.vma.offset; + args.offset = chan->push.addr; do { ret = nvif_object_init(&device->object, 0, *oclass++, @@ -314,11 +328,10 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) struct nvif_device *device = chan->device; struct nouveau_cli *cli = (void *)chan->user.client; struct nouveau_drm *drm = chan->drm; - struct nvkm_mmu *mmu = nvxx_mmu(device); struct nv_dma_v0 args = {}; int ret, i; - nvif_object_map(&chan->user); + nvif_object_map(&chan->user, NULL, 0); if (chan->user.oclass >= FERMI_CHANNEL_GPFIFO) { ret = nvif_notify_init(&chan->user, nouveau_channel_killed, @@ -339,7 +352,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) args.target = NV_DMA_V0_TARGET_VM; args.access = NV_DMA_V0_ACCESS_VM; args.start = 0; - args.limit = cli->vm->mmu->limit - 1; + args.limit = cli->vmm.vmm.limit - 1; } else { args.target = NV_DMA_V0_TARGET_VRAM; args.access = NV_DMA_V0_ACCESS_RDWR; @@ -356,7 +369,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) args.target = NV_DMA_V0_TARGET_VM; args.access = NV_DMA_V0_ACCESS_VM; args.start = 0; - args.limit = cli->vm->mmu->limit - 1; + args.limit = cli->vmm.vmm.limit - 1; } else if (chan->drm->agp.bridge) { args.target = NV_DMA_V0_TARGET_AGP; @@ -368,7 +381,7 @@ nouveau_channel_init(struct nouveau_channel *chan, u32 vram, u32 gart) args.target = NV_DMA_V0_TARGET_VM; args.access = NV_DMA_V0_ACCESS_RDWR; args.start = 0; - args.limit = mmu->limit - 1; + args.limit = cli->vmm.vmm.limit - 1; } ret = nvif_object_init(&chan->user, gart, NV_DMA_IN_MEMORY, diff --git a/drivers/gpu/drm/nouveau/nouveau_chan.h b/drivers/gpu/drm/nouveau/nouveau_chan.h index 46b947ba1cf4..f29d3a72c48c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_chan.h +++ b/drivers/gpu/drm/nouveau/nouveau_chan.h @@ -16,8 +16,9 @@ struct nouveau_channel { struct { struct nouveau_bo *buffer; - struct nvkm_vma vma; + struct nouveau_vma *vma; struct nvif_object ctxdma; + u64 addr; } push; /* TODO: this will be reworked in the near future */ diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 70d8e0d69ad5..69d6e61a01ec 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -373,7 +373,7 @@ find_encoder(struct drm_connector *connector, int type) if (!id) break; - enc = drm_encoder_find(dev, id); + enc = drm_encoder_find(dev, NULL, id); if (!enc) continue; nv_encoder = nouveau_encoder(enc); @@ -441,7 +441,7 @@ nouveau_connector_ddc_detect(struct drm_connector *connector) if (id == 0) break; - encoder = drm_encoder_find(dev, id); + encoder = drm_encoder_find(dev, NULL, id); if (!encoder) continue; nv_encoder = nouveau_encoder(encoder); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 201aec2ea5b8..1411bf05b89d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -1,14 +1,11 @@ #ifndef __NOUVEAU_DISPLAY_H__ #define __NOUVEAU_DISPLAY_H__ - -#include <subdev/mmu.h> - #include "nouveau_drv.h" struct nouveau_framebuffer { struct drm_framebuffer base; struct nouveau_bo *nvbo; - struct nvkm_vma vma; + struct nouveau_vma *vma; u32 r_handle; u32 r_format; u32 r_pitch; diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 2634a1a79888..10e84f6ca2b7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c @@ -26,6 +26,7 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" +#include "nouveau_vmm.h" void OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) @@ -71,11 +72,11 @@ READ_GET(struct nouveau_channel *chan, uint64_t *prev_get, int *timeout) return -EBUSY; } - if (val < chan->push.vma.offset || - val > chan->push.vma.offset + (chan->dma.max << 2)) + if (val < chan->push.addr || + val > chan->push.addr + (chan->dma.max << 2)) return -EINVAL; - return (val - chan->push.vma.offset) >> 2; + return (val - chan->push.addr) >> 2; } void @@ -84,13 +85,13 @@ nv50_dma_push(struct nouveau_channel *chan, struct nouveau_bo *bo, { struct nouveau_cli *cli = (void *)chan->user.client; struct nouveau_bo *pb = chan->push.buffer; - struct nvkm_vma *vma; + struct nouveau_vma *vma; int ip = (chan->dma.ib_put * 2) + chan->dma.ib_base; u64 offset; - vma = nouveau_bo_vma_find(bo, cli->vm); + vma = nouveau_vma_find(bo, &cli->vmm); BUG_ON(!vma); - offset = vma->offset + delta; + offset = vma->addr + delta; BUG_ON(chan->dma.ib_free < 1); @@ -224,7 +225,7 @@ nouveau_dma_wait(struct nouveau_channel *chan, int slots, int size) * instruct the GPU to jump back to the start right * after processing the currently pending commands. */ - OUT_RING(chan, chan->push.vma.offset | 0x20000000); + OUT_RING(chan, chan->push.addr | 0x20000000); /* wait for GET to depart from the skips area. * prevents writing GET==PUT and causing a race diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.h b/drivers/gpu/drm/nouveau/nouveau_dma.h index aff3a9d0a1fc..74e10b14a7da 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.h +++ b/drivers/gpu/drm/nouveau/nouveau_dma.h @@ -140,7 +140,7 @@ BEGIN_IMC0(struct nouveau_channel *chan, int subc, int mthd, u16 data) #define WRITE_PUT(val) do { \ mb(); \ nouveau_bo_rd32(chan->push.buffer, 0); \ - nvif_wr32(&chan->user, chan->user_put, ((val) << 2) + chan->push.vma.offset); \ + nvif_wr32(&chan->user, chan->user_put, ((val) << 2) + chan->push.addr);\ } while (0) static inline void diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 595630d1fb9e..8d4a5be3b913 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -111,33 +111,119 @@ nouveau_name(struct drm_device *dev) return nouveau_platform_name(to_platform_device(dev->dev)); } +static inline bool +nouveau_cli_work_ready(struct dma_fence *fence, bool wait) +{ + if (!dma_fence_is_signaled(fence)) { + if (!wait) + return false; + WARN_ON(dma_fence_wait_timeout(fence, false, 2 * HZ) <= 0); + } + dma_fence_put(fence); + return true; +} + +static void +nouveau_cli_work_flush(struct nouveau_cli *cli, bool wait) +{ + struct nouveau_cli_work *work, *wtmp; + mutex_lock(&cli->lock); + list_for_each_entry_safe(work, wtmp, &cli->worker, head) { + if (!work->fence || nouveau_cli_work_ready(work->fence, wait)) { + list_del(&work->head); + work->func(work); + } + } + mutex_unlock(&cli->lock); +} + +static void +nouveau_cli_work_fence(struct dma_fence *fence, struct dma_fence_cb *cb) +{ + struct nouveau_cli_work *work = container_of(cb, typeof(*work), cb); + schedule_work(&work->cli->work); +} + +void +nouveau_cli_work_queue(struct nouveau_cli *cli, struct dma_fence *fence, + struct nouveau_cli_work *work) +{ + work->fence = dma_fence_get(fence); + work->cli = cli; + mutex_lock(&cli->lock); + list_add_tail(&work->head, &cli->worker); + mutex_unlock(&cli->lock); + if (dma_fence_add_callback(fence, &work->cb, nouveau_cli_work_fence)) + nouveau_cli_work_fence(fence, &work->cb); +} + +static void +nouveau_cli_work(struct work_struct *w) +{ + struct nouveau_cli *cli = container_of(w, typeof(*cli), work); + nouveau_cli_work_flush(cli, false); +} + static void nouveau_cli_fini(struct nouveau_cli *cli) { - nvkm_vm_ref(NULL, &nvxx_client(&cli->base)->vm, NULL); + nouveau_cli_work_flush(cli, true); usif_client_fini(cli); + nouveau_vmm_fini(&cli->vmm); + nvif_mmu_fini(&cli->mmu); nvif_device_fini(&cli->device); + mutex_lock(&cli->drm->master.lock); nvif_client_fini(&cli->base); + mutex_unlock(&cli->drm->master.lock); } static int nouveau_cli_init(struct nouveau_drm *drm, const char *sname, struct nouveau_cli *cli) { + static const struct nvif_mclass + mems[] = { + { NVIF_CLASS_MEM_GF100, -1 }, + { NVIF_CLASS_MEM_NV50 , -1 }, + { NVIF_CLASS_MEM_NV04 , -1 }, + {} + }; + static const struct nvif_mclass + mmus[] = { + { NVIF_CLASS_MMU_GF100, -1 }, + { NVIF_CLASS_MMU_NV50 , -1 }, + { NVIF_CLASS_MMU_NV04 , -1 }, + {} + }; + static const struct nvif_mclass + vmms[] = { + { NVIF_CLASS_VMM_GP100, -1 }, + { NVIF_CLASS_VMM_GM200, -1 }, + { NVIF_CLASS_VMM_GF100, -1 }, + { NVIF_CLASS_VMM_NV50 , -1 }, + { NVIF_CLASS_VMM_NV04 , -1 }, + {} + }; u64 device = nouveau_name(drm->dev); int ret; snprintf(cli->name, sizeof(cli->name), "%s", sname); - cli->dev = drm->dev; + cli->drm = drm; mutex_init(&cli->mutex); usif_client_init(cli); - if (cli == &drm->client) { + INIT_WORK(&cli->work, nouveau_cli_work); + INIT_LIST_HEAD(&cli->worker); + mutex_init(&cli->lock); + + if (cli == &drm->master) { ret = nvif_driver_init(NULL, nouveau_config, nouveau_debug, cli->name, device, &cli->base); } else { - ret = nvif_client_init(&drm->client.base, cli->name, device, + mutex_lock(&drm->master.lock); + ret = nvif_client_init(&drm->master.base, cli->name, device, &cli->base); + mutex_unlock(&drm->master.lock); } if (ret) { NV_ERROR(drm, "Client allocation failed: %d\n", ret); @@ -154,6 +240,38 @@ nouveau_cli_init(struct nouveau_drm *drm, const char *sname, goto done; } + ret = nvif_mclass(&cli->device.object, mmus); + if (ret < 0) { + NV_ERROR(drm, "No supported MMU class\n"); + goto done; + } + + ret = nvif_mmu_init(&cli->device.object, mmus[ret].oclass, &cli->mmu); + if (ret) { + NV_ERROR(drm, "MMU allocation failed: %d\n", ret); + goto done; + } + + ret = nvif_mclass(&cli->mmu.object, vmms); + if (ret < 0) { + NV_ERROR(drm, "No supported VMM class\n"); + goto done; + } + + ret = nouveau_vmm_init(cli, vmms[ret].oclass, &cli->vmm); + if (ret) { + NV_ERROR(drm, "VMM allocation failed: %d\n", ret); + goto done; + } + + ret = nvif_mclass(&cli->mmu.object, mems); + if (ret < 0) { + NV_ERROR(drm, "No supported MEM class\n"); + goto done; + } + + cli->mem = &mems[ret]; + return 0; done: if (ret) nouveau_cli_fini(cli); @@ -433,6 +551,10 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) dev->dev_private = drm; drm->dev = dev; + ret = nouveau_cli_init(drm, "DRM-master", &drm->master); + if (ret) + return ret; + ret = nouveau_cli_init(drm, "DRM", &drm->client); if (ret) return ret; @@ -456,21 +578,6 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) nouveau_vga_init(drm); - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - if (!nvxx_device(&drm->client.device)->mmu) { - ret = -ENOSYS; - goto fail_device; - } - - ret = nvkm_vm_new(nvxx_device(&drm->client.device), - 0, (1ULL << 40), 0x1000, NULL, - &drm->client.vm); - if (ret) - goto fail_device; - - nvxx_client(&drm->client.base)->vm = drm->client.vm; - } - ret = nouveau_ttm_init(drm); if (ret) goto fail_ttm; @@ -516,8 +623,8 @@ fail_bios: nouveau_ttm_fini(drm); fail_ttm: nouveau_vga_fini(drm); -fail_device: nouveau_cli_fini(&drm->client); + nouveau_cli_fini(&drm->master); kfree(drm); return ret; } @@ -550,6 +657,7 @@ nouveau_drm_unload(struct drm_device *dev) if (drm->hdmi_device) pci_dev_put(drm->hdmi_device); nouveau_cli_fini(&drm->client); + nouveau_cli_fini(&drm->master); kfree(drm); } @@ -618,7 +726,7 @@ nouveau_do_suspend(struct drm_device *dev, bool runtime) } NV_DEBUG(drm, "suspending object tree...\n"); - ret = nvif_client_suspend(&drm->client.base); + ret = nvif_client_suspend(&drm->master.base); if (ret) goto fail_client; @@ -642,7 +750,7 @@ nouveau_do_resume(struct drm_device *dev, bool runtime) struct nouveau_drm *drm = nouveau_drm(dev); NV_DEBUG(drm, "resuming object tree...\n"); - nvif_client_resume(&drm->client.base); + nvif_client_resume(&drm->master.base); NV_DEBUG(drm, "resuming fence...\n"); if (drm->fence && nouveau_fence(drm)->resume) @@ -850,15 +958,6 @@ nouveau_drm_open(struct drm_device *dev, struct drm_file *fpriv) cli->base.super = false; - if (drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { - ret = nvkm_vm_new(nvxx_device(&drm->client.device), 0, - (1ULL << 40), 0x1000, NULL, &cli->vm); - if (ret) - goto done; - - nvxx_client(&cli->base)->vm = cli->vm; - } - fpriv->driver_priv = cli; mutex_lock(&drm->client.mutex); diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 822fe1d4d35e..e86b8220a4bb 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h @@ -5,7 +5,7 @@ #define DRIVER_EMAIL "nouveau@lists.freedesktop.org" #define DRIVER_NAME "nouveau" -#define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla" +#define DRIVER_DESC "nVidia Riva/TNT/GeForce/Quadro/Tesla/Tegra K1+" #define DRIVER_DATE "20120801" #define DRIVER_MAJOR 1 @@ -42,6 +42,8 @@ #include <nvif/client.h> #include <nvif/device.h> #include <nvif/ioctl.h> +#include <nvif/mmu.h> +#include <nvif/vmm.h> #include <drm/drmP.h> @@ -61,6 +63,7 @@ struct platform_device; #include "nouveau_fence.h" #include "nouveau_bios.h" +#include "nouveau_vmm.h" struct nouveau_drm_tile { struct nouveau_fence *fence; @@ -86,19 +89,37 @@ enum nouveau_drm_handle { struct nouveau_cli { struct nvif_client base; - struct drm_device *dev; + struct nouveau_drm *drm; struct mutex mutex; struct nvif_device device; + struct nvif_mmu mmu; + struct nouveau_vmm vmm; + const struct nvif_mclass *mem; - struct nvkm_vm *vm; /*XXX*/ struct list_head head; void *abi16; struct list_head objects; struct list_head notifys; char name[32]; + + struct work_struct work; + struct list_head worker; + struct mutex lock; }; +struct nouveau_cli_work { + void (*func)(struct nouveau_cli_work *); + struct nouveau_cli *cli; + struct list_head head; + + struct dma_fence *fence; + struct dma_fence_cb cb; +}; + +void nouveau_cli_work_queue(struct nouveau_cli *, struct dma_fence *, + struct nouveau_cli_work *); + static inline struct nouveau_cli * nouveau_cli(struct drm_file *fpriv) { @@ -109,6 +130,7 @@ nouveau_cli(struct drm_file *fpriv) #include <nvif/device.h> struct nouveau_drm { + struct nouveau_cli master; struct nouveau_cli client; struct drm_device *dev; @@ -133,6 +155,9 @@ struct nouveau_drm { struct nouveau_channel *chan; struct nvif_object copy; int mtrr; + int type_vram; + int type_host; + int type_ncoh; } ttm; /* GEM interface support */ @@ -204,7 +229,7 @@ void nouveau_drm_device_remove(struct drm_device *dev); #define NV_PRINTK(l,c,f,a...) do { \ struct nouveau_cli *_cli = (c); \ - dev_##l(_cli->dev->dev, "%s: "f, _cli->name, ##a); \ + dev_##l(_cli->drm->dev->dev, "%s: "f, _cli->name, ##a); \ } while(0) #define NV_FATAL(drm,f,a...) NV_PRINTK(crit, &(drm)->client, f, ##a) #define NV_ERROR(drm,f,a...) NV_PRINTK(err, &(drm)->client, f, ##a) diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index f7707849bb53..c533d8e04afc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -48,6 +48,7 @@ #include "nouveau_bo.h" #include "nouveau_fbcon.h" #include "nouveau_chan.h" +#include "nouveau_vmm.h" #include "nouveau_crtc.h" @@ -223,7 +224,7 @@ void nouveau_fbcon_accel_save_disable(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - if (drm->fbcon) { + if (drm->fbcon && drm->fbcon->helper.fbdev) { drm->fbcon->saved_flags = drm->fbcon->helper.fbdev->flags; drm->fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; } @@ -233,7 +234,7 @@ void nouveau_fbcon_accel_restore(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); - if (drm->fbcon) { + if (drm->fbcon && drm->fbcon->helper.fbdev) { drm->fbcon->helper.fbdev->flags = drm->fbcon->saved_flags; } } @@ -245,7 +246,8 @@ nouveau_fbcon_accel_fini(struct drm_device *dev) struct nouveau_fbdev *fbcon = drm->fbcon; if (fbcon && drm->channel) { console_lock(); - fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; + if (fbcon->helper.fbdev) + fbcon->helper.fbdev->flags |= FBINFO_HWACCEL_DISABLED; console_unlock(); nouveau_channel_idle(drm->channel); nvif_object_fini(&fbcon->twod); @@ -347,7 +349,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, chan = nouveau_nofbaccel ? NULL : drm->channel; if (chan && device->info.family >= NV_DEVICE_INFO_V0_TESLA) { - ret = nouveau_bo_vma_add(nvbo, drm->client.vm, &fb->vma); + ret = nouveau_vma_new(nvbo, &drm->client.vmm, &fb->vma); if (ret) { NV_ERROR(drm, "failed to map fb into chan: %d\n", ret); chan = NULL; @@ -401,7 +403,7 @@ nouveau_fbcon_create(struct drm_fb_helper *helper, out_unlock: if (chan) - nouveau_bo_vma_del(fb->nvbo, &fb->vma); + nouveau_vma_del(&fb->vma); nouveau_bo_unmap(fb->nvbo); out_unpin: nouveau_bo_unpin(fb->nvbo); @@ -428,7 +430,7 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) drm_fb_helper_fini(&fbcon->helper); if (nouveau_fb->nvbo) { - nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma); + nouveau_vma_del(&nouveau_fb->vma); nouveau_bo_unmap(nouveau_fb->nvbo); nouveau_bo_unpin(nouveau_fb->nvbo); drm_framebuffer_unreference(&nouveau_fb->base); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 99e14e3e0fe4..503fa94dc06d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -199,62 +199,6 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha WARN_ON(ret); } -struct nouveau_fence_work { - struct work_struct work; - struct dma_fence_cb cb; - void (*func)(void *); - void *data; -}; - -static void -nouveau_fence_work_handler(struct work_struct *kwork) -{ - struct nouveau_fence_work *work = container_of(kwork, typeof(*work), work); - work->func(work->data); - kfree(work); -} - -static void nouveau_fence_work_cb(struct dma_fence *fence, struct dma_fence_cb *cb) -{ - struct nouveau_fence_work *work = container_of(cb, typeof(*work), cb); - - schedule_work(&work->work); -} - -void -nouveau_fence_work(struct dma_fence *fence, - void (*func)(void *), void *data) -{ - struct nouveau_fence_work *work; - - if (dma_fence_is_signaled(fence)) - goto err; - - work = kmalloc(sizeof(*work), GFP_KERNEL); - if (!work) { - /* - * this might not be a nouveau fence any more, - * so force a lazy wait here - */ - WARN_ON(nouveau_fence_wait((struct nouveau_fence *)fence, - true, false)); - goto err; - } - - INIT_WORK(&work->work, nouveau_fence_work_handler); - work->func = func; - work->data = data; - - if (dma_fence_add_callback(fence, &work->cb, nouveau_fence_work_cb) < 0) - goto err_free; - return; - -err_free: - kfree(work); -err: - func(data); -} - int nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) { @@ -474,8 +418,6 @@ nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, if (!fence) return -ENOMEM; - fence->sysmem = sysmem; - ret = nouveau_fence_emit(fence, chan); if (ret) nouveau_fence_unref(&fence); diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index d5e58a38f160..c36031aa013e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h @@ -12,8 +12,6 @@ struct nouveau_fence { struct list_head head; - bool sysmem; - struct nouveau_channel __rcu *channel; unsigned long timeout; }; @@ -24,7 +22,6 @@ void nouveau_fence_unref(struct nouveau_fence **); int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); bool nouveau_fence_done(struct nouveau_fence *); -void nouveau_fence_work(struct dma_fence *, void (*)(void *), void *); int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr); int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr); @@ -90,14 +87,12 @@ int nouveau_flip_complete(struct nvif_notify *); struct nv84_fence_chan { struct nouveau_fence_chan base; - struct nvkm_vma vma; - struct nvkm_vma vma_gart; + struct nouveau_vma *vma; }; struct nv84_fence_priv { struct nouveau_fence_priv base; struct nouveau_bo *bo; - struct nouveau_bo *bo_gart; u32 *suspend; struct mutex mutex; }; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 2170534101ca..efc89aaef66a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -31,6 +31,10 @@ #include "nouveau_ttm.h" #include "nouveau_gem.h" +#include "nouveau_mem.h" +#include "nouveau_vmm.h" + +#include <nvif/class.h> void nouveau_gem_object_del(struct drm_gem_object *gem) @@ -64,66 +68,61 @@ nouveau_gem_object_open(struct drm_gem_object *gem, struct drm_file *file_priv) struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); - struct nvkm_vma *vma; struct device *dev = drm->dev->dev; + struct nouveau_vma *vma; int ret; - if (!cli->vm) + if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50) return 0; ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); if (ret) return ret; - vma = nouveau_bo_vma_find(nvbo, cli->vm); - if (!vma) { - vma = kzalloc(sizeof(*vma), GFP_KERNEL); - if (!vma) { - ret = -ENOMEM; - goto out; - } - - ret = pm_runtime_get_sync(dev); - if (ret < 0 && ret != -EACCES) { - kfree(vma); - goto out; - } - - ret = nouveau_bo_vma_add(nvbo, cli->vm, vma); - if (ret) - kfree(vma); - - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - } else { - vma->refcount++; - } + ret = pm_runtime_get_sync(dev); + if (ret < 0 && ret != -EACCES) + goto out; + ret = nouveau_vma_new(nvbo, &cli->vmm, &vma); + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); out: ttm_bo_unreserve(&nvbo->bo); return ret; } +struct nouveau_gem_object_unmap { + struct nouveau_cli_work work; + struct nouveau_vma *vma; +}; + static void -nouveau_gem_object_delete(void *data) +nouveau_gem_object_delete(struct nouveau_vma *vma) { - struct nvkm_vma *vma = data; - nvkm_vm_unmap(vma); - nvkm_vm_put(vma); - kfree(vma); + nouveau_vma_del(&vma); } static void -nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nvkm_vma *vma) +nouveau_gem_object_delete_work(struct nouveau_cli_work *w) +{ + struct nouveau_gem_object_unmap *work = + container_of(w, typeof(*work), work); + nouveau_gem_object_delete(work->vma); + kfree(work); +} + +static void +nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nouveau_vma *vma) { const bool mapped = nvbo->bo.mem.mem_type != TTM_PL_SYSTEM; struct reservation_object *resv = nvbo->bo.resv; struct reservation_object_list *fobj; + struct nouveau_gem_object_unmap *work; struct dma_fence *fence = NULL; fobj = reservation_object_get_list(resv); - list_del(&vma->head); + list_del_init(&vma->head); if (fobj && fobj->shared_count > 1) ttm_bo_wait(&nvbo->bo, false, false); @@ -133,14 +132,20 @@ nouveau_gem_object_unmap(struct nouveau_bo *nvbo, struct nvkm_vma *vma) else fence = reservation_object_get_excl(nvbo->bo.resv); - if (fence && mapped) { - nouveau_fence_work(fence, nouveau_gem_object_delete, vma); - } else { - if (mapped) - nvkm_vm_unmap(vma); - nvkm_vm_put(vma); - kfree(vma); + if (!fence || !mapped) { + nouveau_gem_object_delete(vma); + return; + } + + if (!(work = kmalloc(sizeof(*work), GFP_KERNEL))) { + WARN_ON(dma_fence_wait_timeout(fence, false, 2 * HZ) <= 0); + nouveau_gem_object_delete(vma); + return; } + + work->work.func = nouveau_gem_object_delete_work; + work->vma = vma; + nouveau_cli_work_queue(vma->vmm->cli, fence, &work->work); } void @@ -150,19 +155,19 @@ nouveau_gem_object_close(struct drm_gem_object *gem, struct drm_file *file_priv) struct nouveau_bo *nvbo = nouveau_gem_object(gem); struct nouveau_drm *drm = nouveau_bdev(nvbo->bo.bdev); struct device *dev = drm->dev->dev; - struct nvkm_vma *vma; + struct nouveau_vma *vma; int ret; - if (!cli->vm) + if (cli->vmm.vmm.object.oclass < NVIF_CLASS_VMM_NV50) return; ret = ttm_bo_reserve(&nvbo->bo, false, false, NULL); if (ret) return; - vma = nouveau_bo_vma_find(nvbo, cli->vm); + vma = nouveau_vma_find(nvbo, &cli->vmm); if (vma) { - if (--vma->refcount == 0) { + if (--vma->refs == 0) { ret = pm_runtime_get_sync(dev); if (!WARN_ON(ret < 0 && ret != -EACCES)) { nouveau_gem_object_unmap(nvbo, vma); @@ -179,7 +184,7 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, uint32_t tile_mode, uint32_t tile_flags, struct nouveau_bo **pnvbo) { - struct nouveau_drm *drm = nouveau_drm(cli->dev); + struct nouveau_drm *drm = cli->drm; struct nouveau_bo *nvbo; u32 flags = 0; int ret; @@ -227,7 +232,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, { struct nouveau_cli *cli = nouveau_cli(file_priv); struct nouveau_bo *nvbo = nouveau_gem_object(gem); - struct nvkm_vma *vma; + struct nouveau_vma *vma; if (is_power_of_2(nvbo->valid_domains)) rep->domain = nvbo->valid_domains; @@ -236,18 +241,25 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, else rep->domain = NOUVEAU_GEM_DOMAIN_VRAM; rep->offset = nvbo->bo.offset; - if (cli->vm) { - vma = nouveau_bo_vma_find(nvbo, cli->vm); + if (cli->vmm.vmm.object.oclass >= NVIF_CLASS_VMM_NV50) { + vma = nouveau_vma_find(nvbo, &cli->vmm); if (!vma) return -EINVAL; - rep->offset = vma->offset; + rep->offset = vma->addr; } rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node); - rep->tile_mode = nvbo->tile_mode; - rep->tile_flags = nvbo->tile_flags; + rep->tile_mode = nvbo->mode; + rep->tile_flags = nvbo->contig ? 0 : NOUVEAU_GEM_TILE_NONCONTIG; + if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) + rep->tile_flags |= nvbo->kind << 8; + else + if (cli->device.info.family >= NV_DEVICE_INFO_V0_TESLA) + rep->tile_flags |= nvbo->kind << 8 | nvbo->comp << 16; + else + rep->tile_flags |= nvbo->zeta; return 0; } @@ -255,18 +267,11 @@ int nouveau_gem_ioctl_new(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_cli *cli = nouveau_cli(file_priv); - struct nvkm_fb *fb = nvxx_fb(&drm->client.device); struct drm_nouveau_gem_new *req = data; struct nouveau_bo *nvbo = NULL; int ret = 0; - if (!nvkm_fb_memtype_valid(fb, req->info.tile_flags)) { - NV_PRINTK(err, cli, "bad page flags: 0x%08x\n", req->info.tile_flags); - return -EINVAL; - } - ret = nouveau_gem_new(cli, req->info.size, req->align, req->info.domain, req->info.tile_mode, req->info.tile_flags, &nvbo); @@ -791,7 +796,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, bo[push[i].bo_index].user_priv; uint32_t cmd; - cmd = chan->push.vma.offset + ((chan->dma.cur + 2) << 2); + cmd = chan->push.addr + ((chan->dma.cur + 2) << 2); cmd |= 0x20000000; if (unlikely(cmd != req->suffix0)) { if (!nvbo->kmap.virtual) { @@ -843,7 +848,7 @@ out_next: req->suffix1 = 0x00000000; } else { req->suffix0 = 0x20000000 | - (chan->push.vma.offset + ((chan->dma.cur + 2) << 2)); + (chan->push.addr + ((chan->dma.cur + 2) << 2)); req->suffix1 = 0x00000000; } diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h index 8fa6ed9ddd3a..d39f845dda87 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.h +++ b/drivers/gpu/drm/nouveau/nouveau_gem.h @@ -6,9 +6,6 @@ #include "nouveau_drv.h" #include "nouveau_bo.h" -#define nouveau_bo_tile_layout(nvbo) \ - ((nvbo)->tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) - static inline struct nouveau_bo * nouveau_gem_object(struct drm_gem_object *gem) { diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c new file mode 100644 index 000000000000..589a9621db76 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c @@ -0,0 +1,198 @@ +/* + * 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 "nouveau_mem.h" +#include "nouveau_drv.h" +#include "nouveau_bo.h" + +#include <drm/ttm/ttm_bo_driver.h> + +#include <nvif/class.h> +#include <nvif/if000a.h> +#include <nvif/if500b.h> +#include <nvif/if500d.h> +#include <nvif/if900b.h> +#include <nvif/if900d.h> + +int +nouveau_mem_map(struct nouveau_mem *mem, + struct nvif_vmm *vmm, struct nvif_vma *vma) +{ + union { + struct nv50_vmm_map_v0 nv50; + struct gf100_vmm_map_v0 gf100; + } args; + u32 argc = 0; + bool super; + int ret; + + switch (vmm->object.oclass) { + case NVIF_CLASS_VMM_NV04: + break; + case NVIF_CLASS_VMM_NV50: + args.nv50.version = 0; + args.nv50.ro = 0; + args.nv50.priv = 0; + args.nv50.kind = mem->kind; + args.nv50.comp = mem->comp; + argc = sizeof(args.nv50); + break; + case NVIF_CLASS_VMM_GF100: + case NVIF_CLASS_VMM_GM200: + case NVIF_CLASS_VMM_GP100: + args.gf100.version = 0; + if (mem->mem.type & NVIF_MEM_VRAM) + args.gf100.vol = 0; + else + args.gf100.vol = 1; + args.gf100.ro = 0; + args.gf100.priv = 0; + args.gf100.kind = mem->kind; + argc = sizeof(args.gf100); + break; + default: + WARN_ON(1); + return -ENOSYS; + } + + super = vmm->object.client->super; + vmm->object.client->super = true; + ret = nvif_vmm_map(vmm, vma->addr, mem->mem.size, &args, argc, + &mem->mem, 0); + vmm->object.client->super = super; + return ret; +} + +void +nouveau_mem_fini(struct nouveau_mem *mem) +{ + nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[1]); + nvif_vmm_put(&mem->cli->drm->client.vmm.vmm, &mem->vma[0]); + mutex_lock(&mem->cli->drm->master.lock); + nvif_mem_fini(&mem->mem); + mutex_unlock(&mem->cli->drm->master.lock); +} + +int +nouveau_mem_host(struct ttm_mem_reg *reg, struct ttm_dma_tt *tt) +{ + struct nouveau_mem *mem = nouveau_mem(reg); + struct nouveau_cli *cli = mem->cli; + struct nouveau_drm *drm = cli->drm; + struct nvif_mmu *mmu = &cli->mmu; + struct nvif_mem_ram_v0 args = {}; + bool super = cli->base.super; + u8 type; + int ret; + + if (mmu->type[drm->ttm.type_host].type & NVIF_MEM_UNCACHED) + type = drm->ttm.type_ncoh; + else + type = drm->ttm.type_host; + + if (mem->kind && !(mmu->type[type].type & NVIF_MEM_KIND)) + mem->comp = mem->kind = 0; + if (mem->comp && !(mmu->type[type].type & NVIF_MEM_COMP)) { + if (mmu->object.oclass >= NVIF_CLASS_MMU_GF100) + mem->kind = mmu->kind[mem->kind]; + mem->comp = 0; + } + + if (tt->ttm.sg) args.sgl = tt->ttm.sg->sgl; + else args.dma = tt->dma_address; + + mutex_lock(&drm->master.lock); + cli->base.super = true; + ret = nvif_mem_init_type(mmu, cli->mem->oclass, type, PAGE_SHIFT, + reg->num_pages << PAGE_SHIFT, + &args, sizeof(args), &mem->mem); + cli->base.super = super; + mutex_unlock(&drm->master.lock); + return ret; +} + +int +nouveau_mem_vram(struct ttm_mem_reg *reg, bool contig, u8 page) +{ + struct nouveau_mem *mem = nouveau_mem(reg); + struct nouveau_cli *cli = mem->cli; + struct nouveau_drm *drm = cli->drm; + struct nvif_mmu *mmu = &cli->mmu; + bool super = cli->base.super; + u64 size = ALIGN(reg->num_pages << PAGE_SHIFT, 1 << page); + int ret; + + mutex_lock(&drm->master.lock); + cli->base.super = true; + switch (cli->mem->oclass) { + case NVIF_CLASS_MEM_GF100: + ret = nvif_mem_init_type(mmu, cli->mem->oclass, + drm->ttm.type_vram, page, size, + &(struct gf100_mem_v0) { + .contig = contig, + }, sizeof(struct gf100_mem_v0), + &mem->mem); + break; + case NVIF_CLASS_MEM_NV50: + ret = nvif_mem_init_type(mmu, cli->mem->oclass, + drm->ttm.type_vram, page, size, + &(struct nv50_mem_v0) { + .bankswz = mmu->kind[mem->kind] == 2, + .contig = contig, + }, sizeof(struct nv50_mem_v0), + &mem->mem); + break; + default: + ret = -ENOSYS; + WARN_ON(1); + break; + } + cli->base.super = super; + mutex_unlock(&drm->master.lock); + + reg->start = mem->mem.addr >> PAGE_SHIFT; + return ret; +} + +void +nouveau_mem_del(struct ttm_mem_reg *reg) +{ + struct nouveau_mem *mem = nouveau_mem(reg); + nouveau_mem_fini(mem); + kfree(reg->mm_node); + reg->mm_node = NULL; +} + +int +nouveau_mem_new(struct nouveau_cli *cli, u8 kind, u8 comp, + struct ttm_mem_reg *reg) +{ + struct nouveau_mem *mem; + + if (!(mem = kzalloc(sizeof(*mem), GFP_KERNEL))) + return -ENOMEM; + mem->cli = cli; + mem->kind = kind; + mem->comp = comp; + + reg->mm_node = mem; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.h b/drivers/gpu/drm/nouveau/nouveau_mem.h new file mode 100644 index 000000000000..f6d039e73812 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_mem.h @@ -0,0 +1,30 @@ +#ifndef __NOUVEAU_MEM_H__ +#define __NOUVEAU_MEM_H__ +#include <drm/ttm/ttm_bo_api.h> +struct ttm_dma_tt; + +#include <nvif/mem.h> +#include <nvif/vmm.h> + +static inline struct nouveau_mem * +nouveau_mem(struct ttm_mem_reg *reg) +{ + return reg->mm_node; +} + +struct nouveau_mem { + struct nouveau_cli *cli; + u8 kind; + u8 comp; + struct nvif_mem mem; + struct nvif_vma vma[2]; +}; + +int nouveau_mem_new(struct nouveau_cli *, u8 kind, u8 comp, + struct ttm_mem_reg *); +void nouveau_mem_del(struct ttm_mem_reg *); +int nouveau_mem_vram(struct ttm_mem_reg *, bool contig, u8 page); +int nouveau_mem_host(struct ttm_mem_reg *, struct ttm_dma_tt *); +void nouveau_mem_fini(struct nouveau_mem *); +int nouveau_mem_map(struct nouveau_mem *, struct nvif_vmm *, struct nvif_vma *); +#endif diff --git a/drivers/gpu/drm/nouveau/nouveau_sgdma.c b/drivers/gpu/drm/nouveau/nouveau_sgdma.c index b7ab268f7d6f..941bf33bd249 100644 --- a/drivers/gpu/drm/nouveau/nouveau_sgdma.c +++ b/drivers/gpu/drm/nouveau/nouveau_sgdma.c @@ -2,6 +2,7 @@ #include <linux/slab.h> #include "nouveau_drv.h" +#include "nouveau_mem.h" #include "nouveau_ttm.h" struct nouveau_sgdma_be { @@ -9,7 +10,7 @@ struct nouveau_sgdma_be { * nouve_bo.c works properly, otherwise have to move them here */ struct ttm_dma_tt ttm; - struct nvkm_mem *node; + struct nouveau_mem *mem; }; static void @@ -27,19 +28,20 @@ static int nv04_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct nvkm_mem *node = reg->mm_node; - - if (ttm->sg) { - node->sg = ttm->sg; - node->pages = NULL; - } else { - node->sg = NULL; - node->pages = nvbe->ttm.dma_address; + struct nouveau_mem *mem = nouveau_mem(reg); + int ret; + + ret = nouveau_mem_host(reg, &nvbe->ttm); + if (ret) + return ret; + + ret = nouveau_mem_map(mem, &mem->cli->vmm.vmm, &mem->vma[0]); + if (ret) { + nouveau_mem_fini(mem); + return ret; } - node->size = (reg->num_pages << PAGE_SHIFT) >> 12; - nvkm_vm_map(&node->vma[0], node); - nvbe->node = node; + nvbe->mem = mem; return 0; } @@ -47,7 +49,7 @@ static int nv04_sgdma_unbind(struct ttm_tt *ttm) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - nvkm_vm_unmap(&nvbe->node->vma[0]); + nouveau_mem_fini(nvbe->mem); return 0; } @@ -61,30 +63,20 @@ static int nv50_sgdma_bind(struct ttm_tt *ttm, struct ttm_mem_reg *reg) { struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)ttm; - struct nvkm_mem *node = reg->mm_node; - - /* noop: bound in move_notify() */ - if (ttm->sg) { - node->sg = ttm->sg; - node->pages = NULL; - } else { - node->sg = NULL; - node->pages = nvbe->ttm.dma_address; - } - node->size = (reg->num_pages << PAGE_SHIFT) >> 12; - return 0; -} + struct nouveau_mem *mem = nouveau_mem(reg); + int ret; -static int -nv50_sgdma_unbind(struct ttm_tt *ttm) -{ - /* noop: unbound in move_notify() */ + ret = nouveau_mem_host(reg, &nvbe->ttm); + if (ret) + return ret; + + nvbe->mem = mem; return 0; } static struct ttm_backend_func nv50_sgdma_backend = { .bind = nv50_sgdma_bind, - .unbind = nv50_sgdma_unbind, + .unbind = nv04_sgdma_unbind, .destroy = nouveau_sgdma_destroy }; diff --git a/drivers/gpu/drm/nouveau/nouveau_ttm.c b/drivers/gpu/drm/nouveau/nouveau_ttm.c index b0ad7fcefcf5..08b974b30482 100644 --- a/drivers/gpu/drm/nouveau/nouveau_ttm.c +++ b/drivers/gpu/drm/nouveau/nouveau_ttm.c @@ -23,53 +23,37 @@ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE * USE OR OTHER DEALINGS IN THE SOFTWARE. */ - #include "nouveau_drv.h" -#include "nouveau_ttm.h" #include "nouveau_gem.h" +#include "nouveau_mem.h" +#include "nouveau_ttm.h" #include <drm/drm_legacy.h> #include <core/tegra.h> static int -nouveau_vram_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) +nouveau_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) { - struct nouveau_drm *drm = nouveau_bdev(man->bdev); - struct nvkm_fb *fb = nvxx_fb(&drm->client.device); - man->priv = fb; return 0; } static int -nouveau_vram_manager_fini(struct ttm_mem_type_manager *man) +nouveau_manager_fini(struct ttm_mem_type_manager *man) { - man->priv = NULL; return 0; } -static inline void -nvkm_mem_node_cleanup(struct nvkm_mem *node) +static void +nouveau_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *reg) { - if (node->vma[0].node) { - nvkm_vm_unmap(&node->vma[0]); - nvkm_vm_put(&node->vma[0]); - } - - if (node->vma[1].node) { - nvkm_vm_unmap(&node->vma[1]); - nvkm_vm_put(&node->vma[1]); - } + nouveau_mem_del(reg); } static void -nouveau_vram_manager_del(struct ttm_mem_type_manager *man, - struct ttm_mem_reg *reg) +nouveau_manager_debug(struct ttm_mem_type_manager *man, + struct drm_printer *printer) { - struct nouveau_drm *drm = nouveau_bdev(man->bdev); - struct nvkm_ram *ram = nvxx_fb(&drm->client.device)->ram; - nvkm_mem_node_cleanup(reg->mm_node); - ram->func->put(ram, (struct nvkm_mem **)®->mm_node); } static int @@ -78,192 +62,105 @@ nouveau_vram_manager_new(struct ttm_mem_type_manager *man, const struct ttm_place *place, struct ttm_mem_reg *reg) { - struct nouveau_drm *drm = nouveau_bdev(man->bdev); - struct nvkm_ram *ram = nvxx_fb(&drm->client.device)->ram; struct nouveau_bo *nvbo = nouveau_bo(bo); - struct nvkm_mem *node; - u32 size_nc = 0; + struct nouveau_drm *drm = nvbo->cli->drm; + struct nouveau_mem *mem; int ret; if (drm->client.device.info.ram_size == 0) return -ENOMEM; - if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) - size_nc = 1 << nvbo->page_shift; + ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg); + mem = nouveau_mem(reg); + if (ret) + return ret; - ret = ram->func->get(ram, reg->num_pages << PAGE_SHIFT, - reg->page_alignment << PAGE_SHIFT, size_nc, - (nvbo->tile_flags >> 8) & 0x3ff, &node); + ret = nouveau_mem_vram(reg, nvbo->contig, nvbo->page); if (ret) { - reg->mm_node = NULL; - return (ret == -ENOSPC) ? 0 : ret; + nouveau_mem_del(reg); + if (ret == -ENOSPC) { + reg->mm_node = NULL; + return 0; + } + return ret; } - node->page_shift = nvbo->page_shift; - - reg->mm_node = node; - reg->start = node->offset >> PAGE_SHIFT; return 0; } const struct ttm_mem_type_manager_func nouveau_vram_manager = { - .init = nouveau_vram_manager_init, - .takedown = nouveau_vram_manager_fini, + .init = nouveau_manager_init, + .takedown = nouveau_manager_fini, .get_node = nouveau_vram_manager_new, - .put_node = nouveau_vram_manager_del, + .put_node = nouveau_manager_del, + .debug = nouveau_manager_debug, }; static int -nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) -{ - return 0; -} - -static int -nouveau_gart_manager_fini(struct ttm_mem_type_manager *man) -{ - return 0; -} - -static void -nouveau_gart_manager_del(struct ttm_mem_type_manager *man, - struct ttm_mem_reg *reg) -{ - nvkm_mem_node_cleanup(reg->mm_node); - kfree(reg->mm_node); - reg->mm_node = NULL; -} - -static int nouveau_gart_manager_new(struct ttm_mem_type_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *reg) { - struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct nouveau_bo *nvbo = nouveau_bo(bo); - struct nvkm_mem *node; - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) - return -ENOMEM; + struct nouveau_drm *drm = nvbo->cli->drm; + struct nouveau_mem *mem; + int ret; - node->page_shift = 12; - - switch (drm->client.device.info.family) { - case NV_DEVICE_INFO_V0_TNT: - case NV_DEVICE_INFO_V0_CELSIUS: - case NV_DEVICE_INFO_V0_KELVIN: - case NV_DEVICE_INFO_V0_RANKINE: - case NV_DEVICE_INFO_V0_CURIE: - break; - case NV_DEVICE_INFO_V0_TESLA: - if (drm->client.device.info.chipset != 0x50) - node->memtype = (nvbo->tile_flags & 0x7f00) >> 8; - break; - case NV_DEVICE_INFO_V0_FERMI: - case NV_DEVICE_INFO_V0_KEPLER: - case NV_DEVICE_INFO_V0_MAXWELL: - case NV_DEVICE_INFO_V0_PASCAL: - node->memtype = (nvbo->tile_flags & 0xff00) >> 8; - break; - default: - NV_WARN(drm, "%s: unhandled family type %x\n", __func__, - drm->client.device.info.family); - break; - } + ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg); + mem = nouveau_mem(reg); + if (ret) + return ret; - reg->mm_node = node; - reg->start = 0; + reg->start = 0; return 0; } -static void -nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, - struct drm_printer *printer) -{ -} - const struct ttm_mem_type_manager_func nouveau_gart_manager = { - .init = nouveau_gart_manager_init, - .takedown = nouveau_gart_manager_fini, + .init = nouveau_manager_init, + .takedown = nouveau_manager_fini, .get_node = nouveau_gart_manager_new, - .put_node = nouveau_gart_manager_del, - .debug = nouveau_gart_manager_debug + .put_node = nouveau_manager_del, + .debug = nouveau_manager_debug }; -/*XXX*/ -#include <subdev/mmu/nv04.h> -static int -nv04_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize) -{ - struct nouveau_drm *drm = nouveau_bdev(man->bdev); - struct nvkm_mmu *mmu = nvxx_mmu(&drm->client.device); - struct nv04_mmu *priv = (void *)mmu; - struct nvkm_vm *vm = NULL; - nvkm_vm_ref(priv->vm, &vm, NULL); - man->priv = vm; - return 0; -} - -static int -nv04_gart_manager_fini(struct ttm_mem_type_manager *man) -{ - struct nvkm_vm *vm = man->priv; - nvkm_vm_ref(NULL, &vm, NULL); - man->priv = NULL; - return 0; -} - -static void -nv04_gart_manager_del(struct ttm_mem_type_manager *man, struct ttm_mem_reg *reg) -{ - struct nvkm_mem *node = reg->mm_node; - if (node->vma[0].node) - nvkm_vm_put(&node->vma[0]); - kfree(reg->mm_node); - reg->mm_node = NULL; -} - static int nv04_gart_manager_new(struct ttm_mem_type_manager *man, struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_mem_reg *reg) { - struct nvkm_mem *node; + struct nouveau_bo *nvbo = nouveau_bo(bo); + struct nouveau_drm *drm = nvbo->cli->drm; + struct nouveau_mem *mem; int ret; - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (!node) - return -ENOMEM; - - node->page_shift = 12; + ret = nouveau_mem_new(&drm->master, nvbo->kind, nvbo->comp, reg); + mem = nouveau_mem(reg); + if (ret) + return ret; - ret = nvkm_vm_get(man->priv, reg->num_pages << 12, node->page_shift, - NV_MEM_ACCESS_RW, &node->vma[0]); + ret = nvif_vmm_get(&mem->cli->vmm.vmm, PTES, false, 12, 0, + reg->num_pages << PAGE_SHIFT, &mem->vma[0]); if (ret) { - kfree(node); + nouveau_mem_del(reg); + if (ret == -ENOSPC) { + reg->mm_node = NULL; + return 0; + } return ret; } - reg->mm_node = node; - reg->start = node->vma[0].offset >> PAGE_SHIFT; + reg->start = mem->vma[0].addr >> PAGE_SHIFT; return 0; } -static void -nv04_gart_manager_debug(struct ttm_mem_type_manager *man, - struct drm_printer *printer) -{ -} - const struct ttm_mem_type_manager_func nv04_gart_manager = { - .init = nv04_gart_manager_init, - .takedown = nv04_gart_manager_fini, + .init = nouveau_manager_init, + .takedown = nouveau_manager_fini, .get_node = nv04_gart_manager_new, - .put_node = nv04_gart_manager_del, - .debug = nv04_gart_manager_debug + .put_node = nouveau_manager_del, + .debug = nouveau_manager_debug }; int @@ -343,44 +240,43 @@ nouveau_ttm_init(struct nouveau_drm *drm) { struct nvkm_device *device = nvxx_device(&drm->client.device); struct nvkm_pci *pci = device->pci; + struct nvif_mmu *mmu = &drm->client.mmu; struct drm_device *dev = drm->dev; - u8 bits; - int ret; + int typei, ret; - if (pci && pci->agp.bridge) { - drm->agp.bridge = pci->agp.bridge; - drm->agp.base = pci->agp.base; - drm->agp.size = pci->agp.size; - drm->agp.cma = pci->agp.cma; - } + typei = nvif_mmu_type(mmu, NVIF_MEM_HOST | NVIF_MEM_MAPPABLE | + NVIF_MEM_COHERENT); + if (typei < 0) + return -ENOSYS; - bits = nvxx_mmu(&drm->client.device)->dma_bits; - if (nvxx_device(&drm->client.device)->func->pci) { - if (drm->agp.bridge) - bits = 32; - } else if (device->func->tegra) { - struct nvkm_device_tegra *tegra = device->func->tegra(device); + drm->ttm.type_host = typei; - /* - * If the platform can use a IOMMU, then the addressable DMA - * space is constrained by the IOMMU bit - */ - if (tegra->func->iommu_bit) - bits = min(bits, tegra->func->iommu_bit); + typei = nvif_mmu_type(mmu, NVIF_MEM_HOST | NVIF_MEM_MAPPABLE); + if (typei < 0) + return -ENOSYS; - } + drm->ttm.type_ncoh = typei; - ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits)); - if (ret && bits != 32) { - bits = 32; - ret = dma_set_mask(dev->dev, DMA_BIT_MASK(bits)); + if (drm->client.device.info.platform != NV_DEVICE_INFO_V0_SOC && + drm->client.device.info.family >= NV_DEVICE_INFO_V0_TESLA) { + typei = nvif_mmu_type(mmu, NVIF_MEM_VRAM | NVIF_MEM_MAPPABLE | + NVIF_MEM_KIND | + NVIF_MEM_COMP | + NVIF_MEM_DISP); + if (typei < 0) + return -ENOSYS; + + drm->ttm.type_vram = typei; + } else { + drm->ttm.type_vram = -1; } - if (ret) - return ret; - ret = dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(bits)); - if (ret) - dma_set_coherent_mask(dev->dev, DMA_BIT_MASK(32)); + if (pci && pci->agp.bridge) { + drm->agp.bridge = pci->agp.bridge; + drm->agp.base = pci->agp.base; + drm->agp.size = pci->agp.size; + drm->agp.cma = pci->agp.cma; + } ret = nouveau_ttm_global_init(drm); if (ret) @@ -391,7 +287,7 @@ nouveau_ttm_init(struct nouveau_drm *drm) &nouveau_bo_driver, dev->anon_inode->i_mapping, DRM_FILE_PAGE_OFFSET, - bits <= 32 ? true : false); + drm->client.mmu.dmabits <= 32 ? true : false); if (ret) { NV_ERROR(drm, "error initialising bo driver, %d\n", ret); return ret; @@ -415,7 +311,7 @@ nouveau_ttm_init(struct nouveau_drm *drm) /* GART init */ if (!drm->agp.bridge) { - drm->gem.gart_available = nvxx_mmu(&drm->client.device)->limit; + drm->gem.gart_available = drm->client.vmm.vmm.limit; } else { drm->gem.gart_available = drm->agp.size; } diff --git a/drivers/gpu/drm/nouveau/nouveau_vmm.c b/drivers/gpu/drm/nouveau/nouveau_vmm.c new file mode 100644 index 000000000000..9e2628dd8e4d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_vmm.c @@ -0,0 +1,135 @@ +/* + * 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 "nouveau_vmm.h" +#include "nouveau_drv.h" +#include "nouveau_bo.h" +#include "nouveau_mem.h" + +void +nouveau_vma_unmap(struct nouveau_vma *vma) +{ + if (vma->mem) { + nvif_vmm_unmap(&vma->vmm->vmm, vma->addr); + vma->mem = NULL; + } +} + +int +nouveau_vma_map(struct nouveau_vma *vma, struct nouveau_mem *mem) +{ + struct nvif_vma tmp = { .addr = vma->addr }; + int ret = nouveau_mem_map(mem, &vma->vmm->vmm, &tmp); + if (ret) + return ret; + vma->mem = mem; + return 0; +} + +struct nouveau_vma * +nouveau_vma_find(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm) +{ + struct nouveau_vma *vma; + + list_for_each_entry(vma, &nvbo->vma_list, head) { + if (vma->vmm == vmm) + return vma; + } + + return NULL; +} + +void +nouveau_vma_del(struct nouveau_vma **pvma) +{ + struct nouveau_vma *vma = *pvma; + if (vma && --vma->refs <= 0) { + if (likely(vma->addr != ~0ULL)) { + struct nvif_vma tmp = { .addr = vma->addr, .size = 1 }; + nvif_vmm_put(&vma->vmm->vmm, &tmp); + } + list_del(&vma->head); + *pvma = NULL; + kfree(*pvma); + } +} + +int +nouveau_vma_new(struct nouveau_bo *nvbo, struct nouveau_vmm *vmm, + struct nouveau_vma **pvma) +{ + struct nouveau_mem *mem = nouveau_mem(&nvbo->bo.mem); + struct nouveau_vma *vma; + struct nvif_vma tmp; + int ret; + + if ((vma = *pvma = nouveau_vma_find(nvbo, vmm))) { + vma->refs++; + return 0; + } + + if (!(vma = *pvma = kmalloc(sizeof(*vma), GFP_KERNEL))) + return -ENOMEM; + vma->vmm = vmm; + vma->refs = 1; + vma->addr = ~0ULL; + vma->mem = NULL; + list_add_tail(&vma->head, &nvbo->vma_list); + + if (nvbo->bo.mem.mem_type != TTM_PL_SYSTEM && + mem->mem.page == nvbo->page) { + ret = nvif_vmm_get(&vmm->vmm, LAZY, false, mem->mem.page, 0, + mem->mem.size, &tmp); + if (ret) + goto done; + + vma->addr = tmp.addr; + ret = nouveau_vma_map(vma, mem); + } else { + ret = nvif_vmm_get(&vmm->vmm, PTES, false, mem->mem.page, 0, + mem->mem.size, &tmp); + vma->addr = tmp.addr; + } + +done: + if (ret) + nouveau_vma_del(pvma); + return ret; +} + +void +nouveau_vmm_fini(struct nouveau_vmm *vmm) +{ + nvif_vmm_fini(&vmm->vmm); + vmm->cli = NULL; +} + +int +nouveau_vmm_init(struct nouveau_cli *cli, s32 oclass, struct nouveau_vmm *vmm) +{ + int ret = nvif_vmm_init(&cli->mmu, oclass, PAGE_SIZE, 0, NULL, 0, + &vmm->vmm); + if (ret) + return ret; + + vmm->cli = cli; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nouveau_vmm.h b/drivers/gpu/drm/nouveau/nouveau_vmm.h new file mode 100644 index 000000000000..5c31f43678d3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nouveau_vmm.h @@ -0,0 +1,31 @@ +#ifndef __NOUVEAU_VMA_H__ +#define __NOUVEAU_VMA_H__ +#include <nvif/vmm.h> +struct nouveau_bo; +struct nouveau_mem; + +struct nouveau_vma { + struct nouveau_vmm *vmm; + int refs; + struct list_head head; + u64 addr; + + struct nouveau_mem *mem; +}; + +struct nouveau_vma *nouveau_vma_find(struct nouveau_bo *, struct nouveau_vmm *); +int nouveau_vma_new(struct nouveau_bo *, struct nouveau_vmm *, + struct nouveau_vma **); +void nouveau_vma_del(struct nouveau_vma **); +int nouveau_vma_map(struct nouveau_vma *, struct nouveau_mem *); +void nouveau_vma_unmap(struct nouveau_vma *); + +struct nouveau_vmm { + struct nouveau_cli *cli; + struct nvif_vmm vmm; + struct nvkm_vm *vm; +}; + +int nouveau_vmm_init(struct nouveau_cli *, s32 oclass, struct nouveau_vmm *); +void nouveau_vmm_fini(struct nouveau_vmm *); +#endif diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 9fc8fe017118..9c61e767950d 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -318,7 +318,7 @@ nv50_chan_create(struct nvif_device *device, struct nvif_object *disp, ret = nvif_object_init(disp, 0, oclass[0], data, size, &chan->user); if (ret == 0) - nvif_object_map(&chan->user); + nvif_object_map(&chan->user, NULL, 0); nvif_object_sclass_put(&sclass); return ret; } @@ -424,7 +424,7 @@ nv50_dmac_ctxdma_new(struct nv50_dmac *dmac, struct nouveau_framebuffer *fb) { struct nouveau_drm *drm = nouveau_drm(fb->base.dev); struct nv50_dmac_ctxdma *ctxdma; - const u8 kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8; + const u8 kind = fb->nvbo->kind; const u32 handle = 0xfb000000 | kind; struct { struct nv_dma_v0 base; @@ -510,6 +510,7 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, int ret; mutex_init(&dmac->lock); + INIT_LIST_HEAD(&dmac->ctxdma); dmac->ptr = dma_alloc_coherent(nvxx_device(device)->dev, PAGE_SIZE, &dmac->handle, GFP_KERNEL); @@ -556,7 +557,6 @@ nv50_dmac_create(struct nvif_device *device, struct nvif_object *disp, if (ret) return ret; - INIT_LIST_HEAD(&dmac->ctxdma); return ret; } @@ -847,7 +847,7 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, asyw->image.w = fb->base.width; asyw->image.h = fb->base.height; - asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8; + asyw->image.kind = fb->nvbo->kind; if (asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC) asyw->interval = 0; @@ -857,9 +857,9 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw, if (asyw->image.kind) { asyw->image.layout = 0; if (drm->client.device.info.chipset >= 0xc0) - asyw->image.block = fb->nvbo->tile_mode >> 4; + asyw->image.block = fb->nvbo->mode >> 4; else - asyw->image.block = fb->nvbo->tile_mode; + asyw->image.block = fb->nvbo->mode; asyw->image.pitch = (fb->base.pitches[0] / 4) << 4; } else { asyw->image.layout = 1; @@ -3264,11 +3264,14 @@ nv50_mstm = { void nv50_mstm_service(struct nv50_mstm *mstm) { - struct drm_dp_aux *aux = mstm->mgr.aux; + struct drm_dp_aux *aux = mstm ? mstm->mgr.aux : NULL; bool handled = true; int ret; u8 esi[8] = {}; + if (!aux) + return; + while (handled) { ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT_ESI, esi, 8); if (ret != 8) { diff --git a/drivers/gpu/drm/nouveau/nv50_fbcon.c b/drivers/gpu/drm/nouveau/nv50_fbcon.c index 327dcd7901ed..facd18564e0d 100644 --- a/drivers/gpu/drm/nouveau/nv50_fbcon.c +++ b/drivers/gpu/drm/nouveau/nv50_fbcon.c @@ -25,6 +25,7 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" #include "nouveau_fbcon.h" +#include "nouveau_vmm.h" int nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) @@ -239,8 +240,8 @@ nv50_fbcon_accel_init(struct fb_info *info) OUT_RING(chan, info->fix.line_length); OUT_RING(chan, info->var.xres_virtual); OUT_RING(chan, info->var.yres_virtual); - OUT_RING(chan, upper_32_bits(fb->vma.offset)); - OUT_RING(chan, lower_32_bits(fb->vma.offset)); + OUT_RING(chan, upper_32_bits(fb->vma->addr)); + OUT_RING(chan, lower_32_bits(fb->vma->addr)); BEGIN_NV04(chan, NvSub2D, 0x0230, 2); OUT_RING(chan, format); OUT_RING(chan, 1); @@ -248,8 +249,8 @@ nv50_fbcon_accel_init(struct fb_info *info) OUT_RING(chan, info->fix.line_length); OUT_RING(chan, info->var.xres_virtual); OUT_RING(chan, info->var.yres_virtual); - OUT_RING(chan, upper_32_bits(fb->vma.offset)); - OUT_RING(chan, lower_32_bits(fb->vma.offset)); + OUT_RING(chan, upper_32_bits(fb->vma->addr)); + OUT_RING(chan, lower_32_bits(fb->vma->addr)); FIRE_RING(chan); return 0; diff --git a/drivers/gpu/drm/nouveau/nv84_fence.c b/drivers/gpu/drm/nouveau/nv84_fence.c index bd7a8a1e4ad9..5f0c0c27d5dc 100644 --- a/drivers/gpu/drm/nouveau/nv84_fence.c +++ b/drivers/gpu/drm/nouveau/nv84_fence.c @@ -25,6 +25,7 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" #include "nouveau_fence.h" +#include "nouveau_vmm.h" #include "nv50_display.h" @@ -68,12 +69,7 @@ nv84_fence_emit(struct nouveau_fence *fence) { struct nouveau_channel *chan = fence->channel; struct nv84_fence_chan *fctx = chan->fence; - u64 addr = chan->chid * 16; - - if (fence->sysmem) - addr += fctx->vma_gart.offset; - else - addr += fctx->vma.offset; + u64 addr = fctx->vma->addr + chan->chid * 16; return fctx->base.emit32(chan, addr, fence->base.seqno); } @@ -83,12 +79,7 @@ nv84_fence_sync(struct nouveau_fence *fence, struct nouveau_channel *prev, struct nouveau_channel *chan) { struct nv84_fence_chan *fctx = chan->fence; - u64 addr = prev->chid * 16; - - if (fence->sysmem) - addr += fctx->vma_gart.offset; - else - addr += fctx->vma.offset; + u64 addr = fctx->vma->addr + prev->chid * 16; return fctx->base.sync32(chan, addr, fence->base.seqno); } @@ -108,8 +99,7 @@ nv84_fence_context_del(struct nouveau_channel *chan) nouveau_bo_wr32(priv->bo, chan->chid * 16 / 4, fctx->base.sequence); mutex_lock(&priv->mutex); - nouveau_bo_vma_del(priv->bo, &fctx->vma_gart); - nouveau_bo_vma_del(priv->bo, &fctx->vma); + nouveau_vma_del(&fctx->vma); mutex_unlock(&priv->mutex); nouveau_fence_context_del(&fctx->base); chan->fence = NULL; @@ -137,11 +127,7 @@ nv84_fence_context_new(struct nouveau_channel *chan) fctx->base.sequence = nv84_fence_read(chan); mutex_lock(&priv->mutex); - ret = nouveau_bo_vma_add(priv->bo, cli->vm, &fctx->vma); - if (ret == 0) { - ret = nouveau_bo_vma_add(priv->bo_gart, cli->vm, - &fctx->vma_gart); - } + ret = nouveau_vma_new(priv->bo, &cli->vmm, &fctx->vma); mutex_unlock(&priv->mutex); if (ret) @@ -182,10 +168,6 @@ static void nv84_fence_destroy(struct nouveau_drm *drm) { struct nv84_fence_priv *priv = drm->fence; - nouveau_bo_unmap(priv->bo_gart); - if (priv->bo_gart) - nouveau_bo_unpin(priv->bo_gart); - nouveau_bo_ref(NULL, &priv->bo_gart); nouveau_bo_unmap(priv->bo); if (priv->bo) nouveau_bo_unpin(priv->bo); @@ -238,21 +220,6 @@ nv84_fence_create(struct nouveau_drm *drm) nouveau_bo_ref(NULL, &priv->bo); } - if (ret == 0) - ret = nouveau_bo_new(&drm->client, 16 * priv->base.contexts, 0, - TTM_PL_FLAG_TT | TTM_PL_FLAG_UNCACHED, 0, - 0, NULL, NULL, &priv->bo_gart); - if (ret == 0) { - ret = nouveau_bo_pin(priv->bo_gart, TTM_PL_FLAG_TT, false); - if (ret == 0) { - ret = nouveau_bo_map(priv->bo_gart); - if (ret) - nouveau_bo_unpin(priv->bo_gart); - } - if (ret) - nouveau_bo_ref(NULL, &priv->bo_gart); - } - if (ret) nv84_fence_destroy(drm); return ret; diff --git a/drivers/gpu/drm/nouveau/nvc0_fbcon.c b/drivers/gpu/drm/nouveau/nvc0_fbcon.c index 90f27bfa381f..c0deef4fe727 100644 --- a/drivers/gpu/drm/nouveau/nvc0_fbcon.c +++ b/drivers/gpu/drm/nouveau/nvc0_fbcon.c @@ -25,6 +25,7 @@ #include "nouveau_drv.h" #include "nouveau_dma.h" #include "nouveau_fbcon.h" +#include "nouveau_vmm.h" int nvc0_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) @@ -239,8 +240,8 @@ nvc0_fbcon_accel_init(struct fb_info *info) OUT_RING (chan, info->fix.line_length); OUT_RING (chan, info->var.xres_virtual); OUT_RING (chan, info->var.yres_virtual); - OUT_RING (chan, upper_32_bits(fb->vma.offset)); - OUT_RING (chan, lower_32_bits(fb->vma.offset)); + OUT_RING (chan, upper_32_bits(fb->vma->addr)); + OUT_RING (chan, lower_32_bits(fb->vma->addr)); BEGIN_NVC0(chan, NvSub2D, 0x0230, 10); OUT_RING (chan, format); OUT_RING (chan, 1); @@ -250,8 +251,8 @@ nvc0_fbcon_accel_init(struct fb_info *info) OUT_RING (chan, info->fix.line_length); OUT_RING (chan, info->var.xres_virtual); OUT_RING (chan, info->var.yres_virtual); - OUT_RING (chan, upper_32_bits(fb->vma.offset)); - OUT_RING (chan, lower_32_bits(fb->vma.offset)); + OUT_RING (chan, upper_32_bits(fb->vma->addr)); + OUT_RING (chan, lower_32_bits(fb->vma->addr)); FIRE_RING (chan); return 0; diff --git a/drivers/gpu/drm/nouveau/nvif/Kbuild b/drivers/gpu/drm/nouveau/nvif/Kbuild index 067b5e9f5ec1..f1675a4ab6fa 100644 --- a/drivers/gpu/drm/nouveau/nvif/Kbuild +++ b/drivers/gpu/drm/nouveau/nvif/Kbuild @@ -2,4 +2,7 @@ nvif-y := nvif/object.o nvif-y += nvif/client.o nvif-y += nvif/device.o nvif-y += nvif/driver.o +nvif-y += nvif/mem.o +nvif-y += nvif/mmu.o nvif-y += nvif/notify.o +nvif-y += nvif/vmm.o diff --git a/drivers/gpu/drm/nouveau/nvif/mem.c b/drivers/gpu/drm/nouveau/nvif/mem.c new file mode 100644 index 000000000000..0f9382c60145 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvif/mem.c @@ -0,0 +1,88 @@ +/* + * 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 <nvif/mem.h> +#include <nvif/client.h> + +#include <nvif/if000a.h> + +void +nvif_mem_fini(struct nvif_mem *mem) +{ + nvif_object_fini(&mem->object); +} + +int +nvif_mem_init_type(struct nvif_mmu *mmu, s32 oclass, int type, u8 page, + u64 size, void *argv, u32 argc, struct nvif_mem *mem) +{ + struct nvif_mem_v0 *args; + u8 stack[128]; + int ret; + + mem->object.client = NULL; + if (type < 0) + return -EINVAL; + + if (sizeof(*args) + argc > sizeof(stack)) { + if (!(args = kmalloc(sizeof(*args) + argc, GFP_KERNEL))) + return -ENOMEM; + } else { + args = (void *)stack; + } + args->version = 0; + args->type = type; + args->page = page; + args->size = size; + memcpy(args->data, argv, argc); + + ret = nvif_object_init(&mmu->object, 0, oclass, args, + sizeof(*args) + argc, &mem->object); + if (ret == 0) { + mem->type = mmu->type[type].type; + mem->page = args->page; + mem->addr = args->addr; + mem->size = args->size; + } + + if (args != (void *)stack) + kfree(args); + return ret; + +} + +int +nvif_mem_init(struct nvif_mmu *mmu, s32 oclass, u8 type, u8 page, + u64 size, void *argv, u32 argc, struct nvif_mem *mem) +{ + int ret = -EINVAL, i; + + mem->object.client = NULL; + + for (i = 0; ret && i < mmu->type_nr; i++) { + if ((mmu->type[i].type & type) == type) { + ret = nvif_mem_init_type(mmu, oclass, i, page, size, + argv, argc, mem); + } + } + + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvif/mmu.c b/drivers/gpu/drm/nouveau/nvif/mmu.c new file mode 100644 index 000000000000..15d0dcbf7ab4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvif/mmu.c @@ -0,0 +1,117 @@ +/* + * 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 <nvif/mmu.h> + +#include <nvif/class.h> +#include <nvif/if0008.h> + +void +nvif_mmu_fini(struct nvif_mmu *mmu) +{ + kfree(mmu->kind); + kfree(mmu->type); + kfree(mmu->heap); + nvif_object_fini(&mmu->object); +} + +int +nvif_mmu_init(struct nvif_object *parent, s32 oclass, struct nvif_mmu *mmu) +{ + struct nvif_mmu_v0 args; + int ret, i; + + args.version = 0; + mmu->heap = NULL; + mmu->type = NULL; + mmu->kind = NULL; + + ret = nvif_object_init(parent, 0, oclass, &args, sizeof(args), + &mmu->object); + if (ret) + goto done; + + mmu->dmabits = args.dmabits; + mmu->heap_nr = args.heap_nr; + mmu->type_nr = args.type_nr; + mmu->kind_nr = args.kind_nr; + + mmu->heap = kmalloc(sizeof(*mmu->heap) * mmu->heap_nr, GFP_KERNEL); + mmu->type = kmalloc(sizeof(*mmu->type) * mmu->type_nr, GFP_KERNEL); + if (ret = -ENOMEM, !mmu->heap || !mmu->type) + goto done; + + mmu->kind = kmalloc(sizeof(*mmu->kind) * mmu->kind_nr, GFP_KERNEL); + if (!mmu->kind && mmu->kind_nr) + goto done; + + for (i = 0; i < mmu->heap_nr; i++) { + struct nvif_mmu_heap_v0 args = { .index = i }; + + ret = nvif_object_mthd(&mmu->object, NVIF_MMU_V0_HEAP, + &args, sizeof(args)); + if (ret) + goto done; + + mmu->heap[i].size = args.size; + } + + for (i = 0; i < mmu->type_nr; i++) { + struct nvif_mmu_type_v0 args = { .index = i }; + + ret = nvif_object_mthd(&mmu->object, NVIF_MMU_V0_TYPE, + &args, sizeof(args)); + if (ret) + goto done; + + mmu->type[i].type = 0; + if (args.vram) mmu->type[i].type |= NVIF_MEM_VRAM; + if (args.host) mmu->type[i].type |= NVIF_MEM_HOST; + if (args.comp) mmu->type[i].type |= NVIF_MEM_COMP; + if (args.disp) mmu->type[i].type |= NVIF_MEM_DISP; + if (args.kind ) mmu->type[i].type |= NVIF_MEM_KIND; + if (args.mappable) mmu->type[i].type |= NVIF_MEM_MAPPABLE; + if (args.coherent) mmu->type[i].type |= NVIF_MEM_COHERENT; + if (args.uncached) mmu->type[i].type |= NVIF_MEM_UNCACHED; + mmu->type[i].heap = args.heap; + } + + if (mmu->kind_nr) { + struct nvif_mmu_kind_v0 *kind; + u32 argc = sizeof(*kind) + sizeof(*kind->data) * mmu->kind_nr; + + if (ret = -ENOMEM, !(kind = kmalloc(argc, GFP_KERNEL))) + goto done; + kind->version = 0; + kind->count = mmu->kind_nr; + + ret = nvif_object_mthd(&mmu->object, NVIF_MMU_V0_KIND, + kind, argc); + if (ret == 0) + memcpy(mmu->kind, kind->data, kind->count); + kfree(kind); + } + +done: + if (ret) + nvif_mmu_fini(mmu); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvif/object.c b/drivers/gpu/drm/nouveau/nvif/object.c index c3fb6a20f567..40adfe9b334b 100644 --- a/drivers/gpu/drm/nouveau/nvif/object.c +++ b/drivers/gpu/drm/nouveau/nvif/object.c @@ -166,46 +166,77 @@ nvif_object_mthd(struct nvif_object *object, u32 mthd, void *data, u32 size) } void -nvif_object_unmap(struct nvif_object *object) +nvif_object_unmap_handle(struct nvif_object *object) +{ + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_unmap unmap; + } args = { + .ioctl.type = NVIF_IOCTL_V0_UNMAP, + }; + + nvif_object_ioctl(object, &args, sizeof(args), NULL); +} + +int +nvif_object_map_handle(struct nvif_object *object, void *argv, u32 argc, + u64 *handle, u64 *length) { - if (object->map.size) { - struct nvif_client *client = object->client; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_unmap unmap; - } args = { - .ioctl.type = NVIF_IOCTL_V0_UNMAP, - }; + struct { + struct nvif_ioctl_v0 ioctl; + struct nvif_ioctl_map_v0 map; + } *args; + u32 argn = sizeof(*args) + argc; + int ret, maptype; + + if (!(args = kzalloc(argn, GFP_KERNEL))) + return -ENOMEM; + args->ioctl.type = NVIF_IOCTL_V0_MAP; + memcpy(args->map.data, argv, argc); - if (object->map.ptr) { + ret = nvif_object_ioctl(object, args, argn, NULL); + *handle = args->map.handle; + *length = args->map.length; + maptype = args->map.type; + kfree(args); + return ret ? ret : (maptype == NVIF_IOCTL_MAP_V0_IO); +} + +void +nvif_object_unmap(struct nvif_object *object) +{ + struct nvif_client *client = object->client; + if (object->map.ptr) { + if (object->map.size) { client->driver->unmap(client, object->map.ptr, object->map.size); - object->map.ptr = NULL; + object->map.size = 0; } - - nvif_object_ioctl(object, &args, sizeof(args), NULL); - object->map.size = 0; + object->map.ptr = NULL; + nvif_object_unmap_handle(object); } } int -nvif_object_map(struct nvif_object *object) +nvif_object_map(struct nvif_object *object, void *argv, u32 argc) { struct nvif_client *client = object->client; - struct { - struct nvif_ioctl_v0 ioctl; - struct nvif_ioctl_map_v0 map; - } args = { - .ioctl.type = NVIF_IOCTL_V0_MAP, - }; - int ret = nvif_object_ioctl(object, &args, sizeof(args), NULL); - if (ret == 0) { - object->map.size = args.map.length; - object->map.ptr = client->driver->map(client, args.map.handle, - object->map.size); - if (ret = -ENOMEM, object->map.ptr) + u64 handle, length; + int ret = nvif_object_map_handle(object, argv, argc, &handle, &length); + if (ret >= 0) { + if (ret) { + object->map.ptr = client->driver->map(client, + handle, + length); + if (ret = -ENOMEM, object->map.ptr) { + object->map.size = length; + return 0; + } + } else { + object->map.ptr = (void *)(unsigned long)handle; return 0; - nvif_object_unmap(object); + } + nvif_object_unmap_handle(object); } return ret; } diff --git a/drivers/gpu/drm/nouveau/nvif/vmm.c b/drivers/gpu/drm/nouveau/nvif/vmm.c new file mode 100644 index 000000000000..31cdb2d2e1ff --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvif/vmm.c @@ -0,0 +1,167 @@ +/* + * 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 <nvif/vmm.h> +#include <nvif/mem.h> + +#include <nvif/if000c.h> + +int +nvif_vmm_unmap(struct nvif_vmm *vmm, u64 addr) +{ + return nvif_object_mthd(&vmm->object, NVIF_VMM_V0_UNMAP, + &(struct nvif_vmm_unmap_v0) { .addr = addr }, + sizeof(struct nvif_vmm_unmap_v0)); +} + +int +nvif_vmm_map(struct nvif_vmm *vmm, u64 addr, u64 size, void *argv, u32 argc, + struct nvif_mem *mem, u64 offset) +{ + struct nvif_vmm_map_v0 *args; + u8 stack[16]; + int ret; + + if (sizeof(*args) + argc > sizeof(stack)) { + if (!(args = kmalloc(sizeof(*args) + argc, GFP_KERNEL))) + return -ENOMEM; + } else { + args = (void *)stack; + } + + args->version = 0; + args->addr = addr; + args->size = size; + args->memory = nvif_handle(&mem->object); + args->offset = offset; + memcpy(args->data, argv, argc); + + ret = nvif_object_mthd(&vmm->object, NVIF_VMM_V0_MAP, + args, sizeof(*args) + argc); + if (args != (void *)stack) + kfree(args); + return ret; +} + +void +nvif_vmm_put(struct nvif_vmm *vmm, struct nvif_vma *vma) +{ + if (vma->size) { + WARN_ON(nvif_object_mthd(&vmm->object, NVIF_VMM_V0_PUT, + &(struct nvif_vmm_put_v0) { + .addr = vma->addr, + }, sizeof(struct nvif_vmm_put_v0))); + vma->size = 0; + } +} + +int +nvif_vmm_get(struct nvif_vmm *vmm, enum nvif_vmm_get type, bool sparse, + u8 page, u8 align, u64 size, struct nvif_vma *vma) +{ + struct nvif_vmm_get_v0 args; + int ret; + + args.version = vma->size = 0; + args.sparse = sparse; + args.page = page; + args.align = align; + args.size = size; + + switch (type) { + case ADDR: args.type = NVIF_VMM_GET_V0_ADDR; break; + case PTES: args.type = NVIF_VMM_GET_V0_PTES; break; + case LAZY: args.type = NVIF_VMM_GET_V0_LAZY; break; + default: + WARN_ON(1); + return -EINVAL; + } + + ret = nvif_object_mthd(&vmm->object, NVIF_VMM_V0_GET, + &args, sizeof(args)); + if (ret == 0) { + vma->addr = args.addr; + vma->size = args.size; + } + return ret; +} + +void +nvif_vmm_fini(struct nvif_vmm *vmm) +{ + kfree(vmm->page); + nvif_object_fini(&vmm->object); +} + +int +nvif_vmm_init(struct nvif_mmu *mmu, s32 oclass, u64 addr, u64 size, + void *argv, u32 argc, struct nvif_vmm *vmm) +{ + struct nvif_vmm_v0 *args; + u32 argn = sizeof(*args) + argc; + int ret = -ENOSYS, i; + + vmm->object.client = NULL; + vmm->page = NULL; + + if (!(args = kmalloc(argn, GFP_KERNEL))) + return -ENOMEM; + args->version = 0; + args->addr = addr; + args->size = size; + memcpy(args->data, argv, argc); + + ret = nvif_object_init(&mmu->object, 0, oclass, args, argn, + &vmm->object); + if (ret) + goto done; + + vmm->start = args->addr; + vmm->limit = args->size; + + vmm->page_nr = args->page_nr; + vmm->page = kmalloc(sizeof(*vmm->page) * vmm->page_nr, GFP_KERNEL); + if (!vmm->page) { + ret = -ENOMEM; + goto done; + } + + for (i = 0; i < vmm->page_nr; i++) { + struct nvif_vmm_page_v0 args = { .index = i }; + + ret = nvif_object_mthd(&vmm->object, NVIF_VMM_V0_PAGE, + &args, sizeof(args)); + if (ret) + break; + + vmm->page[i].shift = args.shift; + vmm->page[i].sparse = args.sparse; + vmm->page[i].vram = args.vram; + vmm->page[i].host = args.host; + vmm->page[i].comp = args.comp; + } + +done: + if (ret) + nvif_vmm_fini(vmm); + kfree(args); + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/core/client.c b/drivers/gpu/drm/nouveau/nvkm/core/client.c index 0d3a896892b4..ac671202919e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/client.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/client.c @@ -301,5 +301,7 @@ nvkm_client_new(const char *name, u64 device, const char *cfg, client->debug = nvkm_dbgopt(dbg, "CLIENT"); client->objroot = RB_ROOT; client->ntfy = ntfy; + INIT_LIST_HEAD(&client->umem); + spin_lock_init(&client->lock); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/core/engine.c b/drivers/gpu/drm/nouveau/nvkm/core/engine.c index b6c916954a10..657231c3c098 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/engine.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/engine.c @@ -126,6 +126,15 @@ nvkm_engine_init(struct nvkm_subdev *subdev) return ret; } +static int +nvkm_engine_preinit(struct nvkm_subdev *subdev) +{ + struct nvkm_engine *engine = nvkm_engine(subdev); + if (engine->func->preinit) + engine->func->preinit(engine); + return 0; +} + static void * nvkm_engine_dtor(struct nvkm_subdev *subdev) { @@ -138,6 +147,7 @@ nvkm_engine_dtor(struct nvkm_subdev *subdev) static const struct nvkm_subdev_func nvkm_engine_func = { .dtor = nvkm_engine_dtor, + .preinit = nvkm_engine_preinit, .init = nvkm_engine_init, .fini = nvkm_engine_fini, .intr = nvkm_engine_intr, diff --git a/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c b/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c index a7bd22706b2a..d6de2b3ed2c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/gpuobj.c @@ -42,6 +42,14 @@ nvkm_gpuobj_wr32_fast(struct nvkm_gpuobj *gpuobj, u32 offset, u32 data) } /* accessor functions for gpuobjs allocated directly from instmem */ +static int +nvkm_gpuobj_heap_map(struct nvkm_gpuobj *gpuobj, u64 offset, + struct nvkm_vmm *vmm, struct nvkm_vma *vma, + void *argv, u32 argc) +{ + return nvkm_memory_map(gpuobj->memory, offset, vmm, vma, argv, argc); +} + static u32 nvkm_gpuobj_heap_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) { @@ -67,6 +75,7 @@ nvkm_gpuobj_heap_fast = { .release = nvkm_gpuobj_heap_release, .rd32 = nvkm_gpuobj_rd32_fast, .wr32 = nvkm_gpuobj_wr32_fast, + .map = nvkm_gpuobj_heap_map, }; static const struct nvkm_gpuobj_func @@ -74,6 +83,7 @@ nvkm_gpuobj_heap_slow = { .release = nvkm_gpuobj_heap_release, .rd32 = nvkm_gpuobj_heap_rd32, .wr32 = nvkm_gpuobj_heap_wr32, + .map = nvkm_gpuobj_heap_map, }; static void * @@ -90,9 +100,19 @@ nvkm_gpuobj_heap_acquire(struct nvkm_gpuobj *gpuobj) static const struct nvkm_gpuobj_func nvkm_gpuobj_heap = { .acquire = nvkm_gpuobj_heap_acquire, + .map = nvkm_gpuobj_heap_map, }; /* accessor functions for gpuobjs sub-allocated from a parent gpuobj */ +static int +nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, u64 offset, + struct nvkm_vmm *vmm, struct nvkm_vma *vma, + void *argv, u32 argc) +{ + return nvkm_memory_map(gpuobj->parent, gpuobj->node->offset + offset, + vmm, vma, argv, argc); +} + static u32 nvkm_gpuobj_rd32(struct nvkm_gpuobj *gpuobj, u32 offset) { @@ -118,6 +138,7 @@ nvkm_gpuobj_fast = { .release = nvkm_gpuobj_release, .rd32 = nvkm_gpuobj_rd32_fast, .wr32 = nvkm_gpuobj_wr32_fast, + .map = nvkm_gpuobj_map, }; static const struct nvkm_gpuobj_func @@ -125,6 +146,7 @@ nvkm_gpuobj_slow = { .release = nvkm_gpuobj_release, .rd32 = nvkm_gpuobj_rd32, .wr32 = nvkm_gpuobj_wr32, + .map = nvkm_gpuobj_map, }; static void * @@ -143,6 +165,7 @@ nvkm_gpuobj_acquire(struct nvkm_gpuobj *gpuobj) static const struct nvkm_gpuobj_func nvkm_gpuobj_func = { .acquire = nvkm_gpuobj_acquire, + .map = nvkm_gpuobj_map, }; static int @@ -185,7 +208,7 @@ nvkm_gpuobj_ctor(struct nvkm_device *device, u32 size, int align, bool zero, gpuobj->size = nvkm_memory_size(gpuobj->memory); } - return nvkm_mm_init(&gpuobj->heap, 0, gpuobj->size, 1); + return nvkm_mm_init(&gpuobj->heap, 0, 0, gpuobj->size, 1); } void @@ -196,7 +219,7 @@ nvkm_gpuobj_del(struct nvkm_gpuobj **pgpuobj) if (gpuobj->parent) nvkm_mm_free(&gpuobj->parent->heap, &gpuobj->node); nvkm_mm_fini(&gpuobj->heap); - nvkm_memory_del(&gpuobj->memory); + nvkm_memory_unref(&gpuobj->memory); kfree(*pgpuobj); *pgpuobj = NULL; } @@ -218,26 +241,6 @@ nvkm_gpuobj_new(struct nvkm_device *device, u32 size, int align, bool zero, return ret; } -int -nvkm_gpuobj_map(struct nvkm_gpuobj *gpuobj, struct nvkm_vm *vm, - u32 access, struct nvkm_vma *vma) -{ - struct nvkm_memory *memory = gpuobj->memory; - int ret = nvkm_vm_get(vm, gpuobj->size, 12, access, vma); - if (ret == 0) - nvkm_memory_map(memory, vma, 0); - return ret; -} - -void -nvkm_gpuobj_unmap(struct nvkm_vma *vma) -{ - if (vma->node) { - nvkm_vm_unmap(vma); - nvkm_vm_put(vma); - } -} - /* the below is basically only here to support sharing the paged dma object * for PCI(E)GART on <=nv4x chipsets, and should *not* be expected to work * anywhere else. diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c index be19bbe56bba..d777df5a64e6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ioctl.c @@ -53,7 +53,7 @@ nvkm_ioctl_sclass(struct nvkm_client *client, union { struct nvif_ioctl_sclass_v0 v0; } *args = data; - struct nvkm_oclass oclass; + struct nvkm_oclass oclass = { .client = client }; int ret = -ENOSYS, i = 0; nvif_ioctl(object, "sclass size %d\n", size); @@ -257,13 +257,19 @@ nvkm_ioctl_map(struct nvkm_client *client, union { struct nvif_ioctl_map_v0 v0; } *args = data; + enum nvkm_object_map type; int ret = -ENOSYS; nvif_ioctl(object, "map size %d\n", size); - if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { + if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, true))) { nvif_ioctl(object, "map vers %d\n", args->v0.version); - ret = nvkm_object_map(object, &args->v0.handle, - &args->v0.length); + ret = nvkm_object_map(object, data, size, &type, + &args->v0.handle, + &args->v0.length); + if (type == NVKM_OBJECT_MAP_IO) + args->v0.type = NVIF_IOCTL_MAP_V0_IO; + else + args->v0.type = NVIF_IOCTL_MAP_V0_VA; } return ret; @@ -281,6 +287,7 @@ nvkm_ioctl_unmap(struct nvkm_client *client, nvif_ioctl(object, "unmap size %d\n", size); if (!(ret = nvif_unvers(ret, &data, &size, args->none))) { nvif_ioctl(object, "unmap\n"); + ret = nvkm_object_unmap(object); } return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/core/memory.c b/drivers/gpu/drm/nouveau/nvkm/core/memory.c index 8903c04c977e..e85a08ecd9da 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/memory.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/memory.c @@ -22,27 +22,117 @@ * Authors: Ben Skeggs <bskeggs@redhat.com> */ #include <core/memory.h> +#include <core/mm.h> +#include <subdev/fb.h> #include <subdev/instmem.h> void +nvkm_memory_tags_put(struct nvkm_memory *memory, struct nvkm_device *device, + struct nvkm_tags **ptags) +{ + struct nvkm_fb *fb = device->fb; + struct nvkm_tags *tags = *ptags; + if (tags) { + mutex_lock(&fb->subdev.mutex); + if (refcount_dec_and_test(&tags->refcount)) { + nvkm_mm_free(&fb->tags, &tags->mn); + kfree(memory->tags); + memory->tags = NULL; + } + mutex_unlock(&fb->subdev.mutex); + *ptags = NULL; + } +} + +int +nvkm_memory_tags_get(struct nvkm_memory *memory, struct nvkm_device *device, + u32 nr, void (*clr)(struct nvkm_device *, u32, u32), + struct nvkm_tags **ptags) +{ + struct nvkm_fb *fb = device->fb; + struct nvkm_tags *tags; + + mutex_lock(&fb->subdev.mutex); + if ((tags = memory->tags)) { + /* If comptags exist for the memory, but a different amount + * than requested, the buffer is being mapped with settings + * that are incompatible with existing mappings. + */ + if (tags->mn && tags->mn->length != nr) { + mutex_unlock(&fb->subdev.mutex); + return -EINVAL; + } + + refcount_inc(&tags->refcount); + mutex_unlock(&fb->subdev.mutex); + *ptags = tags; + return 0; + } + + if (!(tags = kmalloc(sizeof(*tags), GFP_KERNEL))) { + mutex_unlock(&fb->subdev.mutex); + return -ENOMEM; + } + + if (!nvkm_mm_head(&fb->tags, 0, 1, nr, nr, 1, &tags->mn)) { + if (clr) + clr(device, tags->mn->offset, tags->mn->length); + } else { + /* Failure to allocate HW comptags is not an error, the + * caller should fall back to an uncompressed map. + * + * As memory can be mapped in multiple places, we still + * need to track the allocation failure and ensure that + * any additional mappings remain uncompressed. + * + * This is handled by returning an empty nvkm_tags. + */ + tags->mn = NULL; + } + + refcount_set(&tags->refcount, 1); + mutex_unlock(&fb->subdev.mutex); + *ptags = tags; + return 0; +} + +void nvkm_memory_ctor(const struct nvkm_memory_func *func, struct nvkm_memory *memory) { memory->func = func; + kref_init(&memory->kref); +} + +static void +nvkm_memory_del(struct kref *kref) +{ + struct nvkm_memory *memory = container_of(kref, typeof(*memory), kref); + if (!WARN_ON(!memory->func)) { + if (memory->func->dtor) + memory = memory->func->dtor(memory); + kfree(memory); + } } void -nvkm_memory_del(struct nvkm_memory **pmemory) +nvkm_memory_unref(struct nvkm_memory **pmemory) { struct nvkm_memory *memory = *pmemory; - if (memory && !WARN_ON(!memory->func)) { - if (memory->func->dtor) - *pmemory = memory->func->dtor(memory); - kfree(*pmemory); + if (memory) { + kref_put(&memory->kref, nvkm_memory_del); *pmemory = NULL; } } +struct nvkm_memory * +nvkm_memory_ref(struct nvkm_memory *memory) +{ + if (memory) + kref_get(&memory->kref); + return memory; +} + int nvkm_memory_new(struct nvkm_device *device, enum nvkm_memory_target target, u64 size, u32 align, bool zero, diff --git a/drivers/gpu/drm/nouveau/nvkm/core/mm.c b/drivers/gpu/drm/nouveau/nvkm/core/mm.c index 5c7891234eea..f78a06a6b2f1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/mm.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/mm.c @@ -237,7 +237,7 @@ nvkm_mm_tail(struct nvkm_mm *mm, u8 heap, u8 type, u32 size_max, u32 size_min, } int -nvkm_mm_init(struct nvkm_mm *mm, u32 offset, u32 length, u32 block) +nvkm_mm_init(struct nvkm_mm *mm, u8 heap, u32 offset, u32 length, u32 block) { struct nvkm_mm_node *node, *prev; u32 next; @@ -274,7 +274,8 @@ nvkm_mm_init(struct nvkm_mm *mm, u32 offset, u32 length, u32 block) list_add_tail(&node->nl_entry, &mm->nodes); list_add_tail(&node->fl_entry, &mm->free); - node->heap = ++mm->heap_nodes; + node->heap = heap; + mm->heap_nodes++; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/core/object.c b/drivers/gpu/drm/nouveau/nvkm/core/object.c index acd76fd4f6d8..301a5e5b5f7f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/object.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/object.c @@ -102,10 +102,19 @@ nvkm_object_ntfy(struct nvkm_object *object, u32 mthd, } int -nvkm_object_map(struct nvkm_object *object, u64 *addr, u32 *size) +nvkm_object_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) { if (likely(object->func->map)) - return object->func->map(object, addr, size); + return object->func->map(object, argv, argc, type, addr, size); + return -ENODEV; +} + +int +nvkm_object_unmap(struct nvkm_object *object) +{ + if (likely(object->func->unmap)) + return object->func->unmap(object); return -ENODEV; } @@ -259,6 +268,7 @@ nvkm_object_dtor(struct nvkm_object *object) } nvif_debug(object, "destroy running...\n"); + nvkm_object_unmap(object); if (object->func->dtor) data = object->func->dtor(object); nvkm_engine_unref(&object->engine); diff --git a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c index e31a0479add0..16299837a296 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/oproxy.c @@ -37,9 +37,17 @@ nvkm_oproxy_ntfy(struct nvkm_object *object, u32 mthd, } static int -nvkm_oproxy_map(struct nvkm_object *object, u64 *addr, u32 *size) +nvkm_oproxy_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) { - return nvkm_object_map(nvkm_oproxy(object)->object, addr, size); + struct nvkm_oproxy *oproxy = nvkm_oproxy(object); + return nvkm_object_map(oproxy->object, argv, argc, type, addr, size); +} + +static int +nvkm_oproxy_unmap(struct nvkm_object *object) +{ + return nvkm_object_unmap(nvkm_oproxy(object)->object); } static int @@ -171,6 +179,7 @@ nvkm_oproxy_func = { .mthd = nvkm_oproxy_mthd, .ntfy = nvkm_oproxy_ntfy, .map = nvkm_oproxy_map, + .unmap = nvkm_oproxy_unmap, .rd08 = nvkm_oproxy_rd08, .rd16 = nvkm_oproxy_rd16, .rd32 = nvkm_oproxy_rd32, diff --git a/drivers/gpu/drm/nouveau/nvkm/core/ramht.c b/drivers/gpu/drm/nouveau/nvkm/core/ramht.c index 89da47234016..ccba4ae73cc5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/core/ramht.c +++ b/drivers/gpu/drm/nouveau/nvkm/core/ramht.c @@ -21,6 +21,7 @@ */ #include <core/ramht.h> #include <core/engine.h> +#include <core/object.h> static u32 nvkm_ramht_hash(struct nvkm_ramht *ramht, int chid, u32 handle) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c b/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c index 8e2e24a74774..44e116f7880d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/bsp/g84.c @@ -39,5 +39,5 @@ int g84_bsp_new(struct nvkm_device *device, int index, struct nvkm_engine **pengine) { return nvkm_xtensa_new_(&g84_bsp, device, index, - true, 0x103000, pengine); + device->chipset != 0x92, 0x103000, pengine); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index e096a5d9c292..e14643615698 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -927,7 +927,7 @@ nv84_chipset = { .i2c = nv50_i2c_new, .imem = nv50_instmem_new, .mc = g84_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g84_pci_new, .therm = g84_therm_new, @@ -959,7 +959,7 @@ nv86_chipset = { .i2c = nv50_i2c_new, .imem = nv50_instmem_new, .mc = g84_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g84_pci_new, .therm = g84_therm_new, @@ -991,7 +991,7 @@ nv92_chipset = { .i2c = nv50_i2c_new, .imem = nv50_instmem_new, .mc = g84_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g92_pci_new, .therm = g84_therm_new, @@ -1023,7 +1023,7 @@ nv94_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = g84_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .therm = g84_therm_new, @@ -1055,7 +1055,7 @@ nv96_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = g84_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .therm = g84_therm_new, @@ -1087,7 +1087,7 @@ nv98_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = g98_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .therm = g84_therm_new, @@ -1119,7 +1119,7 @@ nva0_chipset = { .i2c = nv50_i2c_new, .imem = nv50_instmem_new, .mc = g84_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .therm = g84_therm_new, @@ -1151,7 +1151,7 @@ nva3_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = gt215_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .pmu = gt215_pmu_new, @@ -1185,7 +1185,7 @@ nva5_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = gt215_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .pmu = gt215_pmu_new, @@ -1218,7 +1218,7 @@ nva8_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = gt215_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .pmu = gt215_pmu_new, @@ -1251,7 +1251,7 @@ nvaa_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = g98_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .therm = g84_therm_new, @@ -1283,7 +1283,7 @@ nvac_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = g98_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .therm = g84_therm_new, @@ -1315,7 +1315,7 @@ nvaf_chipset = { .i2c = g94_i2c_new, .imem = nv50_instmem_new, .mc = gt215_mc_new, - .mmu = nv50_mmu_new, + .mmu = g84_mmu_new, .mxm = nv50_mxm_new, .pci = g94_pci_new, .pmu = gt215_pmu_new, @@ -1678,7 +1678,7 @@ nve4_chipset = { .imem = nv50_instmem_new, .ltc = gk104_ltc_new, .mc = gk104_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk104_pmu_new, @@ -1717,7 +1717,7 @@ nve6_chipset = { .imem = nv50_instmem_new, .ltc = gk104_ltc_new, .mc = gk104_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk104_pmu_new, @@ -1756,7 +1756,7 @@ nve7_chipset = { .imem = nv50_instmem_new, .ltc = gk104_ltc_new, .mc = gk104_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk104_pmu_new, @@ -1790,7 +1790,7 @@ nvea_chipset = { .imem = gk20a_instmem_new, .ltc = gk104_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk20a_mmu_new, .pmu = gk20a_pmu_new, .timer = gk20a_timer_new, .top = gk104_top_new, @@ -1820,7 +1820,7 @@ nvf0_chipset = { .imem = nv50_instmem_new, .ltc = gk104_ltc_new, .mc = gk104_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk110_pmu_new, @@ -1858,7 +1858,7 @@ nvf1_chipset = { .imem = nv50_instmem_new, .ltc = gk104_ltc_new, .mc = gk104_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk110_pmu_new, @@ -1896,7 +1896,7 @@ nv106_chipset = { .imem = nv50_instmem_new, .ltc = gk104_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk208_pmu_new, @@ -1934,7 +1934,7 @@ nv108_chipset = { .imem = nv50_instmem_new, .ltc = gk104_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk208_pmu_new, @@ -1958,7 +1958,7 @@ nv108_chipset = { static const struct nvkm_device_chip nv117_chipset = { .name = "GM107", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .clk = gk104_clk_new, @@ -1972,7 +1972,7 @@ nv117_chipset = { .imem = nv50_instmem_new, .ltc = gm107_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gm107_pmu_new, @@ -1992,7 +1992,7 @@ nv117_chipset = { static const struct nvkm_device_chip nv118_chipset = { .name = "GM108", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .clk = gk104_clk_new, @@ -2006,7 +2006,7 @@ nv118_chipset = { .imem = nv50_instmem_new, .ltc = gm107_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gk104_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gm107_pmu_new, @@ -2026,7 +2026,7 @@ nv118_chipset = { static const struct nvkm_device_chip nv120_chipset = { .name = "GM200", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2039,7 +2039,7 @@ nv120_chipset = { .imem = nv50_instmem_new, .ltc = gm200_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gm200_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gm107_pmu_new, @@ -2061,7 +2061,7 @@ nv120_chipset = { static const struct nvkm_device_chip nv124_chipset = { .name = "GM204", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2074,7 +2074,7 @@ nv124_chipset = { .imem = nv50_instmem_new, .ltc = gm200_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gm200_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gm107_pmu_new, @@ -2096,7 +2096,7 @@ nv124_chipset = { static const struct nvkm_device_chip nv126_chipset = { .name = "GM206", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2109,7 +2109,7 @@ nv126_chipset = { .imem = nv50_instmem_new, .ltc = gm200_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gm200_mmu_new, .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gm107_pmu_new, @@ -2131,7 +2131,7 @@ nv126_chipset = { static const struct nvkm_device_chip nv12b_chipset = { .name = "GM20B", - .bar = gk20a_bar_new, + .bar = gm20b_bar_new, .bus = gf100_bus_new, .clk = gm20b_clk_new, .fb = gm20b_fb_new, @@ -2140,7 +2140,7 @@ nv12b_chipset = { .imem = gk20a_instmem_new, .ltc = gm200_ltc_new, .mc = gk20a_mc_new, - .mmu = gf100_mmu_new, + .mmu = gm20b_mmu_new, .pmu = gm20b_pmu_new, .secboot = gm20b_secboot_new, .timer = gk20a_timer_new, @@ -2156,7 +2156,7 @@ nv12b_chipset = { static const struct nvkm_device_chip nv130_chipset = { .name = "GP100", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2168,7 +2168,8 @@ nv130_chipset = { .imem = nv50_instmem_new, .ltc = gp100_ltc_new, .mc = gp100_mc_new, - .mmu = gf100_mmu_new, + .mmu = gp100_mmu_new, + .therm = gp100_therm_new, .secboot = gm200_secboot_new, .pci = gp100_pci_new, .pmu = gp100_pmu_new, @@ -2190,7 +2191,7 @@ nv130_chipset = { static const struct nvkm_device_chip nv132_chipset = { .name = "GP102", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2202,7 +2203,8 @@ nv132_chipset = { .imem = nv50_instmem_new, .ltc = gp100_ltc_new, .mc = gp100_mc_new, - .mmu = gf100_mmu_new, + .mmu = gp100_mmu_new, + .therm = gp100_therm_new, .secboot = gp102_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, @@ -2224,7 +2226,7 @@ nv132_chipset = { static const struct nvkm_device_chip nv134_chipset = { .name = "GP104", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2236,7 +2238,8 @@ nv134_chipset = { .imem = nv50_instmem_new, .ltc = gp100_ltc_new, .mc = gp100_mc_new, - .mmu = gf100_mmu_new, + .mmu = gp100_mmu_new, + .therm = gp100_therm_new, .secboot = gp102_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, @@ -2258,7 +2261,7 @@ nv134_chipset = { static const struct nvkm_device_chip nv136_chipset = { .name = "GP106", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2270,7 +2273,8 @@ nv136_chipset = { .imem = nv50_instmem_new, .ltc = gp100_ltc_new, .mc = gp100_mc_new, - .mmu = gf100_mmu_new, + .mmu = gp100_mmu_new, + .therm = gp100_therm_new, .secboot = gp102_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, @@ -2292,7 +2296,7 @@ nv136_chipset = { static const struct nvkm_device_chip nv137_chipset = { .name = "GP107", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2304,7 +2308,8 @@ nv137_chipset = { .imem = nv50_instmem_new, .ltc = gp100_ltc_new, .mc = gp100_mc_new, - .mmu = gf100_mmu_new, + .mmu = gp100_mmu_new, + .therm = gp100_therm_new, .secboot = gp102_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, @@ -2326,7 +2331,7 @@ nv137_chipset = { static const struct nvkm_device_chip nv138_chipset = { .name = "GP108", - .bar = gf100_bar_new, + .bar = gm107_bar_new, .bios = nvkm_bios_new, .bus = gf100_bus_new, .devinit = gm200_devinit_new, @@ -2338,7 +2343,8 @@ nv138_chipset = { .imem = nv50_instmem_new, .ltc = gp100_ltc_new, .mc = gp100_mc_new, - .mmu = gf100_mmu_new, + .mmu = gp100_mmu_new, + .therm = gp100_therm_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, .timer = gk20a_timer_new, @@ -2355,7 +2361,7 @@ nv138_chipset = { static const struct nvkm_device_chip nv13b_chipset = { .name = "GP10B", - .bar = gk20a_bar_new, + .bar = gm20b_bar_new, .bus = gf100_bus_new, .fb = gp10b_fb_new, .fuse = gm107_fuse_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h index 20249d8e444d..2c3c3ee3c494 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/ctrl.h @@ -1,7 +1,7 @@ #ifndef __NVKM_DEVICE_CTRL_H__ #define __NVKM_DEVICE_CTRL_H__ #define nvkm_control(p) container_of((p), struct nvkm_control, object) -#include <core/device.h> +#include <core/object.h> struct nvkm_control { struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c index 74a1ffa425f7..f302d2b5782a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/pci.c @@ -1627,7 +1627,7 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, const struct nvkm_device_pci_vendor *pciv; const char *name = NULL; struct nvkm_device_pci *pdev; - int ret; + int ret, bits; ret = pci_enable_device(pci_dev); if (ret) @@ -1679,17 +1679,17 @@ nvkm_device_pci_new(struct pci_dev *pci_dev, const char *cfg, const char *dbg, if (ret) return ret; - /* - * Set a preliminary DMA mask based on the .dma_bits member of the - * MMU subdevice. This allows other subdevices to create DMA mappings - * in their init() or oneinit() methods, which may be called before the - * TTM layer sets the DMA mask definitively. - * This is necessary for platforms where the default DMA mask of 32 - * does not cover any system memory, i.e., when all RAM is > 4 GB. - */ - if (pdev->device.mmu) - dma_set_mask_and_coherent(&pci_dev->dev, - DMA_BIT_MASK(pdev->device.mmu->dma_bits)); + /* Set DMA mask based on capabilities reported by the MMU subdev. */ + if (pdev->device.mmu && !pdev->device.pci->agp.bridge) + bits = pdev->device.mmu->dma_bits; + else + bits = 32; + + ret = dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(bits)); + if (ret && bits != 32) { + dma_set_mask_and_coherent(&pci_dev->dev, DMA_BIT_MASK(32)); + pdev->device.mmu->dma_bits = 32; + } return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c index 189ed80e21ff..78597da6313a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/tegra.c @@ -136,7 +136,7 @@ nvkm_device_tegra_probe_iommu(struct nvkm_device_tegra *tdev) if (ret) goto free_domain; - ret = nvkm_mm_init(&tdev->iommu.mm, 0, + ret = nvkm_mm_init(&tdev->iommu.mm, 0, 0, (1ULL << tdev->func->iommu_bit) >> tdev->iommu.pgshift, 1); if (ret) @@ -216,7 +216,7 @@ nvkm_device_tegra_fini(struct nvkm_device *device, bool suspend) if (tdev->irq) { free_irq(tdev->irq, tdev); tdev->irq = 0; - }; + } } static int @@ -309,8 +309,6 @@ nvkm_device_tegra_new(const struct nvkm_device_tegra_func *func, /** * The IOMMU bit defines the upper limit of the GPU-addressable space. - * This will be refined in nouveau_ttm_init but we need to do it early - * for instmem to behave properly */ ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(tdev->func->iommu_bit)); if (ret) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c index 513ee6b79553..17adcb4e8854 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/user.c @@ -206,10 +206,12 @@ nvkm_udevice_wr32(struct nvkm_object *object, u64 addr, u32 data) } static int -nvkm_udevice_map(struct nvkm_object *object, u64 *addr, u32 *size) +nvkm_udevice_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) { struct nvkm_udevice *udev = nvkm_udevice(object); struct nvkm_device *device = udev->device; + *type = NVKM_OBJECT_MAP_IO; *addr = device->func->resource_addr(device, 0); *size = device->func->resource_size(device, 0); return 0; @@ -292,6 +294,11 @@ nvkm_udevice_child_get(struct nvkm_object *object, int index, if (!sclass) { switch (index) { case 0: sclass = &nvkm_control_oclass; break; + case 1: + if (!device->mmu) + return -EINVAL; + sclass = &device->mmu->user; + break; default: return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c index 0c0310498afd..723dcbde2ac2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.c @@ -191,11 +191,13 @@ nv50_disp_chan_ntfy(struct nvkm_object *object, u32 type, } static int -nv50_disp_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) +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 nv50_disp *disp = chan->root->disp; struct nvkm_device *device = disp->base.engine.subdev.device; + *type = NVKM_OBJECT_MAP_IO; *addr = device->func->resource_addr(device, 0) + 0x640000 + (chan->chid.user * 0x1000); *size = 0x001000; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h index 737b38f6fbd2..9bb4ad5b0e57 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/channv50.h @@ -1,6 +1,7 @@ #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_chan { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h index a1e8bf48b778..c9e0a8f7b5d5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/disp/ior.h @@ -147,7 +147,7 @@ void gf119_hda_eld(struct nvkm_ior *, u8 *, u8); #define IOR_MSG(i,l,f,a...) do { \ struct nvkm_ior *_ior = (i); \ - nvkm_##l(&_ior->disp->engine.subdev, "%s: "f, _ior->name, ##a); \ + nvkm_##l(&_ior->disp->engine.subdev, "%s: "f"\n", _ior->name, ##a); \ } 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) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c index c95942ef8216..49ef7e57aad4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/dma/usernv04.c @@ -26,7 +26,7 @@ #include <core/gpuobj.h> #include <subdev/fb.h> -#include <subdev/mmu/nv04.h> +#include <subdev/mmu/vmm.h> #include <nvif/class.h> @@ -49,8 +49,8 @@ nv04_dmaobj_bind(struct nvkm_dmaobj *base, struct nvkm_gpuobj *parent, int ret; if (dmaobj->clone) { - struct nv04_mmu *mmu = nv04_mmu(device->mmu); - struct nvkm_memory *pgt = mmu->vm->pgt[0].mem[0]; + struct nvkm_memory *pgt = + device->mmu->vmm->pd->pt[0]->memory; if (!dmaobj->base.start) return nvkm_gpuobj_wrap(pgt, pgpuobj); nvkm_kmap(pgt); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c index 2e7b4e2105ef..816ccaedfc73 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/falcon.c @@ -99,7 +99,7 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend) const u32 base = falcon->addr; if (!suspend) { - nvkm_memory_del(&falcon->core); + nvkm_memory_unref(&falcon->core); if (falcon->external) { vfree(falcon->data.data); vfree(falcon->code.data); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c index 660ca7aa95ea..64f6b7654a08 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/base.c @@ -27,6 +27,7 @@ #include <core/client.h> #include <core/gpuobj.h> #include <core/notify.h> +#include <subdev/mc.h> #include <nvif/event.h> #include <nvif/unpack.h> @@ -278,6 +279,12 @@ nvkm_fifo_oneinit(struct nvkm_engine *engine) return 0; } +static void +nvkm_fifo_preinit(struct nvkm_engine *engine) +{ + nvkm_mc_reset(engine->subdev.device, NVKM_ENGINE_FIFO); +} + static int nvkm_fifo_init(struct nvkm_engine *engine) { @@ -302,6 +309,7 @@ nvkm_fifo_dtor(struct nvkm_engine *engine) static const struct nvkm_engine_func nvkm_fifo = { .dtor = nvkm_fifo_dtor, + .preinit = nvkm_fifo_preinit, .oneinit = nvkm_fifo_oneinit, .init = nvkm_fifo_init, .fini = nvkm_fifo_fini, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c index fab760ae922f..d83485385934 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chan.c @@ -117,8 +117,8 @@ nvkm_fifo_chan_child_del(struct nvkm_oproxy *base) if (chan->func->engine_dtor) chan->func->engine_dtor(chan, engine); nvkm_object_del(&engn->object); - if (chan->vm) - atomic_dec(&chan->vm->engref[engine->subdev.index]); + if (chan->vmm) + atomic_dec(&chan->vmm->engref[engine->subdev.index]); } } @@ -151,8 +151,8 @@ nvkm_fifo_chan_child_new(const struct nvkm_oclass *oclass, void *data, u32 size, .engine = oclass->engine, }; - if (chan->vm) - atomic_inc(&chan->vm->engref[engine->subdev.index]); + if (chan->vmm) + atomic_inc(&chan->vmm->engref[engine->subdev.index]); if (engine->func->fifo.cclass) { ret = engine->func->fifo.cclass(chan, &cclass, @@ -253,9 +253,11 @@ nvkm_fifo_chan_ntfy(struct nvkm_object *object, u32 type, } static int -nvkm_fifo_chan_map(struct nvkm_object *object, u64 *addr, u32 *size) +nvkm_fifo_chan_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *addr, u64 *size) { struct nvkm_fifo_chan *chan = nvkm_fifo_chan(object); + *type = NVKM_OBJECT_MAP_IO; *addr = chan->addr; *size = chan->size; return 0; @@ -325,7 +327,10 @@ nvkm_fifo_chan_dtor(struct nvkm_object *object) if (chan->user) iounmap(chan->user); - nvkm_vm_ref(NULL, &chan->vm, NULL); + if (chan->vmm) { + nvkm_vmm_part(chan->vmm, chan->inst->memory); + nvkm_vmm_unref(&chan->vmm); + } nvkm_gpuobj_del(&chan->push); nvkm_gpuobj_del(&chan->inst); @@ -347,13 +352,12 @@ nvkm_fifo_chan_func = { int nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, struct nvkm_fifo *fifo, u32 size, u32 align, bool zero, - u64 vm, u64 push, u64 engines, int bar, u32 base, u32 user, - const struct nvkm_oclass *oclass, + u64 hvmm, u64 push, u64 engines, int bar, u32 base, + u32 user, const struct nvkm_oclass *oclass, struct nvkm_fifo_chan *chan) { struct nvkm_client *client = oclass->client; struct nvkm_device *device = fifo->engine.subdev.device; - struct nvkm_mmu *mmu = device->mmu; struct nvkm_dmaobj *dmaobj; unsigned long flags; int ret; @@ -382,16 +386,19 @@ nvkm_fifo_chan_ctor(const struct nvkm_fifo_chan_func *func, } /* channel address space */ - if (!vm && mmu) { - if (!client->vm || client->vm->mmu == mmu) { - ret = nvkm_vm_ref(client->vm, &chan->vm, NULL); - if (ret) - return ret; - } else { + if (hvmm) { + struct nvkm_vmm *vmm = nvkm_uvmm_search(client, hvmm); + if (IS_ERR(vmm)) + return PTR_ERR(vmm); + + if (vmm->mmu != device->mmu) return -EINVAL; - } - } else { - return -ENOENT; + + ret = nvkm_vmm_join(vmm, chan->inst->memory); + if (ret) + return ret; + + chan->vmm = nvkm_vmm_ref(vmm); } /* allocate channel id */ diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c index 61797c4dd07a..a5c998fe4485 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/chang84.c @@ -229,15 +229,18 @@ g84_fifo_chan_func = { }; int -g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, +g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, const struct nvkm_oclass *oclass, struct nv50_fifo_chan *chan) { struct nvkm_device *device = fifo->base.engine.subdev.device; int ret; + if (!vmm) + return -EINVAL; + ret = nvkm_fifo_chan_ctor(&g84_fifo_chan_func, &fifo->base, - 0x10000, 0x1000, false, vm, push, + 0x10000, 0x1000, false, vmm, push, (1ULL << NVKM_ENGINE_BSP) | (1ULL << NVKM_ENGINE_CE0) | (1ULL << NVKM_ENGINE_CIPHER) | @@ -277,9 +280,5 @@ g84_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, if (ret) return ret; - ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); - if (ret) - return ret; - - return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd); + return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h index 7d697e2dce1a..fc1142af02cf 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changf100.h @@ -11,12 +11,9 @@ struct gf100_fifo_chan { struct list_head head; bool killed; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *vm; - struct { struct nvkm_gpuobj *inst; - struct nvkm_vma vma; + struct nvkm_vma *vma; } engn[NVKM_SUBDEV_NR]; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h index 230f64e5f731..5beb5c628473 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/changk104.h @@ -12,12 +12,9 @@ struct gk104_fifo_chan { struct list_head head; bool killed; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *vm; - struct { struct nvkm_gpuobj *inst; - struct nvkm_vma vma; + struct nvkm_vma *vma; } engn[NVKM_SUBDEV_NR]; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c index 25b60aff40e4..85f7dbf53c99 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.c @@ -206,7 +206,6 @@ void * nv50_fifo_chan_dtor(struct nvkm_fifo_chan *base) { struct nv50_fifo_chan *chan = nv50_fifo_chan(base); - nvkm_vm_ref(NULL, &chan->vm, chan->pgd); nvkm_ramht_del(&chan->ramht); nvkm_gpuobj_del(&chan->pgd); nvkm_gpuobj_del(&chan->eng); @@ -229,15 +228,18 @@ nv50_fifo_chan_func = { }; int -nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, +nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vmm, u64 push, const struct nvkm_oclass *oclass, struct nv50_fifo_chan *chan) { struct nvkm_device *device = fifo->base.engine.subdev.device; int ret; + if (!vmm) + return -EINVAL; + ret = nvkm_fifo_chan_ctor(&nv50_fifo_chan_func, &fifo->base, - 0x10000, 0x1000, false, vm, push, + 0x10000, 0x1000, false, vmm, push, (1ULL << NVKM_ENGINE_DMAOBJ) | (1ULL << NVKM_ENGINE_SW) | (1ULL << NVKM_ENGINE_GR) | @@ -262,9 +264,5 @@ nv50_fifo_chan_ctor(struct nv50_fifo *fifo, u64 vm, u64 push, if (ret) return ret; - ret = nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); - if (ret) - return ret; - - return nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd); + return nvkm_ramht_new(device, 0x8000, 16, chan->base.inst, &chan->ramht); } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h index 4b9da469b704..d853056e040b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/channv50.h @@ -13,19 +13,18 @@ struct nv50_fifo_chan { struct nvkm_gpuobj *eng; struct nvkm_gpuobj *pgd; struct nvkm_ramht *ramht; - struct nvkm_vm *vm; struct nvkm_gpuobj *engn[NVKM_SUBDEV_NR]; }; -int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push, +int nv50_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, const struct nvkm_oclass *, struct nv50_fifo_chan *); void *nv50_fifo_chan_dtor(struct nvkm_fifo_chan *); void nv50_fifo_chan_fini(struct nvkm_fifo_chan *); void nv50_fifo_chan_engine_dtor(struct nvkm_fifo_chan *, struct nvkm_engine *); void nv50_fifo_chan_object_dtor(struct nvkm_fifo_chan *, int); -int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vm, u64 push, +int g84_fifo_chan_ctor(struct nv50_fifo *, u64 vmm, u64 push, const struct nvkm_oclass *, struct nv50_fifo_chan *); extern const struct nvkm_fifo_chan_oclass nv50_fifo_dma_oclass; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c index caa914074752..fc34cddcd2f5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmag84.c @@ -44,9 +44,9 @@ g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, nvif_ioctl(parent, "create channel dma size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel dma vers %d vm %llx " + nvif_ioctl(parent, "create channel dma vers %d vmm %llx " "pushbuf %llx offset %016llx\n", - args->v0.version, args->v0.vm, args->v0.pushbuf, + args->v0.version, args->v0.vmm, args->v0.pushbuf, args->v0.offset); if (!args->v0.pushbuf) return -EINVAL; @@ -57,7 +57,7 @@ g84_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return -ENOMEM; *pobject = &chan->base.object; - ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, + ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf, oclass, chan); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c index 0a7b6ed5ed28..c213122cf088 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv04.c @@ -95,6 +95,7 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) nvkm_mask(device, NV04_PFIFO_CACHE1_PULL0, 0x00000001, 0); c = fifo->ramfc; + nvkm_kmap(fctx); do { u32 rm = ((1ULL << c->bits) - 1) << c->regs; u32 cm = ((1ULL << c->bits) - 1) << c->ctxs; @@ -102,6 +103,7 @@ nv04_fifo_dma_fini(struct nvkm_fifo_chan *base) u32 cv = (nvkm_ro32(fctx, c->ctxp + data) & ~cm); nvkm_wo32(fctx, c->ctxp + data, cv | (rv << c->ctxs)); } while ((++c)->bits); + nvkm_done(fctx); c = fifo->ramfc; do { diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c index 480bc3777be5..8043718ad150 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/dmanv50.c @@ -44,9 +44,9 @@ nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, nvif_ioctl(parent, "create channel dma size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel dma vers %d vm %llx " + nvif_ioctl(parent, "create channel dma vers %d vmm %llx " "pushbuf %llx offset %016llx\n", - args->v0.version, args->v0.vm, args->v0.pushbuf, + args->v0.version, args->v0.vmm, args->v0.pushbuf, args->v0.offset); if (!args->v0.pushbuf) return -EINVAL; @@ -57,7 +57,7 @@ nv50_fifo_dma_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return -ENOMEM; *pobject = &chan->base.object; - ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, + ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf, oclass, chan); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c index cd468ab1db12..f69576868164 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.c @@ -559,6 +559,7 @@ gf100_fifo_oneinit(struct nvkm_fifo *base) struct gf100_fifo *fifo = gf100_fifo(base); struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; + struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); int ret; /* Determine number of PBDMAs by checking valid enable bits. */ @@ -584,12 +585,12 @@ gf100_fifo_oneinit(struct nvkm_fifo *base) if (ret) return ret; - ret = nvkm_bar_umap(device->bar, 128 * 0x1000, 12, &fifo->user.bar); + ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem), + &fifo->user.bar); if (ret) return ret; - nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0); - return 0; + return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0); } static void @@ -628,7 +629,7 @@ gf100_fifo_init(struct nvkm_fifo *base) } nvkm_mask(device, 0x002200, 0x00000001, 0x00000001); - nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar.offset >> 12); + nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); nvkm_wr32(device, 0x002100, 0xffffffff); nvkm_wr32(device, 0x002140, 0x7fffffff); @@ -639,10 +640,11 @@ static void * gf100_fifo_dtor(struct nvkm_fifo *base) { struct gf100_fifo *fifo = gf100_fifo(base); - nvkm_vm_put(&fifo->user.bar); - nvkm_memory_del(&fifo->user.mem); - nvkm_memory_del(&fifo->runlist.mem[0]); - nvkm_memory_del(&fifo->runlist.mem[1]); + struct nvkm_device *device = fifo->base.engine.subdev.device; + nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar); + nvkm_memory_unref(&fifo->user.mem); + nvkm_memory_unref(&fifo->runlist.mem[0]); + nvkm_memory_unref(&fifo->runlist.mem[1]); return fifo; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h index 70db58eab9c3..b81a2ad48aa4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gf100.h @@ -26,7 +26,7 @@ struct gf100_fifo { struct { struct nvkm_memory *mem; - struct nvkm_vma bar; + struct nvkm_vma *bar; } user; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c index a7e55c422501..84bd703dd897 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.c @@ -771,6 +771,7 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) struct gk104_fifo *fifo = gk104_fifo(base); struct nvkm_subdev *subdev = &fifo->base.engine.subdev; struct nvkm_device *device = subdev->device; + struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); int engn, runl, pbid, ret, i, j; enum nvkm_devidx engidx; u32 *map; @@ -834,13 +835,12 @@ gk104_fifo_oneinit(struct nvkm_fifo *base) if (ret) return ret; - ret = nvkm_bar_umap(device->bar, fifo->base.nr * 0x200, 12, - &fifo->user.bar); + ret = nvkm_vmm_get(bar, 12, nvkm_memory_size(fifo->user.mem), + &fifo->user.bar); if (ret) return ret; - nvkm_memory_map(fifo->user.mem, &fifo->user.bar, 0); - return 0; + return nvkm_memory_map(fifo->user.mem, 0, bar, fifo->user.bar, NULL, 0); } static void @@ -866,7 +866,7 @@ gk104_fifo_init(struct nvkm_fifo *base) nvkm_wr32(device, 0x04014c + (i * 0x2000), 0xffffffff); /* INTREN */ } - nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar.offset >> 12); + nvkm_wr32(device, 0x002254, 0x10000000 | fifo->user.bar->addr >> 12); nvkm_wr32(device, 0x002100, 0xffffffff); nvkm_wr32(device, 0x002140, 0x7fffffff); @@ -876,14 +876,15 @@ static void * gk104_fifo_dtor(struct nvkm_fifo *base) { struct gk104_fifo *fifo = gk104_fifo(base); + struct nvkm_device *device = fifo->base.engine.subdev.device; int i; - nvkm_vm_put(&fifo->user.bar); - nvkm_memory_del(&fifo->user.mem); + nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &fifo->user.bar); + nvkm_memory_unref(&fifo->user.mem); for (i = 0; i < fifo->runlist_nr; i++) { - nvkm_memory_del(&fifo->runlist[i].mem[1]); - nvkm_memory_del(&fifo->runlist[i].mem[0]); + nvkm_memory_unref(&fifo->runlist[i].mem[1]); + nvkm_memory_unref(&fifo->runlist[i].mem[0]); } return fifo; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h index 44bff98d6725..466f1051f91a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gk104.h @@ -37,7 +37,7 @@ struct gk104_fifo { struct { struct nvkm_memory *mem; - struct nvkm_vma bar; + struct nvkm_vma *bar; } user; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c index 77c2f2a28bf3..2121f517b1dd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifog84.c @@ -45,10 +45,10 @@ g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, nvif_ioctl(parent, "create channel gpfifo size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " + nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " "pushbuf %llx ioffset %016llx " "ilength %08x\n", - args->v0.version, args->v0.vm, args->v0.pushbuf, + args->v0.version, args->v0.vmm, args->v0.pushbuf, args->v0.ioffset, args->v0.ilength); if (!args->v0.pushbuf) return -EINVAL; @@ -59,7 +59,7 @@ g84_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return -ENOMEM; *pobject = &chan->base.object; - ret = g84_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, + ret = g84_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf, oclass, chan); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c index f9e0377d3d24..75f9632789b3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogf100.c @@ -111,7 +111,7 @@ gf100_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, struct nvkm_gpuobj *inst = chan->base.inst; if (offset) { - u64 addr = chan->engn[engine->subdev.index].vma.offset; + u64 addr = chan->engn[engine->subdev.index].vma->addr; nvkm_kmap(inst); nvkm_wo32(inst, offset + 0x00, lower_32_bits(addr) | 4); nvkm_wo32(inst, offset + 0x04, upper_32_bits(addr)); @@ -126,7 +126,7 @@ gf100_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base, struct nvkm_engine *engine) { struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma); + nvkm_vmm_put(chan->base.vmm, &chan->engn[engine->subdev.index].vma); nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst); } @@ -146,8 +146,13 @@ gf100_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, if (ret) return ret; - return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm, - NV_MEM_ACCESS_RW, &chan->engn[engn].vma); + ret = nvkm_vmm_get(chan->base.vmm, 12, chan->engn[engn].inst->size, + &chan->engn[engn].vma); + if (ret) + return ret; + + return nvkm_memory_map(chan->engn[engn].inst, 0, chan->base.vmm, + chan->engn[engn].vma, NULL, 0); } static void @@ -190,10 +195,7 @@ gf100_fifo_gpfifo_init(struct nvkm_fifo_chan *base) static void * gf100_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) { - struct gf100_fifo_chan *chan = gf100_fifo_chan(base); - nvkm_vm_ref(NULL, &chan->vm, chan->pgd); - nvkm_gpuobj_del(&chan->pgd); - return chan; + return gf100_fifo_chan(base); } static const struct nvkm_fifo_chan_func @@ -216,7 +218,6 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, struct fermi_channel_gpfifo_v0 v0; } *args = data; struct gf100_fifo *fifo = gf100_fifo(base); - struct nvkm_device *device = fifo->base.engine.subdev.device; struct nvkm_object *parent = oclass->parent; struct gf100_fifo_chan *chan; u64 usermem, ioffset, ilength; @@ -224,10 +225,12 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, nvif_ioctl(parent, "create channel gpfifo size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " + nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " "ioffset %016llx ilength %08x\n", - args->v0.version, args->v0.vm, args->v0.ioffset, + args->v0.version, args->v0.vmm, args->v0.ioffset, args->v0.ilength); + if (!args->v0.vmm) + return -EINVAL; } else return ret; @@ -239,7 +242,7 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, INIT_LIST_HEAD(&chan->head); ret = nvkm_fifo_chan_ctor(&gf100_fifo_gpfifo_func, &fifo->base, - 0x1000, 0x1000, true, args->v0.vm, 0, + 0x1000, 0x1000, true, args->v0.vmm, 0, (1ULL << NVKM_ENGINE_CE0) | (1ULL << NVKM_ENGINE_CE1) | (1ULL << NVKM_ENGINE_GR) | @@ -247,29 +250,13 @@ gf100_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, (1ULL << NVKM_ENGINE_MSPPP) | (1ULL << NVKM_ENGINE_MSVLD) | (1ULL << NVKM_ENGINE_SW), - 1, fifo->user.bar.offset, 0x1000, + 1, fifo->user.bar->addr, 0x1000, oclass, &chan->base); if (ret) return ret; args->v0.chid = chan->base.chid; - /* page directory */ - ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd); - if (ret) - return ret; - - nvkm_kmap(chan->base.inst); - nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr)); - nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr)); - nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff); - nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff); - nvkm_done(chan->base.inst); - - ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd); - if (ret) - return ret; - /* clear channel control registers */ usermem = chan->base.chid * 0x1000; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c index 8abf6f8ef445..80c87521bebe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifogk104.c @@ -117,7 +117,7 @@ gk104_fifo_gpfifo_engine_init(struct nvkm_fifo_chan *base, u32 offset = gk104_fifo_gpfifo_engine_addr(engine); if (offset) { - u64 addr = chan->engn[engine->subdev.index].vma.offset; + u64 addr = chan->engn[engine->subdev.index].vma->addr; u32 datalo = lower_32_bits(addr) | 0x00000004; u32 datahi = upper_32_bits(addr); nvkm_kmap(inst); @@ -138,7 +138,7 @@ gk104_fifo_gpfifo_engine_dtor(struct nvkm_fifo_chan *base, struct nvkm_engine *engine) { struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - nvkm_gpuobj_unmap(&chan->engn[engine->subdev.index].vma); + nvkm_vmm_put(chan->base.vmm, &chan->engn[engine->subdev.index].vma); nvkm_gpuobj_del(&chan->engn[engine->subdev.index].inst); } @@ -158,8 +158,13 @@ gk104_fifo_gpfifo_engine_ctor(struct nvkm_fifo_chan *base, if (ret) return ret; - return nvkm_gpuobj_map(chan->engn[engn].inst, chan->vm, - NV_MEM_ACCESS_RW, &chan->engn[engn].vma); + ret = nvkm_vmm_get(chan->base.vmm, 12, chan->engn[engn].inst->size, + &chan->engn[engn].vma); + if (ret) + return ret; + + return nvkm_memory_map(chan->engn[engn].inst, 0, chan->base.vmm, + chan->engn[engn].vma, NULL, 0); } static void @@ -203,10 +208,7 @@ gk104_fifo_gpfifo_init(struct nvkm_fifo_chan *base) static void * gk104_fifo_gpfifo_dtor(struct nvkm_fifo_chan *base) { - struct gk104_fifo_chan *chan = gk104_fifo_chan(base); - nvkm_vm_ref(NULL, &chan->vm, chan->pgd); - nvkm_gpuobj_del(&chan->pgd); - return chan; + return gk104_fifo_chan(base); } static const struct nvkm_fifo_chan_func @@ -229,17 +231,19 @@ struct gk104_fifo_chan_func { static int gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func, struct gk104_fifo *fifo, u32 *engmask, u16 *chid, - u64 vm, u64 ioffset, u64 ilength, + u64 vmm, u64 ioffset, u64 ilength, const struct nvkm_oclass *oclass, struct nvkm_object **pobject) { - struct nvkm_device *device = fifo->base.engine.subdev.device; struct gk104_fifo_chan *chan; int runlist = -1, ret = -ENOSYS, i, j; u32 engines = 0, present = 0; u64 subdevs = 0; u64 usermem; + if (!vmm) + return -EINVAL; + /* Determine which downstream engines are present */ for (i = 0; i < fifo->engine_nr; i++) { struct nvkm_engine *engine = fifo->engine[i].engine; @@ -285,30 +289,14 @@ gk104_fifo_gpfifo_new_(const struct gk104_fifo_chan_func *func, INIT_LIST_HEAD(&chan->head); ret = nvkm_fifo_chan_ctor(&gk104_fifo_gpfifo_func, &fifo->base, - 0x1000, 0x1000, true, vm, 0, subdevs, - 1, fifo->user.bar.offset, 0x200, + 0x1000, 0x1000, true, vmm, 0, subdevs, + 1, fifo->user.bar->addr, 0x200, oclass, &chan->base); if (ret) return ret; *chid = chan->base.chid; - /* Page directory. */ - ret = nvkm_gpuobj_new(device, 0x10000, 0x1000, false, NULL, &chan->pgd); - if (ret) - return ret; - - nvkm_kmap(chan->base.inst); - nvkm_wo32(chan->base.inst, 0x0200, lower_32_bits(chan->pgd->addr)); - nvkm_wo32(chan->base.inst, 0x0204, upper_32_bits(chan->pgd->addr)); - nvkm_wo32(chan->base.inst, 0x0208, 0xffffffff); - nvkm_wo32(chan->base.inst, 0x020c, 0x000000ff); - nvkm_done(chan->base.inst); - - ret = nvkm_vm_ref(chan->base.vm, &chan->vm, chan->pgd); - if (ret) - return ret; - /* Clear channel control registers. */ usermem = chan->base.chid * 0x200; ilength = order_base_2(ilength / 8); @@ -373,18 +361,17 @@ gk104_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, nvif_ioctl(parent, "create channel gpfifo size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " + nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " "ioffset %016llx ilength %08x engine %08x\n", - args->v0.version, args->v0.vm, args->v0.ioffset, + args->v0.version, args->v0.vmm, args->v0.ioffset, args->v0.ilength, args->v0.engines); return gk104_fifo_gpfifo_new_(gk104_fifo_gpfifo, fifo, &args->v0.engines, &args->v0.chid, - args->v0.vm, + args->v0.vmm, args->v0.ioffset, args->v0.ilength, oclass, pobject); - } return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c index c5a7de9db259..d8f28ec1e4a8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/gpfifonv50.c @@ -45,10 +45,10 @@ nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, nvif_ioctl(parent, "create channel gpfifo size %d\n", size); if (!(ret = nvif_unpack(ret, &data, &size, args->v0, 0, 0, false))) { - nvif_ioctl(parent, "create channel gpfifo vers %d vm %llx " + nvif_ioctl(parent, "create channel gpfifo vers %d vmm %llx " "pushbuf %llx ioffset %016llx " "ilength %08x\n", - args->v0.version, args->v0.vm, args->v0.pushbuf, + args->v0.version, args->v0.vmm, args->v0.pushbuf, args->v0.ioffset, args->v0.ilength); if (!args->v0.pushbuf) return -EINVAL; @@ -59,7 +59,7 @@ nv50_fifo_gpfifo_new(struct nvkm_fifo *base, const struct nvkm_oclass *oclass, return -ENOMEM; *pobject = &chan->base.object; - ret = nv50_fifo_chan_ctor(fifo, args->v0.vm, args->v0.pushbuf, + ret = nv50_fifo_chan_ctor(fifo, args->v0.vmm, args->v0.pushbuf, oclass, chan); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c index 66eb12c2b5ba..fa6e094d8068 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/fifo/nv50.c @@ -100,8 +100,8 @@ void * nv50_fifo_dtor(struct nvkm_fifo *base) { struct nv50_fifo *fifo = nv50_fifo(base); - nvkm_memory_del(&fifo->runlist[1]); - nvkm_memory_del(&fifo->runlist[0]); + nvkm_memory_unref(&fifo->runlist[1]); + nvkm_memory_unref(&fifo->runlist[0]); return fifo; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c index bc77eea351a5..881015080d83 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.c @@ -986,14 +986,14 @@ gf100_grctx_pack_tpc[] = { ******************************************************************************/ int -gf100_grctx_mmio_data(struct gf100_grctx *info, u32 size, u32 align, u32 access) +gf100_grctx_mmio_data(struct gf100_grctx *info, u32 size, u32 align, bool priv) { if (info->data) { info->buffer[info->buffer_nr] = round_up(info->addr, align); info->addr = info->buffer[info->buffer_nr] + size; info->data->size = size; info->data->align = align; - info->data->access = access; + info->data->priv = priv; info->data++; return info->buffer_nr++; } @@ -1028,9 +1028,8 @@ void gf100_grctx_generate_bundle(struct gf100_grctx *info) { const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); + const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true); mmio_refn(info, 0x408004, 0x00000000, s, b); mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); mmio_refn(info, 0x418808, 0x00000000, s, b); @@ -1041,9 +1040,8 @@ void gf100_grctx_generate_pagepool(struct gf100_grctx *info) { const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); + const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); mmio_refn(info, 0x40800c, 0x00000000, s, b); mmio_wr32(info, 0x408010, 0x80000000); mmio_refn(info, 0x419004, 0x00000000, s, b); @@ -1057,9 +1055,8 @@ gf100_grctx_generate_attrib(struct gf100_grctx *info) const struct gf100_grctx_func *grctx = gr->func->grctx; const u32 attrib = grctx->attrib_nr; const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); - const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); + const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false); int gpc, tpc; u32 bo = 0; @@ -1267,85 +1264,87 @@ gf100_grctx_generate_main(struct gf100_gr *gr, struct gf100_grctx *info) nvkm_mc_unk260(device, 1); } +#define CB_RESERVED 0x80000 + int gf100_grctx_generate(struct gf100_gr *gr) { const struct gf100_grctx_func *grctx = gr->func->grctx; struct nvkm_subdev *subdev = &gr->base.engine.subdev; struct nvkm_device *device = subdev->device; - struct nvkm_memory *chan; + struct nvkm_memory *inst = NULL; + struct nvkm_memory *data = NULL; + struct nvkm_vmm *vmm = NULL; + struct nvkm_vma *ctx = NULL; struct gf100_grctx info; int ret, i; u64 addr; - /* allocate memory to for a "channel", which we'll use to generate - * the default context values + /* Allocate memory to for a "channel", which we'll use to generate + * the default context values. */ - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x80000 + gr->size, - 0x1000, true, &chan); - if (ret) { - nvkm_error(subdev, "failed to allocate chan memory, %d\n", ret); - return ret; - } + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + 0x1000, 0x1000, true, &inst); + if (ret) + goto done; - addr = nvkm_memory_addr(chan); + ret = nvkm_vmm_new(device, 0, 0, NULL, 0, NULL, "grctx", &vmm); + if (ret) + goto done; - /* PGD pointer */ - nvkm_kmap(chan); - nvkm_wo32(chan, 0x0200, lower_32_bits(addr + 0x1000)); - nvkm_wo32(chan, 0x0204, upper_32_bits(addr + 0x1000)); - nvkm_wo32(chan, 0x0208, 0xffffffff); - nvkm_wo32(chan, 0x020c, 0x000000ff); + vmm->debug = subdev->debug; - /* PGT[0] pointer */ - nvkm_wo32(chan, 0x1000, 0x00000000); - nvkm_wo32(chan, 0x1004, 0x00000001 | (addr + 0x2000) >> 8); + ret = nvkm_vmm_join(vmm, inst); + if (ret) + goto done; - /* identity-map the whole "channel" into its own vm */ - for (i = 0; i < nvkm_memory_size(chan) / 4096; i++) { - u64 addr = ((nvkm_memory_addr(chan) + (i * 4096)) >> 8) | 1; - nvkm_wo32(chan, 0x2000 + (i * 8), lower_32_bits(addr)); - nvkm_wo32(chan, 0x2004 + (i * 8), upper_32_bits(addr)); - } + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, + CB_RESERVED + gr->size, 0, true, &data); + if (ret) + goto done; - /* context pointer (virt) */ - nvkm_wo32(chan, 0x0210, 0x00080004); - nvkm_wo32(chan, 0x0214, 0x00000000); - nvkm_done(chan); + ret = nvkm_vmm_get(vmm, 0, nvkm_memory_size(data), &ctx); + if (ret) + goto done; - nvkm_wr32(device, 0x100cb8, (addr + 0x1000) >> 8); - nvkm_wr32(device, 0x100cbc, 0x80000001); - nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x100c80) & 0x00008000) - break; - ); + ret = nvkm_memory_map(data, 0, vmm, ctx, NULL, 0); + if (ret) + goto done; + + + /* Setup context pointer. */ + nvkm_kmap(inst); + nvkm_wo32(inst, 0x0210, lower_32_bits(ctx->addr + CB_RESERVED) | 4); + nvkm_wo32(inst, 0x0214, upper_32_bits(ctx->addr + CB_RESERVED)); + nvkm_done(inst); - /* setup default state for mmio list construction */ + /* Setup default state for mmio list construction. */ info.gr = gr; info.data = gr->mmio_data; info.mmio = gr->mmio_list; - info.addr = 0x2000 + (i * 8); + info.addr = ctx->addr; info.buffer_nr = 0; - /* make channel current */ + /* Make channel current. */ + addr = nvkm_memory_addr(inst) >> 12; if (gr->firmware) { nvkm_wr32(device, 0x409840, 0x00000030); - nvkm_wr32(device, 0x409500, 0x80000000 | addr >> 12); + nvkm_wr32(device, 0x409500, 0x80000000 | addr); nvkm_wr32(device, 0x409504, 0x00000003); nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800) & 0x00000010) break; ); - nvkm_kmap(chan); - nvkm_wo32(chan, 0x8001c, 1); - nvkm_wo32(chan, 0x80020, 0); - nvkm_wo32(chan, 0x80028, 0); - nvkm_wo32(chan, 0x8002c, 0); - nvkm_done(chan); + nvkm_kmap(data); + nvkm_wo32(data, 0x1c, 1); + nvkm_wo32(data, 0x20, 0); + nvkm_wo32(data, 0x28, 0); + nvkm_wo32(data, 0x2c, 0); + nvkm_done(data); } else { nvkm_wr32(device, 0x409840, 0x80000000); - nvkm_wr32(device, 0x409500, 0x80000000 | addr >> 12); + nvkm_wr32(device, 0x409500, 0x80000000 | addr); nvkm_wr32(device, 0x409504, 0x00000001); nvkm_msec(device, 2000, if (nvkm_rd32(device, 0x409800) & 0x80000000) @@ -1355,8 +1354,8 @@ gf100_grctx_generate(struct gf100_gr *gr) grctx->main(gr, &info); - /* trigger a context unload by unsetting the "next channel valid" bit - * and faking a context switch interrupt + /* Trigger a context unload by unsetting the "next channel valid" bit + * and faking a context switch interrupt. */ nvkm_mask(device, 0x409b04, 0x80000000, 0x00000000); nvkm_wr32(device, 0x409000, 0x00000100); @@ -1370,17 +1369,21 @@ gf100_grctx_generate(struct gf100_gr *gr) gr->data = kmalloc(gr->size, GFP_KERNEL); if (gr->data) { - nvkm_kmap(chan); + nvkm_kmap(data); for (i = 0; i < gr->size; i += 4) - gr->data[i / 4] = nvkm_ro32(chan, 0x80000 + i); - nvkm_done(chan); + gr->data[i / 4] = nvkm_ro32(data, CB_RESERVED + i); + nvkm_done(data); ret = 0; } else { ret = -ENOMEM; } done: - nvkm_memory_del(&chan); + nvkm_vmm_put(vmm, &ctx); + nvkm_memory_unref(&data); + nvkm_vmm_part(vmm, inst); + nvkm_vmm_unref(&vmm); + nvkm_memory_unref(&inst); return ret; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h index 017180d147cf..4731e56fbb11 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf100.h @@ -11,7 +11,7 @@ struct gf100_grctx { u64 addr; }; -int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, u32 access); +int gf100_grctx_mmio_data(struct gf100_grctx *, u32 size, u32 align, bool priv); void gf100_grctx_mmio_item(struct gf100_grctx *, u32 addr, u32 data, int s, int); #define mmio_vram(a,b,c,d) gf100_grctx_mmio_data((a), (b), (c), (d)) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c index 505cdcbfc085..82f71b10c06e 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf108.c @@ -735,9 +735,8 @@ gf108_grctx_generate_attrib(struct gf100_grctx *info) const u32 alpha = grctx->alpha_nr; const u32 beta = grctx->attrib_nr; const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); - const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); + const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false); const int timeslice_mode = 1; const int max_batches = 0xffff; u32 bo = 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c index 74a64e3fd59a..19301d88577d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgf117.c @@ -187,9 +187,8 @@ gf117_grctx_generate_attrib(struct gf100_grctx *info) const u32 alpha = grctx->alpha_nr; const u32 beta = grctx->attrib_nr; const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); - const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); + const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false); const int timeslice_mode = 1; const int max_batches = 0xffff; u32 bo = 0; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c index c46b3fdf7203..825c8fd500bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgk104.c @@ -847,9 +847,8 @@ gk104_grctx_generate_bundle(struct gf100_grctx *info) const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, grctx->bundle_size / 0x20); const u32 token_limit = grctx->bundle_token_limit; - const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); + const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true); mmio_refn(info, 0x408004, 0x00000000, s, b); mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); mmio_refn(info, 0x418808, 0x00000000, s, b); @@ -861,9 +860,8 @@ void gk104_grctx_generate_pagepool(struct gf100_grctx *info) { const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); + const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); mmio_refn(info, 0x40800c, 0x00000000, s, b); mmio_wr32(info, 0x408010, 0x80000000); mmio_refn(info, 0x419004, 0x00000000, s, b); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c index 4c4b5ab6e46d..9b43d4ce3eaa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgm107.c @@ -867,9 +867,8 @@ gm107_grctx_generate_bundle(struct gf100_grctx *info) const u32 state_limit = min(grctx->bundle_min_gpm_fifo_depth, grctx->bundle_size / 0x20); const u32 token_limit = grctx->bundle_token_limit; - const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, grctx->bundle_size, (1 << s), access); + const int b = mmio_vram(info, grctx->bundle_size, (1 << s), true); mmio_refn(info, 0x408004, 0x00000000, s, b); mmio_wr32(info, 0x408008, 0x80000000 | (grctx->bundle_size >> s)); mmio_refn(info, 0x418e24, 0x00000000, s, b); @@ -881,9 +880,8 @@ void gm107_grctx_generate_pagepool(struct gf100_grctx *info) { const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); + const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); mmio_refn(info, 0x40800c, 0x00000000, s, b); mmio_wr32(info, 0x408010, 0x80000000); mmio_refn(info, 0x419004, 0x00000000, s, b); @@ -900,9 +898,8 @@ gm107_grctx_generate_attrib(struct gf100_grctx *info) const u32 alpha = grctx->alpha_nr; const u32 attrib = grctx->attrib_nr; const u32 size = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); - const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), access); + const int b = mmio_vram(info, size * gr->tpc_total, (1 << s), false); const int max_batches = 0xffff; u32 bo = 0; u32 ao = bo + grctx->attrib_nr_max * gr->tpc_total; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c index 7833bc777a29..88ea322d956c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp100.c @@ -33,9 +33,8 @@ void gp100_grctx_generate_pagepool(struct gf100_grctx *info) { const struct gf100_grctx_func *grctx = info->gr->func->grctx; - const u32 access = NV_MEM_ACCESS_RW | NV_MEM_ACCESS_SYS; const int s = 8; - const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), access); + const int b = mmio_vram(info, grctx->pagepool_size, (1 << s), true); mmio_refn(info, 0x40800c, 0x00000000, s, b); mmio_wr32(info, 0x408010, 0x80000000); mmio_refn(info, 0x419004, 0x00000000, s, b); @@ -51,9 +50,8 @@ gp100_grctx_generate_attrib(struct gf100_grctx *info) const u32 attrib = grctx->attrib_nr; const u32 pertpc = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); const u32 size = roundup(gr->tpc_total * pertpc, 0x80); - const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size, (1 << s), access); + const int b = mmio_vram(info, size, (1 << s), false); const int max_batches = 0xffff; u32 ao = 0; u32 bo = ao + grctx->alpha_nr_max * gr->tpc_total; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c index 80b7ab0bee3a..7a66b4c2eb18 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/ctxgp102.c @@ -38,9 +38,8 @@ gp102_grctx_generate_attrib(struct gf100_grctx *info) const u32 attrib = grctx->attrib_nr; const u32 pertpc = 0x20 * (grctx->attrib_nr_max + grctx->alpha_nr_max); const u32 size = roundup(gr->tpc_total * pertpc, 0x80); - const u32 access = NV_MEM_ACCESS_RW; const int s = 12; - const int b = mmio_vram(info, size, (1 << s), access); + const int b = mmio_vram(info, size, (1 << s), false); const int max_batches = 0xffff; u32 ao = 0; u32 bo = ao + grctx->alpha_nr_max * gr->tpc_total; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c index 99689f4de502..2f8dc107047d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.c @@ -37,6 +37,7 @@ #include <nvif/class.h> #include <nvif/cl9097.h> +#include <nvif/if900d.h> #include <nvif/unpack.h> /******************************************************************************* @@ -327,13 +328,13 @@ gf100_gr_chan_bind(struct nvkm_object *object, struct nvkm_gpuobj *parent, if (!gr->firmware) { nvkm_wo32(*pgpuobj, 0x00, chan->mmio_nr / 2); - nvkm_wo32(*pgpuobj, 0x04, chan->mmio_vma.offset >> 8); + nvkm_wo32(*pgpuobj, 0x04, chan->mmio_vma->addr >> 8); } else { nvkm_wo32(*pgpuobj, 0xf4, 0); nvkm_wo32(*pgpuobj, 0xf8, 0); nvkm_wo32(*pgpuobj, 0x10, chan->mmio_nr / 2); - nvkm_wo32(*pgpuobj, 0x14, lower_32_bits(chan->mmio_vma.offset)); - nvkm_wo32(*pgpuobj, 0x18, upper_32_bits(chan->mmio_vma.offset)); + nvkm_wo32(*pgpuobj, 0x14, lower_32_bits(chan->mmio_vma->addr)); + nvkm_wo32(*pgpuobj, 0x18, upper_32_bits(chan->mmio_vma->addr)); nvkm_wo32(*pgpuobj, 0x1c, 1); nvkm_wo32(*pgpuobj, 0x20, 0); nvkm_wo32(*pgpuobj, 0x28, 0); @@ -350,18 +351,13 @@ gf100_gr_chan_dtor(struct nvkm_object *object) int i; for (i = 0; i < ARRAY_SIZE(chan->data); i++) { - if (chan->data[i].vma.node) { - nvkm_vm_unmap(&chan->data[i].vma); - nvkm_vm_put(&chan->data[i].vma); - } - nvkm_memory_del(&chan->data[i].mem); + nvkm_vmm_put(chan->vmm, &chan->data[i].vma); + nvkm_memory_unref(&chan->data[i].mem); } - if (chan->mmio_vma.node) { - nvkm_vm_unmap(&chan->mmio_vma); - nvkm_vm_put(&chan->mmio_vma); - } - nvkm_memory_del(&chan->mmio); + nvkm_vmm_put(chan->vmm, &chan->mmio_vma); + nvkm_memory_unref(&chan->mmio); + nvkm_vmm_unref(&chan->vmm); return chan; } @@ -380,6 +376,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, struct gf100_gr_data *data = gr->mmio_data; struct gf100_gr_mmio *mmio = gr->mmio_list; struct gf100_gr_chan *chan; + struct gf100_vmm_map_v0 args = { .priv = 1 }; struct nvkm_device *device = gr->base.engine.subdev.device; int ret, i; @@ -387,6 +384,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, return -ENOMEM; nvkm_object_ctor(&gf100_gr_chan, oclass, &chan->object); chan->gr = gr; + chan->vmm = nvkm_vmm_ref(fifoch->vmm); *pobject = &chan->object; /* allocate memory for a "mmio list" buffer that's used by the HUB @@ -398,12 +396,14 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, if (ret) return ret; - ret = nvkm_vm_get(fifoch->vm, 0x1000, 12, NV_MEM_ACCESS_RW | - NV_MEM_ACCESS_SYS, &chan->mmio_vma); + ret = nvkm_vmm_get(fifoch->vmm, 12, 0x1000, &chan->mmio_vma); if (ret) return ret; - nvkm_memory_map(chan->mmio, &chan->mmio_vma, 0); + ret = nvkm_memory_map(chan->mmio, 0, fifoch->vmm, + chan->mmio_vma, &args, sizeof(args)); + if (ret) + return ret; /* allocate buffers referenced by mmio list */ for (i = 0; data->size && i < ARRAY_SIZE(gr->mmio_data); i++) { @@ -413,13 +413,19 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, if (ret) return ret; - ret = nvkm_vm_get(fifoch->vm, - nvkm_memory_size(chan->data[i].mem), 12, - data->access, &chan->data[i].vma); + ret = nvkm_vmm_get(fifoch->vmm, 12, + nvkm_memory_size(chan->data[i].mem), + &chan->data[i].vma); + if (ret) + return ret; + + args.priv = data->priv; + + ret = nvkm_memory_map(chan->data[i].mem, 0, chan->vmm, + chan->data[i].vma, &args, sizeof(args)); if (ret) return ret; - nvkm_memory_map(chan->data[i].mem, &chan->data[i].vma, 0); data++; } @@ -430,7 +436,7 @@ gf100_gr_chan_new(struct nvkm_gr *base, struct nvkm_fifo_chan *fifoch, u32 data = mmio->data; if (mmio->buffer >= 0) { - u64 info = chan->data[mmio->buffer].vma.offset; + u64 info = chan->data[mmio->buffer].vma->addr; data |= info >> mmio->shift; } @@ -1855,8 +1861,12 @@ gf100_gr_ctor_fw(struct gf100_gr *gr, const char *fwname, int ret; ret = nvkm_firmware_get(device, fwname, &fw); - if (ret) - return gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret); + if (ret) { + ret = gf100_gr_ctor_fw_legacy(gr, fwname, fuc, ret); + if (ret) + return -ENODEV; + return 0; + } fuc->size = fw->size; fuc->data = kmemdup(fw->data, fuc->size, GFP_KERNEL); @@ -1903,25 +1913,33 @@ gf100_gr_new_(const struct gf100_gr_func *func, struct nvkm_device *device, return 0; } +void +gf100_gr_init_gpc_mmu(struct gf100_gr *gr) +{ + struct nvkm_device *device = gr->base.engine.subdev.device; + struct nvkm_fb *fb = device->fb; + + nvkm_wr32(device, 0x418880, nvkm_rd32(device, 0x100c80) & 0x00000001); + nvkm_wr32(device, 0x4188a4, 0x00000000); + nvkm_wr32(device, 0x418888, 0x00000000); + nvkm_wr32(device, 0x41888c, 0x00000000); + nvkm_wr32(device, 0x418890, 0x00000000); + nvkm_wr32(device, 0x418894, 0x00000000); + nvkm_wr32(device, 0x4188b4, nvkm_memory_addr(fb->mmu_wr) >> 8); + nvkm_wr32(device, 0x4188b8, nvkm_memory_addr(fb->mmu_rd) >> 8); +} + int gf100_gr_init(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; - struct nvkm_fb *fb = device->fb; const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); u32 data[TPC_MAX / 8] = {}; u8 tpcnr[GPC_MAX]; int gpc, tpc, rop; int i; - nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x08a4), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x0888), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(fb->mmu_wr) >> 8); - nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(fb->mmu_rd) >> 8); + gr->func->init_gpc_mmu(gr); gf100_gr_mmio(gr, gr->func->mmio); @@ -2036,6 +2054,7 @@ gf100_gr_gpccs_ucode = { static const struct gf100_gr_func gf100_gr = { .init = gf100_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .mmio = gf100_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index a36e45a4a635..d7c2adb9b543 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -45,7 +45,7 @@ struct gf100_gr_data { u32 size; u32 align; - u32 access; + bool priv; }; struct gf100_gr_mmio { @@ -156,18 +156,20 @@ int gp100_gr_init(struct gf100_gr *); void gp100_gr_init_rop_active_fbps(struct gf100_gr *); #define gf100_gr_chan(p) container_of((p), struct gf100_gr_chan, object) +#include <core/object.h> struct gf100_gr_chan { struct nvkm_object object; struct gf100_gr *gr; + struct nvkm_vmm *vmm; struct nvkm_memory *mmio; - struct nvkm_vma mmio_vma; + struct nvkm_vma *mmio_vma; int mmio_nr; struct { struct nvkm_memory *mem; - struct nvkm_vma vma; + struct nvkm_vma *vma; } data[4]; }; @@ -253,6 +255,7 @@ extern const struct gf100_gr_init gf100_gr_init_mpc_0[]; extern const struct gf100_gr_init gf100_gr_init_be_0[]; extern const struct gf100_gr_init gf100_gr_init_fe_1[]; extern const struct gf100_gr_init gf100_gr_init_pe_1[]; +void gf100_gr_init_gpc_mmu(struct gf100_gr *); extern const struct gf100_gr_init gf104_gr_init_ds_0[]; extern const struct gf100_gr_init gf104_gr_init_tex_0[]; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c index d736dcd55ea2..ec0f11983b23 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf104.c @@ -115,6 +115,7 @@ gf104_gr_pack_mmio[] = { static const struct gf100_gr_func gf104_gr = { .init = gf100_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .mmio = gf104_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c index 2f0d24498427..cc152eb74123 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf108.c @@ -106,6 +106,7 @@ gf108_gr_pack_mmio[] = { static const struct gf100_gr_func gf108_gr = { .init = gf100_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .mmio = gf108_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c index d1d942eb86af..10d2d73ca8c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf110.c @@ -87,6 +87,7 @@ gf110_gr_pack_mmio[] = { static const struct gf100_gr_func gf110_gr = { .init = gf100_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .mmio = gf110_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c index 0124e468086e..ac09a07c4150 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf117.c @@ -123,6 +123,7 @@ gf117_gr_gpccs_ucode = { static const struct gf100_gr_func gf117_gr = { .init = gf100_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .mmio = gf117_gr_pack_mmio, .fecs.ucode = &gf117_gr_fecs_ucode, .gpccs.ucode = &gf117_gr_gpccs_ucode, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c index 8d8e4cafe28f..7f449ec6f760 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf119.c @@ -178,6 +178,7 @@ gf119_gr_pack_mmio[] = { static const struct gf100_gr_func gf119_gr = { .init = gf100_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .mmio = gf119_gr_pack_mmio, .fecs.ucode = &gf100_gr_fecs_ucode, .gpccs.ucode = &gf100_gr_gpccs_ucode, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index ec22da6c99fc..5e82f94c2245 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -24,8 +24,6 @@ #include "gf100.h" #include "ctxgf100.h" -#include <subdev/fb.h> - #include <nvif/class.h> /******************************************************************************* @@ -207,21 +205,13 @@ int gk104_gr_init(struct gf100_gr *gr) { struct nvkm_device *device = gr->base.engine.subdev.device; - struct nvkm_fb *fb = device->fb; const u32 magicgpc918 = DIV_ROUND_UP(0x00800000, gr->tpc_total); u32 data[TPC_MAX / 8] = {}; u8 tpcnr[GPC_MAX]; int gpc, tpc, rop; int i; - nvkm_wr32(device, GPC_BCAST(0x0880), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x08a4), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x0888), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x088c), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x0890), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x0894), 0x00000000); - nvkm_wr32(device, GPC_BCAST(0x08b4), nvkm_memory_addr(fb->mmu_wr) >> 8); - nvkm_wr32(device, GPC_BCAST(0x08b8), nvkm_memory_addr(fb->mmu_rd) >> 8); + gr->func->init_gpc_mmu(gr); gf100_gr_mmio(gr, gr->func->mmio); @@ -339,6 +329,7 @@ gk104_gr_gpccs_ucode = { static const struct gf100_gr_func gk104_gr = { .init = gk104_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .mmio = gk104_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index f31b171a4102..a38e19b61c1d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -183,6 +183,7 @@ gk110_gr_gpccs_ucode = { static const struct gf100_gr_func gk110_gr = { .init = gk104_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .mmio = gk110_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c index d76dd178007f..1912c0bfd7ee 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110b.c @@ -103,6 +103,7 @@ gk110b_gr_pack_mmio[] = { static const struct gf100_gr_func gk110b_gr = { .init = gk104_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .mmio = gk110b_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c index 14bbe6ed02a9..1fc258163f25 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk208.c @@ -162,6 +162,7 @@ gk208_gr_gpccs_ucode = { static const struct gf100_gr_func gk208_gr = { .init = gk104_gr_init, + .init_gpc_mmu = gf100_gr_init_gpc_mmu, .init_rop_active_fbps = gk104_gr_init_rop_active_fbps, .init_ppc_exceptions = gk104_gr_init_ppc_exceptions, .mmio = gk208_gr_pack_mmio, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c index d1dc92999dc0..d6840dc81a29 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.c @@ -59,7 +59,7 @@ void * nv20_gr_chan_dtor(struct nvkm_object *object) { struct nv20_gr_chan *chan = nv20_gr_chan(object); - nvkm_memory_del(&chan->inst); + nvkm_memory_unref(&chan->inst); return chan; } @@ -323,7 +323,7 @@ void * nv20_gr_dtor(struct nvkm_gr *base) { struct nv20_gr *gr = nv20_gr(base); - nvkm_memory_del(&gr->ctxtab); + nvkm_memory_unref(&gr->ctxtab); return gr; } diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h index cdf4501e3798..d0cb2b8846ec 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv20.h @@ -19,6 +19,7 @@ void nv20_gr_tile(struct nvkm_gr *, int, struct nvkm_fb_tile *); int nv30_gr_init(struct nvkm_gr *); #define nv20_gr_chan(p) container_of((p), struct nv20_gr_chan, object) +#include <core/object.h> struct nv20_gr_chan { struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h index 2812ed11f877..bee8ef2d5697 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv40.h @@ -16,6 +16,7 @@ void nv40_gr_intr(struct nvkm_gr *); u64 nv40_gr_units(struct nvkm_gr *); #define nv40_gr_chan(p) container_of((p), struct nv40_gr_chan, object) +#include <core/object.h> struct nv40_gr_chan { struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h index 45eec83a5969..1ab6ea436b70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/nv50.h @@ -19,6 +19,7 @@ u64 nv50_gr_units(struct nvkm_gr *); int g84_gr_tlb_flush(struct nvkm_gr *); #define nv50_gr_chan(p) container_of((p), struct nv50_gr_chan, object) +#include <core/object.h> struct nv50_gr_chan { struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h index d3bb34fcdebf..f0d35beb58df 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv31.h @@ -18,6 +18,7 @@ struct nv31_mpeg_func { }; #define nv31_mpeg_chan(p) container_of((p), struct nv31_mpeg_chan, object) +#include <core/object.h> struct nv31_mpeg_chan { struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c index 4e528851e9c0..6df880a39019 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/mpeg/nv50.c @@ -24,6 +24,7 @@ #include "priv.h" #include <core/gpuobj.h> +#include <core/object.h> #include <subdev/timer.h> #include <nvif/class.h> diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h index d7b81cbf82b5..4ff0475e776c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/priv.h @@ -67,6 +67,7 @@ struct nvkm_specdom { }; #define nvkm_perfdom(p) container_of((p), struct nvkm_perfdom, object) +#include <core/object.h> struct nvkm_perfdom { struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h index 6608bf6c6842..b5be49f0ac56 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/chan.h @@ -1,9 +1,11 @@ #ifndef __NVKM_SW_CHAN_H__ #define __NVKM_SW_CHAN_H__ #define nvkm_sw_chan(p) container_of((p), struct nvkm_sw_chan, object) -#include "priv.h" +#include <core/object.h> #include <core/event.h> +#include "priv.h" + struct nvkm_sw_chan { const struct nvkm_sw_chan_func *func; struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h index 943ef4c10091..bcfff62131fe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/sw/nvsw.h @@ -1,7 +1,7 @@ #ifndef __NVKM_NVSW_H__ #define __NVKM_NVSW_H__ #define nvkm_nvsw(p) container_of((p), struct nvkm_nvsw, object) -#include "priv.h" +#include <core/object.h> struct nvkm_nvsw { struct nvkm_object object; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c b/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c index 06bdb67a0205..70549381e082 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/xtensa.c @@ -86,7 +86,7 @@ nvkm_xtensa_fini(struct nvkm_engine *engine, bool suspend) nvkm_wr32(device, base + 0xd94, 0); /* FIFO_CTRL */ if (!suspend) - nvkm_memory_del(&xtensa->gpu_fw); + nvkm_memory_unref(&xtensa->gpu_fw); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c index 1b7f48efd8b1..14be41f24155 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/base.c @@ -60,7 +60,7 @@ nvkm_falcon_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, u8 port, } void -nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *inst) +nvkm_falcon_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *inst) { if (!falcon->func->bind_context) { nvkm_error(falcon->user, diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c index 669c24028470..9def926f24d4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/v1.c @@ -180,7 +180,7 @@ nvkm_falcon_v1_read_dmem(struct nvkm_falcon *falcon, u32 start, u32 size, } static void -nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) +nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_memory *ctx) { u32 inst_loc; u32 fbif; @@ -216,7 +216,7 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) nvkm_falcon_wr32(falcon, fbif + 4 * FALCON_DMAIDX_PHYS_SYS_NCOH, 0x6); /* Set context */ - switch (nvkm_memory_target(ctx->memory)) { + switch (nvkm_memory_target(ctx)) { case NVKM_MEM_TARGET_VRAM: inst_loc = 0; break; case NVKM_MEM_TARGET_HOST: inst_loc = 2; break; case NVKM_MEM_TARGET_NCOH: inst_loc = 3; break; @@ -228,7 +228,7 @@ nvkm_falcon_v1_bind_context(struct nvkm_falcon *falcon, struct nvkm_gpuobj *ctx) /* Enable context */ nvkm_falcon_mask(falcon, 0x048, 0x1, 0x1); nvkm_falcon_wr32(falcon, 0x054, - ((ctx->addr >> 12) & 0xfffffff) | + ((nvkm_memory_addr(ctx) >> 12) & 0xfffffff) | (inst_loc << 28) | (1 << 30)); nvkm_falcon_mask(falcon, 0x090, 0x10000, 0x10000); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild index 1e138b337955..e5830453813d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/Kbuild @@ -3,3 +3,5 @@ nvkm-y += nvkm/subdev/bar/nv50.o nvkm-y += nvkm/subdev/bar/g84.o nvkm-y += nvkm/subdev/bar/gf100.o nvkm-y += nvkm/subdev/bar/gk20a.o +nvkm-y += nvkm/subdev/bar/gm107.o +nvkm-y += nvkm/subdev/bar/gm20b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c index c561d148cebc..9646adec57cb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/base.c @@ -30,39 +30,76 @@ nvkm_bar_flush(struct nvkm_bar *bar) bar->func->flush(bar); } -struct nvkm_vm * -nvkm_bar_kmap(struct nvkm_bar *bar) +struct nvkm_vmm * +nvkm_bar_bar1_vmm(struct nvkm_device *device) { - /* disallow kmap() until after vm has been bootstrapped */ - if (bar && bar->func->kmap && bar->subdev.oneinit) - return bar->func->kmap(bar); + return device->bar->func->bar1.vmm(device->bar); +} + +struct nvkm_vmm * +nvkm_bar_bar2_vmm(struct nvkm_device *device) +{ + /* Denies access to BAR2 when it's not initialised, used by INSTMEM + * to know when object access needs to go through the BAR0 window. + */ + struct nvkm_bar *bar = device->bar; + if (bar && bar->bar2) + return bar->func->bar2.vmm(bar); return NULL; } -int -nvkm_bar_umap(struct nvkm_bar *bar, u64 size, int type, struct nvkm_vma *vma) +void +nvkm_bar_bar2_fini(struct nvkm_device *device) { - return bar->func->umap(bar, size, type, vma); + struct nvkm_bar *bar = device->bar; + if (bar && bar->bar2) { + bar->func->bar2.fini(bar); + bar->bar2 = false; + } +} + +void +nvkm_bar_bar2_init(struct nvkm_device *device) +{ + struct nvkm_bar *bar = device->bar; + if (bar && bar->subdev.oneinit && !bar->bar2 && bar->func->bar2.init) { + bar->func->bar2.init(bar); + bar->func->bar2.wait(bar); + bar->bar2 = true; + } } static int -nvkm_bar_oneinit(struct nvkm_subdev *subdev) +nvkm_bar_fini(struct nvkm_subdev *subdev, bool suspend) { struct nvkm_bar *bar = nvkm_bar(subdev); - return bar->func->oneinit(bar); + bar->func->bar1.fini(bar); + return 0; } static int nvkm_bar_init(struct nvkm_subdev *subdev) { struct nvkm_bar *bar = nvkm_bar(subdev); - return bar->func->init(bar); + bar->func->bar1.init(bar); + bar->func->bar1.wait(bar); + if (bar->func->init) + bar->func->init(bar); + return 0; +} + +static int +nvkm_bar_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_bar *bar = nvkm_bar(subdev); + return bar->func->oneinit(bar); } static void * nvkm_bar_dtor(struct nvkm_subdev *subdev) { struct nvkm_bar *bar = nvkm_bar(subdev); + nvkm_bar_bar2_fini(subdev->device); return bar->func->dtor(bar); } @@ -71,6 +108,7 @@ nvkm_bar = { .dtor = nvkm_bar_dtor, .oneinit = nvkm_bar_oneinit, .init = nvkm_bar_init, + .fini = nvkm_bar_fini, }; void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c index ef717136c838..87f26f54b481 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/g84.c @@ -44,8 +44,14 @@ g84_bar_func = { .dtor = nv50_bar_dtor, .oneinit = nv50_bar_oneinit, .init = nv50_bar_init, - .kmap = nv50_bar_kmap, - .umap = nv50_bar_umap, + .bar1.init = nv50_bar_bar1_init, + .bar1.fini = nv50_bar_bar1_fini, + .bar1.wait = nv50_bar_bar1_wait, + .bar1.vmm = nv50_bar_bar1_vmm, + .bar2.init = nv50_bar_bar2_init, + .bar2.fini = nv50_bar_bar2_fini, + .bar2.wait = nv50_bar_bar1_wait, + .bar2.vmm = nv50_bar_bar2_vmm, .flush = g84_bar_flush, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c index 676c167c95b9..a3ba7f50198b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.c @@ -23,39 +23,73 @@ */ #include "gf100.h" -#include <core/gpuobj.h> +#include <core/memory.h> #include <core/option.h> #include <subdev/fb.h> #include <subdev/mmu.h> -static struct nvkm_vm * -gf100_bar_kmap(struct nvkm_bar *base) +struct nvkm_vmm * +gf100_bar_bar1_vmm(struct nvkm_bar *base) { - return gf100_bar(base)->bar[0].vm; + return gf100_bar(base)->bar[1].vmm; } -int -gf100_bar_umap(struct nvkm_bar *base, u64 size, int type, struct nvkm_vma *vma) +void +gf100_bar_bar1_wait(struct nvkm_bar *base) +{ + /* NFI why it's twice. */ + nvkm_bar_flush(base); + nvkm_bar_flush(base); +} + +void +gf100_bar_bar1_fini(struct nvkm_bar *bar) { + nvkm_mask(bar->subdev.device, 0x001704, 0x80000000, 0x00000000); +} + +void +gf100_bar_bar1_init(struct nvkm_bar *base) +{ + struct nvkm_device *device = base->subdev.device; struct gf100_bar *bar = gf100_bar(base); - return nvkm_vm_get(bar->bar[1].vm, size, type, NV_MEM_ACCESS_RW, vma); + const u32 addr = nvkm_memory_addr(bar->bar[1].inst) >> 12; + nvkm_wr32(device, 0x001704, 0x80000000 | addr); +} + +struct nvkm_vmm * +gf100_bar_bar2_vmm(struct nvkm_bar *base) +{ + return gf100_bar(base)->bar[0].vmm; +} + +void +gf100_bar_bar2_fini(struct nvkm_bar *bar) +{ + nvkm_mask(bar->subdev.device, 0x001714, 0x80000000, 0x00000000); +} + +void +gf100_bar_bar2_init(struct nvkm_bar *base) +{ + struct nvkm_device *device = base->subdev.device; + struct gf100_bar *bar = gf100_bar(base); + u32 addr = nvkm_memory_addr(bar->bar[0].inst) >> 12; + if (bar->bar2_halve) + addr |= 0x40000000; + nvkm_wr32(device, 0x001714, 0x80000000 | addr); } static int -gf100_bar_ctor_vm(struct gf100_bar *bar, struct gf100_bar_vm *bar_vm, - struct lock_class_key *key, int bar_nr) +gf100_bar_oneinit_bar(struct gf100_bar *bar, struct gf100_barN *bar_vm, + struct lock_class_key *key, int bar_nr) { struct nvkm_device *device = bar->base.subdev.device; - struct nvkm_vm *vm; resource_size_t bar_len; int ret; ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, false, - &bar_vm->mem); - if (ret) - return ret; - - ret = nvkm_gpuobj_new(device, 0x8000, 0, false, NULL, &bar_vm->pgd); + &bar_vm->inst); if (ret) return ret; @@ -63,98 +97,64 @@ gf100_bar_ctor_vm(struct gf100_bar *bar, struct gf100_bar_vm *bar_vm, if (bar_nr == 3 && bar->bar2_halve) bar_len >>= 1; - ret = nvkm_vm_new(device, 0, bar_len, 0, key, &vm); + ret = nvkm_vmm_new(device, 0, bar_len, NULL, 0, key, + (bar_nr == 3) ? "bar2" : "bar1", &bar_vm->vmm); if (ret) return ret; - atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); + atomic_inc(&bar_vm->vmm->engref[NVKM_SUBDEV_BAR]); + bar_vm->vmm->debug = bar->base.subdev.debug; /* * Bootstrap page table lookup. */ if (bar_nr == 3) { - ret = nvkm_vm_boot(vm, bar_len); - if (ret) { - nvkm_vm_ref(NULL, &vm, NULL); + ret = nvkm_vmm_boot(bar_vm->vmm); + if (ret) return ret; - } } - ret = nvkm_vm_ref(vm, &bar_vm->vm, bar_vm->pgd); - nvkm_vm_ref(NULL, &vm, NULL); - if (ret) - return ret; - - nvkm_kmap(bar_vm->mem); - nvkm_wo32(bar_vm->mem, 0x0200, lower_32_bits(bar_vm->pgd->addr)); - nvkm_wo32(bar_vm->mem, 0x0204, upper_32_bits(bar_vm->pgd->addr)); - nvkm_wo32(bar_vm->mem, 0x0208, lower_32_bits(bar_len - 1)); - nvkm_wo32(bar_vm->mem, 0x020c, upper_32_bits(bar_len - 1)); - nvkm_done(bar_vm->mem); - return 0; + return nvkm_vmm_join(bar_vm->vmm, bar_vm->inst); } int gf100_bar_oneinit(struct nvkm_bar *base) { static struct lock_class_key bar1_lock; - static struct lock_class_key bar3_lock; + static struct lock_class_key bar2_lock; struct gf100_bar *bar = gf100_bar(base); int ret; - /* BAR3 */ - if (bar->base.func->kmap) { - ret = gf100_bar_ctor_vm(bar, &bar->bar[0], &bar3_lock, 3); + /* BAR2 */ + if (bar->base.func->bar2.init) { + ret = gf100_bar_oneinit_bar(bar, &bar->bar[0], &bar2_lock, 3); if (ret) return ret; + + bar->base.subdev.oneinit = true; + nvkm_bar_bar2_init(bar->base.subdev.device); } /* BAR1 */ - ret = gf100_bar_ctor_vm(bar, &bar->bar[1], &bar1_lock, 1); + ret = gf100_bar_oneinit_bar(bar, &bar->bar[1], &bar1_lock, 1); if (ret) return ret; return 0; } -int -gf100_bar_init(struct nvkm_bar *base) -{ - struct gf100_bar *bar = gf100_bar(base); - struct nvkm_device *device = bar->base.subdev.device; - u32 addr; - - nvkm_mask(device, 0x000200, 0x00000100, 0x00000000); - nvkm_mask(device, 0x000200, 0x00000100, 0x00000100); - - addr = nvkm_memory_addr(bar->bar[1].mem) >> 12; - nvkm_wr32(device, 0x001704, 0x80000000 | addr); - - if (bar->bar[0].mem) { - addr = nvkm_memory_addr(bar->bar[0].mem) >> 12; - if (bar->bar2_halve) - addr |= 0x40000000; - nvkm_wr32(device, 0x001714, 0x80000000 | addr); - } - - return 0; -} - void * gf100_bar_dtor(struct nvkm_bar *base) { struct gf100_bar *bar = gf100_bar(base); - nvkm_vm_ref(NULL, &bar->bar[1].vm, bar->bar[1].pgd); - nvkm_gpuobj_del(&bar->bar[1].pgd); - nvkm_memory_del(&bar->bar[1].mem); + nvkm_vmm_part(bar->bar[1].vmm, bar->bar[1].inst); + nvkm_vmm_unref(&bar->bar[1].vmm); + nvkm_memory_unref(&bar->bar[1].inst); - if (bar->bar[0].vm) { - nvkm_memory_del(&bar->bar[0].vm->pgt[0].mem[0]); - nvkm_vm_ref(NULL, &bar->bar[0].vm, bar->bar[0].pgd); - } - nvkm_gpuobj_del(&bar->bar[0].pgd); - nvkm_memory_del(&bar->bar[0].mem); + nvkm_vmm_part(bar->bar[0].vmm, bar->bar[0].inst); + nvkm_vmm_unref(&bar->bar[0].vmm); + nvkm_memory_unref(&bar->bar[0].inst); return bar; } @@ -175,9 +175,14 @@ static const struct nvkm_bar_func gf100_bar_func = { .dtor = gf100_bar_dtor, .oneinit = gf100_bar_oneinit, - .init = gf100_bar_init, - .kmap = gf100_bar_kmap, - .umap = gf100_bar_umap, + .bar1.init = gf100_bar_bar1_init, + .bar1.fini = gf100_bar_bar1_fini, + .bar1.wait = gf100_bar_bar1_wait, + .bar1.vmm = gf100_bar_bar1_vmm, + .bar2.init = gf100_bar_bar2_init, + .bar2.fini = gf100_bar_bar2_fini, + .bar2.wait = gf100_bar_bar1_wait, + .bar2.vmm = gf100_bar_bar2_vmm, .flush = g84_bar_flush, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h index 20a5255362ba..e4da39139e95 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gf100.h @@ -3,22 +3,24 @@ #define gf100_bar(p) container_of((p), struct gf100_bar, base) #include "priv.h" -struct gf100_bar_vm { - struct nvkm_memory *mem; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *vm; +struct gf100_barN { + struct nvkm_memory *inst; + struct nvkm_vmm *vmm; }; struct gf100_bar { struct nvkm_bar base; bool bar2_halve; - struct gf100_bar_vm bar[2]; + struct gf100_barN bar[2]; }; int gf100_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, int, struct nvkm_bar **); void *gf100_bar_dtor(struct nvkm_bar *); int gf100_bar_oneinit(struct nvkm_bar *); -int gf100_bar_init(struct nvkm_bar *); -int gf100_bar_umap(struct nvkm_bar *, u64, int, struct nvkm_vma *); +void gf100_bar_bar1_init(struct nvkm_bar *); +void gf100_bar_bar1_wait(struct nvkm_bar *); +struct nvkm_vmm *gf100_bar_bar1_vmm(struct nvkm_bar *); +void gf100_bar_bar2_init(struct nvkm_bar *); +struct nvkm_vmm *gf100_bar_bar2_vmm(struct nvkm_bar *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c index 9232fab4274c..b10077d38839 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gk20a.c @@ -25,8 +25,10 @@ static const struct nvkm_bar_func gk20a_bar_func = { .dtor = gf100_bar_dtor, .oneinit = gf100_bar_oneinit, - .init = gf100_bar_init, - .umap = gf100_bar_umap, + .bar1.init = gf100_bar_bar1_init, + .bar1.fini = gf100_bar_bar1_fini, + .bar1.wait = gf100_bar_bar1_wait, + .bar1.vmm = gf100_bar_bar1_vmm, .flush = g84_bar_flush, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm107.c new file mode 100644 index 000000000000..3ddf9222d935 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm107.c @@ -0,0 +1,65 @@ +/* + * 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 "gf100.h" + +#include <subdev/timer.h> + +void +gm107_bar_bar1_wait(struct nvkm_bar *bar) +{ + struct nvkm_device *device = bar->subdev.device; + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x001710) & 0x00000003)) + break; + ); +} + +static void +gm107_bar_bar2_wait(struct nvkm_bar *bar) +{ + struct nvkm_device *device = bar->subdev.device; + nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x001710) & 0x0000000c)) + break; + ); +} + +static const struct nvkm_bar_func +gm107_bar_func = { + .dtor = gf100_bar_dtor, + .oneinit = gf100_bar_oneinit, + .bar1.init = gf100_bar_bar1_init, + .bar1.fini = gf100_bar_bar1_fini, + .bar1.wait = gm107_bar_bar1_wait, + .bar1.vmm = gf100_bar_bar1_vmm, + .bar2.init = gf100_bar_bar2_init, + .bar2.fini = gf100_bar_bar2_fini, + .bar2.wait = gm107_bar_bar2_wait, + .bar2.vmm = gf100_bar_bar2_vmm, + .flush = g84_bar_flush, +}; + +int +gm107_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) +{ + return gf100_bar_new_(&gm107_bar_func, device, index, pbar); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c new file mode 100644 index 000000000000..950bff1955ad --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/gm20b.c @@ -0,0 +1,42 @@ +/* + * 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 "gf100.h" + +static const struct nvkm_bar_func +gm20b_bar_func = { + .dtor = gf100_bar_dtor, + .oneinit = gf100_bar_oneinit, + .bar1.init = gf100_bar_bar1_init, + .bar1.fini = gf100_bar_bar1_fini, + .bar1.wait = gm107_bar_bar1_wait, + .bar1.vmm = gf100_bar_bar1_vmm, + .flush = g84_bar_flush, +}; + +int +gm20b_bar_new(struct nvkm_device *device, int index, struct nvkm_bar **pbar) +{ + int ret = gf100_bar_new_(&gm20b_bar_func, device, index, pbar); + if (ret == 0) + (*pbar)->iomap_uncached = true; + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c index 6eff637ac301..157b076a1272 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.c @@ -28,19 +28,6 @@ #include <subdev/mmu.h> #include <subdev/timer.h> -struct nvkm_vm * -nv50_bar_kmap(struct nvkm_bar *base) -{ - return nv50_bar(base)->bar3_vm; -} - -int -nv50_bar_umap(struct nvkm_bar *base, u64 size, int type, struct nvkm_vma *vma) -{ - struct nv50_bar *bar = nv50_bar(base); - return nvkm_vm_get(bar->bar1_vm, size, type, NV_MEM_ACCESS_RW, vma); -} - static void nv50_bar_flush(struct nvkm_bar *base) { @@ -56,14 +43,72 @@ nv50_bar_flush(struct nvkm_bar *base) spin_unlock_irqrestore(&bar->base.lock, flags); } +struct nvkm_vmm * +nv50_bar_bar1_vmm(struct nvkm_bar *base) +{ + return nv50_bar(base)->bar1_vmm; +} + +void +nv50_bar_bar1_wait(struct nvkm_bar *base) +{ + nvkm_bar_flush(base); +} + +void +nv50_bar_bar1_fini(struct nvkm_bar *bar) +{ + nvkm_wr32(bar->subdev.device, 0x001708, 0x00000000); +} + +void +nv50_bar_bar1_init(struct nvkm_bar *base) +{ + struct nvkm_device *device = base->subdev.device; + struct nv50_bar *bar = nv50_bar(base); + nvkm_wr32(device, 0x001708, 0x80000000 | bar->bar1->node->offset >> 4); +} + +struct nvkm_vmm * +nv50_bar_bar2_vmm(struct nvkm_bar *base) +{ + return nv50_bar(base)->bar2_vmm; +} + +void +nv50_bar_bar2_fini(struct nvkm_bar *bar) +{ + nvkm_wr32(bar->subdev.device, 0x00170c, 0x00000000); +} + +void +nv50_bar_bar2_init(struct nvkm_bar *base) +{ + struct nvkm_device *device = base->subdev.device; + struct nv50_bar *bar = nv50_bar(base); + nvkm_wr32(device, 0x001704, 0x00000000 | bar->mem->addr >> 12); + nvkm_wr32(device, 0x001704, 0x40000000 | bar->mem->addr >> 12); + nvkm_wr32(device, 0x00170c, 0x80000000 | bar->bar2->node->offset >> 4); +} + +void +nv50_bar_init(struct nvkm_bar *base) +{ + struct nv50_bar *bar = nv50_bar(base); + struct nvkm_device *device = bar->base.subdev.device; + int i; + + for (i = 0; i < 8; i++) + nvkm_wr32(device, 0x001900 + (i * 4), 0x00000000); +} + int nv50_bar_oneinit(struct nvkm_bar *base) { struct nv50_bar *bar = nv50_bar(base); struct nvkm_device *device = bar->base.subdev.device; static struct lock_class_key bar1_lock; - static struct lock_class_key bar3_lock; - struct nvkm_vm *vm; + static struct lock_class_key bar2_lock; u64 start, limit; int ret; @@ -80,51 +125,54 @@ nv50_bar_oneinit(struct nvkm_bar *base) if (ret) return ret; - /* BAR3 */ + /* BAR2 */ start = 0x0100000000ULL; limit = start + device->func->resource_size(device, 3); - ret = nvkm_vm_new(device, start, limit - start, start, &bar3_lock, &vm); + ret = nvkm_vmm_new(device, start, limit-- - start, NULL, 0, + &bar2_lock, "bar2", &bar->bar2_vmm); if (ret) return ret; - atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); + atomic_inc(&bar->bar2_vmm->engref[NVKM_SUBDEV_BAR]); + bar->bar2_vmm->debug = bar->base.subdev.debug; - ret = nvkm_vm_boot(vm, limit-- - start); + ret = nvkm_vmm_boot(bar->bar2_vmm); if (ret) return ret; - ret = nvkm_vm_ref(vm, &bar->bar3_vm, bar->pgd); - nvkm_vm_ref(NULL, &vm, NULL); + ret = nvkm_vmm_join(bar->bar2_vmm, bar->mem->memory); if (ret) return ret; - ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar3); + ret = nvkm_gpuobj_new(device, 24, 16, false, bar->mem, &bar->bar2); if (ret) return ret; - nvkm_kmap(bar->bar3); - nvkm_wo32(bar->bar3, 0x00, 0x7fc00000); - nvkm_wo32(bar->bar3, 0x04, lower_32_bits(limit)); - nvkm_wo32(bar->bar3, 0x08, lower_32_bits(start)); - nvkm_wo32(bar->bar3, 0x0c, upper_32_bits(limit) << 24 | + nvkm_kmap(bar->bar2); + nvkm_wo32(bar->bar2, 0x00, 0x7fc00000); + nvkm_wo32(bar->bar2, 0x04, lower_32_bits(limit)); + nvkm_wo32(bar->bar2, 0x08, lower_32_bits(start)); + nvkm_wo32(bar->bar2, 0x0c, upper_32_bits(limit) << 24 | upper_32_bits(start)); - nvkm_wo32(bar->bar3, 0x10, 0x00000000); - nvkm_wo32(bar->bar3, 0x14, 0x00000000); - nvkm_done(bar->bar3); + nvkm_wo32(bar->bar2, 0x10, 0x00000000); + nvkm_wo32(bar->bar2, 0x14, 0x00000000); + nvkm_done(bar->bar2); + + bar->base.subdev.oneinit = true; + nvkm_bar_bar2_init(device); /* BAR1 */ start = 0x0000000000ULL; limit = start + device->func->resource_size(device, 1); - ret = nvkm_vm_new(device, start, limit-- - start, start, &bar1_lock, &vm); - if (ret) - return ret; + ret = nvkm_vmm_new(device, start, limit-- - start, NULL, 0, + &bar1_lock, "bar1", &bar->bar1_vmm); - atomic_inc(&vm->engref[NVKM_SUBDEV_BAR]); + atomic_inc(&bar->bar1_vmm->engref[NVKM_SUBDEV_BAR]); + bar->bar1_vmm->debug = bar->base.subdev.debug; - ret = nvkm_vm_ref(vm, &bar->bar1_vm, bar->pgd); - nvkm_vm_ref(NULL, &vm, NULL); + ret = nvkm_vmm_join(bar->bar1_vmm, bar->mem->memory); if (ret) return ret; @@ -144,45 +192,21 @@ nv50_bar_oneinit(struct nvkm_bar *base) return 0; } -int -nv50_bar_init(struct nvkm_bar *base) -{ - struct nv50_bar *bar = nv50_bar(base); - struct nvkm_device *device = bar->base.subdev.device; - int i; - - nvkm_mask(device, 0x000200, 0x00000100, 0x00000000); - nvkm_mask(device, 0x000200, 0x00000100, 0x00000100); - nvkm_wr32(device, 0x100c80, 0x00060001); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x100c80) & 0x00000001)) - break; - ) < 0) - return -EBUSY; - - nvkm_wr32(device, 0x001704, 0x00000000 | bar->mem->addr >> 12); - nvkm_wr32(device, 0x001704, 0x40000000 | bar->mem->addr >> 12); - nvkm_wr32(device, 0x001708, 0x80000000 | bar->bar1->node->offset >> 4); - nvkm_wr32(device, 0x00170c, 0x80000000 | bar->bar3->node->offset >> 4); - for (i = 0; i < 8; i++) - nvkm_wr32(device, 0x001900 + (i * 4), 0x00000000); - return 0; -} - void * nv50_bar_dtor(struct nvkm_bar *base) { struct nv50_bar *bar = nv50_bar(base); - nvkm_gpuobj_del(&bar->bar1); - nvkm_vm_ref(NULL, &bar->bar1_vm, bar->pgd); - nvkm_gpuobj_del(&bar->bar3); - if (bar->bar3_vm) { - nvkm_memory_del(&bar->bar3_vm->pgt[0].mem[0]); - nvkm_vm_ref(NULL, &bar->bar3_vm, bar->pgd); + if (bar->mem) { + nvkm_gpuobj_del(&bar->bar1); + nvkm_vmm_part(bar->bar1_vmm, bar->mem->memory); + nvkm_vmm_unref(&bar->bar1_vmm); + nvkm_gpuobj_del(&bar->bar2); + nvkm_vmm_part(bar->bar2_vmm, bar->mem->memory); + nvkm_vmm_unref(&bar->bar2_vmm); + nvkm_gpuobj_del(&bar->pgd); + nvkm_gpuobj_del(&bar->pad); + nvkm_gpuobj_del(&bar->mem); } - nvkm_gpuobj_del(&bar->pgd); - nvkm_gpuobj_del(&bar->pad); - nvkm_gpuobj_del(&bar->mem); return bar; } @@ -204,8 +228,14 @@ nv50_bar_func = { .dtor = nv50_bar_dtor, .oneinit = nv50_bar_oneinit, .init = nv50_bar_init, - .kmap = nv50_bar_kmap, - .umap = nv50_bar_umap, + .bar1.init = nv50_bar_bar1_init, + .bar1.fini = nv50_bar_bar1_fini, + .bar1.wait = nv50_bar_bar1_wait, + .bar1.vmm = nv50_bar_bar1_vmm, + .bar2.init = nv50_bar_bar2_init, + .bar2.fini = nv50_bar_bar2_fini, + .bar2.wait = nv50_bar_bar1_wait, + .bar2.vmm = nv50_bar_bar2_vmm, .flush = nv50_bar_flush, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h index 1eb764f22a49..140b76f588b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/nv50.h @@ -9,18 +9,20 @@ struct nv50_bar { struct nvkm_gpuobj *mem; struct nvkm_gpuobj *pad; struct nvkm_gpuobj *pgd; - struct nvkm_vm *bar1_vm; + struct nvkm_vmm *bar1_vmm; struct nvkm_gpuobj *bar1; - struct nvkm_vm *bar3_vm; - struct nvkm_gpuobj *bar3; + struct nvkm_vmm *bar2_vmm; + struct nvkm_gpuobj *bar2; }; int nv50_bar_new_(const struct nvkm_bar_func *, struct nvkm_device *, int, u32 pgd_addr, struct nvkm_bar **); void *nv50_bar_dtor(struct nvkm_bar *); int nv50_bar_oneinit(struct nvkm_bar *); -int nv50_bar_init(struct nvkm_bar *); -struct nvkm_vm *nv50_bar_kmap(struct nvkm_bar *); -int nv50_bar_umap(struct nvkm_bar *, u64, int, struct nvkm_vma *); -void nv50_bar_unmap(struct nvkm_bar *, struct nvkm_vma *); +void nv50_bar_init(struct nvkm_bar *); +void nv50_bar_bar1_init(struct nvkm_bar *); +void nv50_bar_bar1_wait(struct nvkm_bar *); +struct nvkm_vmm *nv50_bar_bar1_vmm(struct nvkm_bar *); +void nv50_bar_bar2_init(struct nvkm_bar *); +struct nvkm_vmm *nv50_bar_bar2_vmm(struct nvkm_bar *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h index d834ef20db5b..14398e2dbdf9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bar/priv.h @@ -9,11 +9,25 @@ void nvkm_bar_ctor(const struct nvkm_bar_func *, struct nvkm_device *, struct nvkm_bar_func { void *(*dtor)(struct nvkm_bar *); int (*oneinit)(struct nvkm_bar *); - int (*init)(struct nvkm_bar *); - struct nvkm_vm *(*kmap)(struct nvkm_bar *); - int (*umap)(struct nvkm_bar *, u64 size, int type, struct nvkm_vma *); + void (*init)(struct nvkm_bar *); + + struct { + void (*init)(struct nvkm_bar *); + void (*fini)(struct nvkm_bar *); + void (*wait)(struct nvkm_bar *); + struct nvkm_vmm *(*vmm)(struct nvkm_bar *); + } bar1, bar2; + void (*flush)(struct nvkm_bar *); }; +void nv50_bar_bar1_fini(struct nvkm_bar *); +void nv50_bar_bar2_fini(struct nvkm_bar *); + void g84_bar_flush(struct nvkm_bar *); + +void gf100_bar_bar1_fini(struct nvkm_bar *); +void gf100_bar_bar2_fini(struct nvkm_bar *); + +void gm107_bar_bar1_wait(struct nvkm_bar *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c index 23caef8df17f..73e463ed55c3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/iccsense.c @@ -99,7 +99,7 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense) rail->extdev_id = nvbios_rd08(bios, entry + 0x1); res_start = 0x5; break; - }; + } if (nvbios_extdev_parse(bios, rail->extdev_id, &extdev)) continue; @@ -115,7 +115,7 @@ nvbios_iccsense_parse(struct nvkm_bios *bios, struct nvbios_iccsense *iccsense) default: rail->resistor_count = 0; break; - }; + } for (r = 0; r < rail->resistor_count; ++r) { rail->resistors[r].mohm = nvbios_rd08(bios, entry + res_start + r * 2); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c index b58ee99f7bfc..9cc10e438b3d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/init.c @@ -36,6 +36,8 @@ #include <subdev/i2c.h> #include <subdev/vga.h> +#include <linux/kernel.h> + #define bioslog(lvl, fmt, args...) do { \ nvkm_printk(init->subdev, lvl, info, "0x%08x[%c]: "fmt, \ init->offset, init_exec(init) ? \ @@ -2271,8 +2273,6 @@ static struct nvbios_init_opcode { [0xaa] = { init_reserved }, }; -#define init_opcode_nr (sizeof(init_opcode) / sizeof(init_opcode[0])) - int nvbios_exec(struct nvbios_init *init) { @@ -2281,7 +2281,8 @@ nvbios_exec(struct nvbios_init *init) init->nested++; while (init->offset) { u8 opcode = nvbios_rd08(bios, init->offset); - if (opcode >= init_opcode_nr || !init_opcode[opcode].exec) { + if (opcode >= ARRAY_SIZE(init_opcode) || + !init_opcode[opcode].exec) { error("unknown opcode 0x%02x\n", opcode); return -EINVAL; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c index 7e83c3985020..20ff5173cf8f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/timing.c @@ -115,16 +115,21 @@ nvbios_timingEp(struct nvkm_bios *bios, int idx, switch (min_t(u8, *hdr, 25)) { case 25: p->timing_10_24 = nvbios_rd08(bios, data + 0x18); + /* fall through */ case 24: case 23: case 22: p->timing_10_21 = nvbios_rd08(bios, data + 0x15); + /* fall through */ case 21: p->timing_10_20 = nvbios_rd08(bios, data + 0x14); + /* fall through */ case 20: p->timing_10_CWL = nvbios_rd08(bios, data + 0x13); + /* fall through */ case 19: p->timing_10_18 = nvbios_rd08(bios, data + 0x12); + /* fall through */ case 18: case 17: p->timing_10_16 = nvbios_rd08(bios, data + 0x10); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c index 158977f8a6e6..c3dae05348eb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv04.c @@ -119,11 +119,11 @@ powerctrl_1_shift(int chip_version, int reg) switch (reg) { case 0x680520: - shift += 4; + shift += 4; /* fall through */ case 0x680508: - shift += 4; + shift += 4; /* fall through */ case 0x680504: - shift += 4; + shift += 4; /* fall through */ case 0x680500: shift += 4; } @@ -245,11 +245,11 @@ setPLL_double_highregs(struct nvkm_devinit *init, u32 reg1, switch (reg1) { case 0x680504: - shift_c040 += 2; + shift_c040 += 2; /* fall through */ case 0x680500: - shift_c040 += 2; + shift_c040 += 2; /* fall through */ case 0x680520: - shift_c040 += 2; + shift_c040 += 2; /* fall through */ case 0x680508: shift_c040 += 2; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c index a7049c041594..73b5d46104bd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/base.c @@ -31,12 +31,6 @@ #include <engine/gr.h> #include <engine/mpeg.h> -bool -nvkm_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype) -{ - return fb->func->memtype_valid(fb, memtype); -} - void nvkm_fb_tile_fini(struct nvkm_fb *fb, int region, struct nvkm_fb_tile *tile) { @@ -100,6 +94,7 @@ static int nvkm_fb_oneinit(struct nvkm_subdev *subdev) { struct nvkm_fb *fb = nvkm_fb(subdev); + u32 tags = 0; if (fb->func->ram_new) { int ret = fb->func->ram_new(fb, &fb->ram); @@ -115,7 +110,16 @@ nvkm_fb_oneinit(struct nvkm_subdev *subdev) return ret; } - return 0; + /* Initialise compression tag allocator. + * + * LTC oneinit() will override this on Fermi and newer. + */ + if (fb->func->tags) { + tags = fb->func->tags(fb); + nvkm_debug(subdev, "%d comptags\n", tags); + } + + return nvkm_mm_init(&fb->tags, 0, 0, tags, 1); } static int @@ -135,8 +139,13 @@ nvkm_fb_init(struct nvkm_subdev *subdev) if (fb->func->init) fb->func->init(fb); - if (fb->func->init_page) - fb->func->init_page(fb); + + if (fb->func->init_page) { + ret = fb->func->init_page(fb); + if (WARN_ON(ret)) + return ret; + } + if (fb->func->init_unkn) fb->func->init_unkn(fb); return 0; @@ -148,12 +157,13 @@ nvkm_fb_dtor(struct nvkm_subdev *subdev) struct nvkm_fb *fb = nvkm_fb(subdev); int i; - nvkm_memory_del(&fb->mmu_wr); - nvkm_memory_del(&fb->mmu_rd); + nvkm_memory_unref(&fb->mmu_wr); + nvkm_memory_unref(&fb->mmu_rd); for (i = 0; i < fb->tile.regions; i++) fb->func->tile.fini(fb, i, &fb->tile.region[i]); + nvkm_mm_fini(&fb->tags); nvkm_ram_del(&fb->ram); if (fb->func->dtor) @@ -176,7 +186,8 @@ nvkm_fb_ctor(const struct nvkm_fb_func *func, struct nvkm_device *device, nvkm_subdev_ctor(&nvkm_fb, device, index, &fb->subdev); fb->func = func; fb->tile.regions = fb->func->tile.regions; - fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", 0); + fb->page = nvkm_longopt(device->cfgopt, "NvFbBigPage", + fb->func->default_bigpage); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c index 9c28392d07e4..06bf95c0c549 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/g84.c @@ -27,6 +27,7 @@ static const struct nv50_fb_func g84_fb = { .ram_new = nv50_ram_new, + .tags = nv20_fb_tags, .trap = 0x001d07ff, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c index a239e73562c8..47d28c279707 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c @@ -27,15 +27,6 @@ #include <core/memory.h> #include <core/option.h> -extern const u8 gf100_pte_storage_type_map[256]; - -bool -gf100_fb_memtype_valid(struct nvkm_fb *fb, u32 tile_flags) -{ - u8 memtype = (tile_flags & 0x0000ff00) >> 8; - return likely((gf100_pte_storage_type_map[memtype] != 0xff)); -} - void gf100_fb_intr(struct nvkm_fb *base) { @@ -80,20 +71,17 @@ gf100_fb_oneinit(struct nvkm_fb *base) return 0; } -void +int gf100_fb_init_page(struct nvkm_fb *fb) { struct nvkm_device *device = fb->subdev.device; switch (fb->page) { - case 16: - nvkm_mask(device, 0x100c80, 0x00000001, 0x00000001); - break; - case 17: + case 16: nvkm_mask(device, 0x100c80, 0x00000001, 0x00000001); break; + case 17: nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); break; default: - nvkm_mask(device, 0x100c80, 0x00000001, 0x00000000); - fb->page = 17; - break; + return -EINVAL; } + return 0; } void @@ -143,7 +131,7 @@ gf100_fb = { .init_page = gf100_fb_init_page, .intr = gf100_fb_intr, .ram_new = gf100_ram_new, - .memtype_valid = gf100_fb_memtype_valid, + .default_bigpage = 17, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h index 412eb89834e8..e3cf0515bb70 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.h @@ -17,7 +17,5 @@ void gf100_fb_intr(struct nvkm_fb *); void gp100_fb_init(struct nvkm_fb *); -void gm200_fb_init_page(struct nvkm_fb *fb); void gm200_fb_init(struct nvkm_fb *base); - #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c index 56af84aa333b..4a9f463745b5 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf108.c @@ -32,7 +32,7 @@ gf108_fb = { .init_page = gf100_fb_init_page, .intr = gf100_fb_intr, .ram_new = gf108_ram_new, - .memtype_valid = gf100_fb_memtype_valid, + .default_bigpage = 17, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c index 4245e2e6e604..0a6e8eaad42c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c @@ -32,7 +32,7 @@ gk104_fb = { .init_page = gf100_fb_init_page, .intr = gf100_fb_intr, .ram_new = gk104_ram_new, - .memtype_valid = gf100_fb_memtype_valid, + .default_bigpage = 17, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c index 5d34d6136616..a7e29b125094 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk20a.c @@ -30,7 +30,7 @@ gk20a_fb = { .init = gf100_fb_init, .init_page = gf100_fb_init_page, .intr = gf100_fb_intr, - .memtype_valid = gf100_fb_memtype_valid, + .default_bigpage = 17, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c index db699025f546..69c876d5d1c1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm107.c @@ -32,7 +32,7 @@ gm107_fb = { .init_page = gf100_fb_init_page, .intr = gf100_fb_intr, .ram_new = gm107_ram_new, - .memtype_valid = gf100_fb_memtype_valid, + .default_bigpage = 17, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c index d83da5ddbc1e..8137e19d3292 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm200.c @@ -26,22 +26,18 @@ #include <core/memory.h> -void +int gm200_fb_init_page(struct nvkm_fb *fb) { struct nvkm_device *device = fb->subdev.device; switch (fb->page) { - case 16: - nvkm_mask(device, 0x100c80, 0x00000801, 0x00000001); - break; - case 17: - nvkm_mask(device, 0x100c80, 0x00000801, 0x00000000); - break; + case 16: nvkm_mask(device, 0x100c80, 0x00001801, 0x00001001); break; + case 17: nvkm_mask(device, 0x100c80, 0x00001801, 0x00000000); break; + case 0: nvkm_mask(device, 0x100c80, 0x00001800, 0x00001800); break; default: - nvkm_mask(device, 0x100c80, 0x00000800, 0x00000800); - fb->page = 0; - break; + return -EINVAL; } + return 0; } void @@ -69,7 +65,7 @@ gm200_fb = { .init_page = gm200_fb_init_page, .intr = gf100_fb_intr, .ram_new = gm200_ram_new, - .memtype_valid = gf100_fb_memtype_valid, + .default_bigpage = 0 /* per-instance. */, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c index b87c233bcd6d..12db61e31128 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gm20b.c @@ -30,7 +30,7 @@ gm20b_fb = { .init = gm200_fb_init, .init_page = gm200_fb_init_page, .intr = gf100_fb_intr, - .memtype_valid = gf100_fb_memtype_valid, + .default_bigpage = 0 /* per-instance. */, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c index 98474aec1921..147f69b30cd8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp100.c @@ -59,7 +59,6 @@ gp100_fb = { .init_page = gm200_fb_init_page, .init_unkn = gp100_fb_init_unkn, .ram_new = gp100_ram_new, - .memtype_valid = gf100_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c index 73b4ae1c73dc..b84b9861ef26 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp102.c @@ -33,7 +33,6 @@ gp102_fb = { .init = gp100_fb_init, .init_page = gm200_fb_init_page, .ram_new = gp100_ram_new, - .memtype_valid = gf100_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c index f2b1fbf428d5..af8e43979dc1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gp10b.c @@ -28,7 +28,6 @@ gp10b_fb = { .init = gm200_fb_init, .init_page = gm200_fb_init_page, .intr = gf100_fb_intr, - .memtype_valid = gf100_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c index ebb30608d5ef..9266559b45f9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gt215.c @@ -27,6 +27,7 @@ static const struct nv50_fb_func gt215_fb = { .ram_new = gt215_ram_new, + .tags = nv20_fb_tags, .trap = 0x000d0fff, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c index 8ff2e5db4571..c886664533c8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv04.c @@ -25,14 +25,6 @@ #include "ram.h" #include "regsnv04.h" -bool -nv04_fb_memtype_valid(struct nvkm_fb *fb, u32 tile_flags) -{ - if (!(tile_flags & 0xff00)) - return true; - return false; -} - static void nv04_fb_init(struct nvkm_fb *fb) { @@ -49,7 +41,6 @@ static const struct nvkm_fb_func nv04_fb = { .init = nv04_fb_init, .ram_new = nv04_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c index e8c44f5a3d84..c998b7e96aa3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv10.c @@ -61,7 +61,6 @@ nv10_fb = { .tile.fini = nv10_fb_tile_fini, .tile.prog = nv10_fb_tile_prog, .ram_new = nv10_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c index 2ae0beb87567..7b9f04f44af8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv1a.c @@ -33,7 +33,6 @@ nv1a_fb = { .tile.fini = nv10_fb_tile_fini, .tile.prog = nv10_fb_tile_prog, .ram_new = nv1a_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c index 126865dfe777..a021d21ff153 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv20.c @@ -45,7 +45,7 @@ nv20_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, { u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40); - if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { + if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!(flags & 2)) tile->zcomp = 0x00000000; /* Z16 */ else tile->zcomp = 0x04000000; /* Z24S8 */ tile->zcomp |= tile->tag->offset; @@ -63,7 +63,7 @@ nv20_fb_tile_fini(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) tile->limit = 0; tile->pitch = 0; tile->zcomp = 0; - nvkm_mm_free(&fb->ram->tags, &tile->tag); + nvkm_mm_free(&fb->tags, &tile->tag); } void @@ -77,15 +77,22 @@ nv20_fb_tile_prog(struct nvkm_fb *fb, int i, struct nvkm_fb_tile *tile) nvkm_wr32(device, 0x100300 + (i * 0x04), tile->zcomp); } +u32 +nv20_fb_tags(struct nvkm_fb *fb) +{ + const u32 tags = nvkm_rd32(fb->subdev.device, 0x100320); + return tags ? tags + 1 : 0; +} + static const struct nvkm_fb_func nv20_fb = { + .tags = nv20_fb_tags, .tile.regions = 8, .tile.init = nv20_fb_tile_init, .tile.comp = nv20_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, .ram_new = nv20_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c index c56746d2a502..7709f5fe9a45 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv25.c @@ -32,7 +32,7 @@ nv25_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, { u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40); - if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { + if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (!(flags & 2)) tile->zcomp = 0x00100000; /* Z16 */ else tile->zcomp = 0x00200000; /* Z24S8 */ tile->zcomp |= tile->tag->offset; @@ -44,13 +44,13 @@ nv25_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, static const struct nvkm_fb_func nv25_fb = { + .tags = nv20_fb_tags, .tile.regions = 8, .tile.init = nv20_fb_tile_init, .tile.comp = nv25_fb_tile_comp, .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, .ram_new = nv20_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c index 2a7c4831b821..8aa782666507 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv30.c @@ -51,7 +51,7 @@ nv30_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, { u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40); - if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { + if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (flags & 2) tile->zcomp |= 0x01000000; /* Z16 */ else tile->zcomp |= 0x02000000; /* Z24S8 */ tile->zcomp |= ((tile->tag->offset ) >> 6); @@ -116,6 +116,7 @@ nv30_fb_init(struct nvkm_fb *fb) static const struct nvkm_fb_func nv30_fb = { + .tags = nv20_fb_tags, .init = nv30_fb_init, .tile.regions = 8, .tile.init = nv30_fb_tile_init, @@ -123,7 +124,6 @@ nv30_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, .ram_new = nv20_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c index 1604b3789ad1..6e83dcff72e0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv35.c @@ -32,7 +32,7 @@ nv35_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, { u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40); - if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { + if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (flags & 2) tile->zcomp |= 0x04000000; /* Z16 */ else tile->zcomp |= 0x08000000; /* Z24S8 */ tile->zcomp |= ((tile->tag->offset ) >> 6); @@ -45,6 +45,7 @@ nv35_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, static const struct nvkm_fb_func nv35_fb = { + .tags = nv20_fb_tags, .init = nv30_fb_init, .tile.regions = 8, .tile.init = nv30_fb_tile_init, @@ -52,7 +53,6 @@ nv35_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, .ram_new = nv20_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c index 80cc0a6e3416..2a07617bb44c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv36.c @@ -32,7 +32,7 @@ nv36_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, { u32 tiles = DIV_ROUND_UP(size, 0x40); u32 tags = round_up(tiles / fb->ram->parts, 0x40); - if (!nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { + if (!nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { if (flags & 2) tile->zcomp |= 0x10000000; /* Z16 */ else tile->zcomp |= 0x20000000; /* Z24S8 */ tile->zcomp |= ((tile->tag->offset ) >> 6); @@ -45,6 +45,7 @@ nv36_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, static const struct nvkm_fb_func nv36_fb = { + .tags = nv20_fb_tags, .init = nv30_fb_init, .tile.regions = 8, .tile.init = nv30_fb_tile_init, @@ -52,7 +53,6 @@ nv36_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, .ram_new = nv20_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c index deec46a310f8..955160778b5b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv40.c @@ -33,7 +33,7 @@ nv40_fb_tile_comp(struct nvkm_fb *fb, int i, u32 size, u32 flags, u32 tiles = DIV_ROUND_UP(size, 0x80); u32 tags = round_up(tiles / fb->ram->parts, 0x100); if ( (flags & 2) && - !nvkm_mm_head(&fb->ram->tags, 0, 1, tags, tags, 1, &tile->tag)) { + !nvkm_mm_head(&fb->tags, 0, 1, tags, tags, 1, &tile->tag)) { tile->zcomp = 0x28000000; /* Z24S8_SPLIT_GRAD */ tile->zcomp |= ((tile->tag->offset ) >> 8); tile->zcomp |= ((tile->tag->offset + tags - 1) >> 8) << 13; @@ -51,6 +51,7 @@ nv40_fb_init(struct nvkm_fb *fb) static const struct nvkm_fb_func nv40_fb = { + .tags = nv20_fb_tags, .init = nv40_fb_init, .tile.regions = 8, .tile.init = nv30_fb_tile_init, @@ -58,7 +59,6 @@ nv40_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv20_fb_tile_prog, .ram_new = nv40_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c index 79e57dd5a00f..b77f08d34cc3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv41.c @@ -45,6 +45,7 @@ nv41_fb_init(struct nvkm_fb *fb) static const struct nvkm_fb_func nv41_fb = { + .tags = nv20_fb_tags, .init = nv41_fb_init, .tile.regions = 12, .tile.init = nv30_fb_tile_init, @@ -52,7 +53,6 @@ nv41_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv41_fb_tile_prog, .ram_new = nv41_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c index 06246cce5ec4..b59dc486083d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv44.c @@ -62,7 +62,6 @@ nv44_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv44_fb_tile_prog, .ram_new = nv44_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c index 3598a1aa65be..cab7d20fa039 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv46.c @@ -48,7 +48,6 @@ nv46_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv44_fb_tile_prog, .ram_new = nv44_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c index c505e4429314..a8b0ad4c871d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv47.c @@ -28,6 +28,7 @@ static const struct nvkm_fb_func nv47_fb = { + .tags = nv20_fb_tags, .init = nv41_fb_init, .tile.regions = 15, .tile.init = nv30_fb_tile_init, @@ -35,7 +36,6 @@ nv47_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv41_fb_tile_prog, .ram_new = nv41_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c index 7b91b9f170e5..d0b317bb0252 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv49.c @@ -28,6 +28,7 @@ static const struct nvkm_fb_func nv49_fb = { + .tags = nv20_fb_tags, .init = nv41_fb_init, .tile.regions = 15, .tile.init = nv30_fb_tile_init, @@ -35,7 +36,6 @@ nv49_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv41_fb_tile_prog, .ram_new = nv49_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c index 4e98210c1b1c..6a6f0c086071 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv4e.c @@ -34,7 +34,6 @@ nv4e_fb = { .tile.fini = nv20_fb_tile_fini, .tile.prog = nv44_fb_tile_prog, .ram_new = nv44_ram_new, - .memtype_valid = nv04_fb_memtype_valid, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c index 0595e0722bfc..b2f5bf8144ea 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.c @@ -28,18 +28,6 @@ #include <core/enum.h> #include <engine/fifo.h> -int -nv50_fb_memtype[0x80] = { - 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, 2, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 2, 2, 2, 2, 2, 2, 2, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 0, 0, - 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 2, 2, 2, 2, - 1, 0, 2, 0, 1, 0, 2, 0, 1, 1, 2, 2, 1, 1, 0, 0 -}; - static int nv50_fb_ram_new(struct nvkm_fb *base, struct nvkm_ram **pram) { @@ -47,12 +35,6 @@ nv50_fb_ram_new(struct nvkm_fb *base, struct nvkm_ram **pram) return fb->func->ram_new(&fb->base, pram); } -static bool -nv50_fb_memtype_valid(struct nvkm_fb *fb, u32 memtype) -{ - return nv50_fb_memtype[(memtype & 0xff00) >> 8] != 0; -} - static const struct nvkm_enum vm_dispatch_subclients[] = { { 0x00000000, "GRCTX" }, { 0x00000001, "NOTIFY" }, @@ -244,6 +226,15 @@ nv50_fb_init(struct nvkm_fb *base) nvkm_wr32(device, 0x100c90, fb->func->trap); } +static u32 +nv50_fb_tags(struct nvkm_fb *base) +{ + struct nv50_fb *fb = nv50_fb(base); + if (fb->func->tags) + return fb->func->tags(&fb->base); + return 0; +} + static void * nv50_fb_dtor(struct nvkm_fb *base) { @@ -262,11 +253,11 @@ nv50_fb_dtor(struct nvkm_fb *base) static const struct nvkm_fb_func nv50_fb_ = { .dtor = nv50_fb_dtor, + .tags = nv50_fb_tags, .oneinit = nv50_fb_oneinit, .init = nv50_fb_init, .intr = nv50_fb_intr, .ram_new = nv50_fb_ram_new, - .memtype_valid = nv50_fb_memtype_valid, }; int @@ -287,6 +278,7 @@ nv50_fb_new_(const struct nv50_fb_func *func, struct nvkm_device *device, static const struct nv50_fb_func nv50_fb = { .ram_new = nv50_ram_new, + .tags = nv20_fb_tags, .trap = 0x000707ff, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h index faa88c8c66fe..13231d4b00d9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/nv50.h @@ -12,10 +12,10 @@ struct nv50_fb { struct nv50_fb_func { int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); + u32 (*tags)(struct nvkm_fb *); u32 trap; }; int nv50_fb_new_(const struct nv50_fb_func *, struct nvkm_device *, int index, struct nvkm_fb **pfb); -extern int nv50_fb_memtype[0x80]; #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index e905d44fa1d5..e05d95240e85 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -6,9 +6,10 @@ struct nvkm_bios; struct nvkm_fb_func { void *(*dtor)(struct nvkm_fb *); + u32 (*tags)(struct nvkm_fb *); int (*oneinit)(struct nvkm_fb *); void (*init)(struct nvkm_fb *); - void (*init_page)(struct nvkm_fb *); + int (*init_page)(struct nvkm_fb *); void (*init_unkn)(struct nvkm_fb *); void (*intr)(struct nvkm_fb *); @@ -24,7 +25,7 @@ struct nvkm_fb_func { int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); - bool (*memtype_valid)(struct nvkm_fb *, u32 memtype); + u8 default_bigpage; }; void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, @@ -33,13 +34,12 @@ int nvkm_fb_new_(const struct nvkm_fb_func *, struct nvkm_device *device, int index, struct nvkm_fb **); int nvkm_fb_bios_memtype(struct nvkm_bios *); -bool nv04_fb_memtype_valid(struct nvkm_fb *, u32 memtype); - void nv10_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *); void nv10_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); void nv10_fb_tile_prog(struct nvkm_fb *, int, struct nvkm_fb_tile *); +u32 nv20_fb_tags(struct nvkm_fb *); void nv20_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *); void nv20_fb_tile_fini(struct nvkm_fb *, int i, struct nvkm_fb_tile *); @@ -62,8 +62,7 @@ void nv46_fb_tile_init(struct nvkm_fb *, int i, u32 addr, u32 size, u32 pitch, u32 flags, struct nvkm_fb_tile *); int gf100_fb_oneinit(struct nvkm_fb *); -void gf100_fb_init_page(struct nvkm_fb *); -bool gf100_fb_memtype_valid(struct nvkm_fb *, u32); +int gf100_fb_init_page(struct nvkm_fb *); -void gm200_fb_init_page(struct nvkm_fb *); +int gm200_fb_init_page(struct nvkm_fb *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c index c17d559dbfbe..24c7bd505731 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.c @@ -21,8 +21,132 @@ * * Authors: Ben Skeggs <bskeggs@redhat.com> */ +#define nvkm_vram(p) container_of((p), struct nvkm_vram, memory) #include "ram.h" +#include <core/memory.h> +#include <subdev/mmu.h> + +struct nvkm_vram { + struct nvkm_memory memory; + struct nvkm_ram *ram; + u8 page; + struct nvkm_mm_node *mn; +}; + +static int +nvkm_vram_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, + struct nvkm_vma *vma, void *argv, u32 argc) +{ + struct nvkm_vram *vram = nvkm_vram(memory); + struct nvkm_vmm_map map = { + .memory = &vram->memory, + .offset = offset, + .mem = vram->mn, + }; + + return nvkm_vmm_map(vmm, vma, argv, argc, &map); +} + +static u64 +nvkm_vram_size(struct nvkm_memory *memory) +{ + return (u64)nvkm_mm_size(nvkm_vram(memory)->mn) << NVKM_RAM_MM_SHIFT; +} + +static u64 +nvkm_vram_addr(struct nvkm_memory *memory) +{ + struct nvkm_vram *vram = nvkm_vram(memory); + if (!nvkm_mm_contiguous(vram->mn)) + return ~0ULL; + return (u64)nvkm_mm_addr(vram->mn) << NVKM_RAM_MM_SHIFT; +} + +static u8 +nvkm_vram_page(struct nvkm_memory *memory) +{ + return nvkm_vram(memory)->page; +} + +static enum nvkm_memory_target +nvkm_vram_target(struct nvkm_memory *memory) +{ + return NVKM_MEM_TARGET_VRAM; +} + +static void * +nvkm_vram_dtor(struct nvkm_memory *memory) +{ + struct nvkm_vram *vram = nvkm_vram(memory); + struct nvkm_mm_node *next = vram->mn; + struct nvkm_mm_node *node; + mutex_lock(&vram->ram->fb->subdev.mutex); + while ((node = next)) { + next = node->next; + nvkm_mm_free(&vram->ram->vram, &node); + } + mutex_unlock(&vram->ram->fb->subdev.mutex); + return vram; +} + +static const struct nvkm_memory_func +nvkm_vram = { + .dtor = nvkm_vram_dtor, + .target = nvkm_vram_target, + .page = nvkm_vram_page, + .addr = nvkm_vram_addr, + .size = nvkm_vram_size, + .map = nvkm_vram_map, +}; + +int +nvkm_ram_get(struct nvkm_device *device, u8 heap, u8 type, u8 rpage, u64 size, + bool contig, bool back, struct nvkm_memory **pmemory) +{ + struct nvkm_ram *ram; + struct nvkm_mm *mm; + struct nvkm_mm_node **node, *r; + struct nvkm_vram *vram; + u8 page = max(rpage, (u8)NVKM_RAM_MM_SHIFT); + u32 align = (1 << page) >> NVKM_RAM_MM_SHIFT; + u32 max = ALIGN(size, 1 << page) >> NVKM_RAM_MM_SHIFT; + u32 min = contig ? max : align; + int ret; + + if (!device->fb || !(ram = device->fb->ram)) + return -ENODEV; + ram = device->fb->ram; + mm = &ram->vram; + + if (!(vram = kzalloc(sizeof(*vram), GFP_KERNEL))) + return -ENOMEM; + nvkm_memory_ctor(&nvkm_vram, &vram->memory); + vram->ram = ram; + vram->page = page; + *pmemory = &vram->memory; + + mutex_lock(&ram->fb->subdev.mutex); + node = &vram->mn; + do { + if (back) + ret = nvkm_mm_tail(mm, heap, type, max, min, align, &r); + else + ret = nvkm_mm_head(mm, heap, type, max, min, align, &r); + if (ret) { + mutex_unlock(&ram->fb->subdev.mutex); + nvkm_memory_unref(pmemory); + return ret; + } + + *node = r; + node = &r->next; + max -= r->length; + } while (max); + mutex_unlock(&ram->fb->subdev.mutex); + return 0; +} + int nvkm_ram_init(struct nvkm_ram *ram) { @@ -38,7 +162,6 @@ nvkm_ram_del(struct nvkm_ram **pram) if (ram && !WARN_ON(!ram->func)) { if (ram->func->dtor) *pram = ram->func->dtor(ram); - nvkm_mm_fini(&ram->tags); nvkm_mm_fini(&ram->vram); kfree(*pram); *pram = NULL; @@ -47,8 +170,7 @@ nvkm_ram_del(struct nvkm_ram **pram) int nvkm_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, - enum nvkm_ram_type type, u64 size, u32 tags, - struct nvkm_ram *ram) + enum nvkm_ram_type type, u64 size, struct nvkm_ram *ram) { static const char *name[] = { [NVKM_RAM_TYPE_UNKNOWN] = "of unknown memory type", @@ -73,28 +195,20 @@ nvkm_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, ram->size = size; if (!nvkm_mm_initialised(&ram->vram)) { - ret = nvkm_mm_init(&ram->vram, 0, size >> NVKM_RAM_MM_SHIFT, 1); + ret = nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL, 0, + size >> NVKM_RAM_MM_SHIFT, 1); if (ret) return ret; } - if (!nvkm_mm_initialised(&ram->tags)) { - ret = nvkm_mm_init(&ram->tags, 0, tags ? ++tags : 0, 1); - if (ret) - return ret; - - nvkm_debug(subdev, "%d compression tags\n", tags); - } - return 0; } int nvkm_ram_new_(const struct nvkm_ram_func *func, struct nvkm_fb *fb, - enum nvkm_ram_type type, u64 size, u32 tags, - struct nvkm_ram **pram) + enum nvkm_ram_type type, u64 size, struct nvkm_ram **pram) { if (!(*pram = kzalloc(sizeof(**pram), GFP_KERNEL))) return -ENOMEM; - return nvkm_ram_ctor(func, fb, type, size, tags, *pram); + return nvkm_ram_ctor(func, fb, type, size, *pram); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h index fac7e73c3ddf..70fd59dcd06d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ram.h @@ -3,11 +3,9 @@ #include "priv.h" int nvkm_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, - enum nvkm_ram_type, u64 size, u32 tags, - struct nvkm_ram *); + enum nvkm_ram_type, u64 size, struct nvkm_ram *); int nvkm_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, - enum nvkm_ram_type, u64 size, u32 tags, - struct nvkm_ram **); + enum nvkm_ram_type, u64 size, struct nvkm_ram **); void nvkm_ram_del(struct nvkm_ram **); int nvkm_ram_init(struct nvkm_ram *); @@ -15,9 +13,6 @@ extern const struct nvkm_ram_func nv04_ram_func; int nv50_ram_ctor(const struct nvkm_ram_func *, struct nvkm_fb *, struct nvkm_ram *); -int nv50_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); -void nv50_ram_put(struct nvkm_ram *, struct nvkm_mem **); -void __nv50_ram_put(struct nvkm_ram *, struct nvkm_mem *); int gf100_ram_new_(const struct nvkm_ram_func *, struct nvkm_fb *, struct nvkm_ram **); @@ -28,8 +23,6 @@ u32 gf100_ram_probe_fbp(const struct nvkm_ram_func *, u32 gf100_ram_probe_fbp_amount(const struct nvkm_ram_func *, u32, struct nvkm_device *, int, int *); u32 gf100_ram_probe_fbpa_amount(struct nvkm_device *, int); -int gf100_ram_get(struct nvkm_ram *, u64, u32, u32, u32, struct nvkm_mem **); -void gf100_ram_put(struct nvkm_ram *, struct nvkm_mem **); int gf100_ram_init(struct nvkm_ram *); int gf100_ram_calc(struct nvkm_ram *, u32); int gf100_ram_prog(struct nvkm_ram *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c index 4a9bd4f1cb93..ac87a3b6b7c9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c @@ -32,7 +32,6 @@ #include <subdev/bios/timing.h> #include <subdev/clk.h> #include <subdev/clk/pll.h> -#include <subdev/ltc.h> struct gf100_ramfuc { struct ramfuc base; @@ -420,86 +419,6 @@ gf100_ram_tidy(struct nvkm_ram *base) ram_exec(&ram->fuc, false); } -void -gf100_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem) -{ - struct nvkm_ltc *ltc = ram->fb->subdev.device->ltc; - struct nvkm_mem *mem = *pmem; - - *pmem = NULL; - if (unlikely(mem == NULL)) - return; - - mutex_lock(&ram->fb->subdev.mutex); - if (mem->tag) - nvkm_ltc_tags_free(ltc, &mem->tag); - __nv50_ram_put(ram, mem); - mutex_unlock(&ram->fb->subdev.mutex); - - kfree(mem); -} - -int -gf100_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nvkm_mem **pmem) -{ - struct nvkm_ltc *ltc = ram->fb->subdev.device->ltc; - struct nvkm_mm *mm = &ram->vram; - struct nvkm_mm_node **node, *r; - struct nvkm_mem *mem; - int type = (memtype & 0x0ff); - int back = (memtype & 0x800); - const bool comp = gf100_pte_storage_type_map[type] != type; - int ret; - - size >>= NVKM_RAM_MM_SHIFT; - align >>= NVKM_RAM_MM_SHIFT; - ncmin >>= NVKM_RAM_MM_SHIFT; - if (!ncmin) - ncmin = size; - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - mem->size = size; - - mutex_lock(&ram->fb->subdev.mutex); - if (comp) { - /* compression only works with lpages */ - if (align == (1 << (17 - NVKM_RAM_MM_SHIFT))) { - int n = size >> 5; - nvkm_ltc_tags_alloc(ltc, n, &mem->tag); - } - - if (unlikely(!mem->tag)) - type = gf100_pte_storage_type_map[type]; - } - mem->memtype = type; - - node = &mem->mem; - do { - if (back) - ret = nvkm_mm_tail(mm, 0, 1, size, ncmin, align, &r); - else - ret = nvkm_mm_head(mm, 0, 1, size, ncmin, align, &r); - if (ret) { - mutex_unlock(&ram->fb->subdev.mutex); - ram->func->put(ram, &mem); - return ret; - } - - *node = r; - node = &r->next; - size -= r->length; - } while (size); - mutex_unlock(&ram->fb->subdev.mutex); - - mem->offset = (u64)mem->mem->offset << NVKM_RAM_MM_SHIFT; - *pmem = mem; - return 0; -} - int gf100_ram_init(struct nvkm_ram *base) { @@ -604,7 +523,7 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, nvkm_debug(subdev, "Upper: %4lld MiB @ %010llx\n", usize >> 20, ubase); nvkm_debug(subdev, "Total: %4lld MiB\n", total >> 20); - ret = nvkm_ram_ctor(func, fb, type, total, 0, ram); + ret = nvkm_ram_ctor(func, fb, type, total, ram); if (ret) return ret; @@ -617,7 +536,8 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, */ if (lower != total) { /* The common memory amount is addressed normally. */ - ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + ret = nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL, + rsvd_head >> NVKM_RAM_MM_SHIFT, (lower - rsvd_head) >> NVKM_RAM_MM_SHIFT, 1); if (ret) return ret; @@ -625,13 +545,15 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb, /* And the rest is much higher in the physical address * space, and may not be usable for certain operations. */ - ret = nvkm_mm_init(&ram->vram, ubase >> NVKM_RAM_MM_SHIFT, + ret = nvkm_mm_init(&ram->vram, NVKM_RAM_MM_MIXED, + ubase >> NVKM_RAM_MM_SHIFT, (usize - rsvd_tail) >> NVKM_RAM_MM_SHIFT, 1); if (ret) return ret; } else { /* GPUs without mixed-memory are a lot nicer... */ - ret = nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + ret = nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL, + rsvd_head >> NVKM_RAM_MM_SHIFT, (total - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT, 1); if (ret) @@ -738,8 +660,6 @@ gf100_ram = { .probe_fbp_amount = gf100_ram_probe_fbp_amount, .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, .init = gf100_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, .calc = gf100_ram_calc, .prog = gf100_ram_prog, .tidy = gf100_ram_tidy, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c index 985ec64cf369..70a06e3cd55a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf108.c @@ -48,8 +48,6 @@ gf108_ram = { .probe_fbp_amount = gf108_ram_probe_fbp_amount, .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, .init = gf100_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, .calc = gf100_ram_calc, .prog = gf100_ram_prog, .tidy = gf100_ram_tidy, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c index 75814f15eb53..8bcb7e79a0cb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgk104.c @@ -1704,8 +1704,6 @@ gk104_ram = { .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, .dtor = gk104_ram_dtor, .init = gk104_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, .calc = gk104_ram_calc, .prog = gk104_ram_prog, .tidy = gk104_ram_tidy, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c index 3f0b56347291..27c68e3f9772 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm107.c @@ -39,8 +39,6 @@ gm107_ram = { .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, .dtor = gk104_ram_dtor, .init = gk104_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, .calc = gk104_ram_calc, .prog = gk104_ram_prog, .tidy = gk104_ram_tidy, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c index fd8facf90476..6b0cac1fe7b4 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgm200.c @@ -54,8 +54,6 @@ gm200_ram = { .probe_fbpa_amount = gf100_ram_probe_fbpa_amount, .dtor = gk104_ram_dtor, .init = gk104_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, .calc = gk104_ram_calc, .prog = gk104_ram_prog, .tidy = gk104_ram_tidy, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c index df8a87333b67..adb62a6beb63 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgp100.c @@ -84,8 +84,6 @@ gp100_ram = { .probe_fbp_amount = gm200_ram_probe_fbp_amount, .probe_fbpa_amount = gp100_ram_probe_fbpa, .init = gp100_ram_init, - .get = gf100_ram_get, - .put = gf100_ram_put, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c index f10664372161..920b3d347803 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgt215.c @@ -26,6 +26,7 @@ #include "ram.h" #include "ramfuc.h" +#include <core/memory.h> #include <core/option.h> #include <subdev/bios.h> #include <subdev/bios/M0205.h> @@ -86,7 +87,7 @@ struct gt215_ltrain { u32 r_100720; u32 r_1111e0; u32 r_111400; - struct nvkm_mem *mem; + struct nvkm_memory *memory; }; struct gt215_ram { @@ -279,10 +280,10 @@ gt215_link_train_init(struct gt215_ram *ram) struct gt215_ltrain *train = &ram->ltrain; struct nvkm_device *device = ram->base.fb->subdev.device; struct nvkm_bios *bios = device->bios; - struct nvkm_mem *mem; struct nvbios_M0205E M0205E; u8 ver, hdr, cnt, len; u32 r001700; + u64 addr; int ret, i = 0; train->state = NVA3_TRAIN_UNSUPPORTED; @@ -297,14 +298,14 @@ gt215_link_train_init(struct gt215_ram *ram) train->state = NVA3_TRAIN_ONCE; - ret = ram->base.func->get(&ram->base, 0x8000, 0x10000, 0, 0x800, - &ram->ltrain.mem); + ret = nvkm_ram_get(device, NVKM_RAM_MM_NORMAL, 0x01, 16, 0x8000, + true, true, &ram->ltrain.memory); if (ret) return ret; - mem = ram->ltrain.mem; + addr = nvkm_memory_addr(ram->ltrain.memory); - nvkm_wr32(device, 0x100538, 0x10000000 | (mem->offset >> 16)); + nvkm_wr32(device, 0x100538, 0x10000000 | (addr >> 16)); nvkm_wr32(device, 0x1005a8, 0x0000ffff); nvkm_mask(device, 0x10f800, 0x00000001, 0x00000001); @@ -320,7 +321,7 @@ gt215_link_train_init(struct gt215_ram *ram) /* And upload the pattern */ r001700 = nvkm_rd32(device, 0x1700); - nvkm_wr32(device, 0x1700, mem->offset >> 16); + nvkm_wr32(device, 0x1700, addr >> 16); for (i = 0; i < 16; i++) nvkm_wr32(device, 0x700000 + (i << 2), pattern[i]); for (i = 0; i < 16; i++) @@ -336,8 +337,7 @@ gt215_link_train_init(struct gt215_ram *ram) static void gt215_link_train_fini(struct gt215_ram *ram) { - if (ram->ltrain.mem) - ram->base.func->put(&ram->base, &ram->ltrain.mem); + nvkm_memory_unref(&ram->ltrain.memory); } /* @@ -931,8 +931,6 @@ static const struct nvkm_ram_func gt215_ram_func = { .dtor = gt215_ram_dtor, .init = gt215_ram_init, - .get = nv50_ram_get, - .put = nv50_ram_put, .calc = gt215_ram_calc, .prog = gt215_ram_prog, .tidy = gt215_ram_tidy, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c index 017a91de74a0..7de18e53ef45 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/rammcp77.c @@ -53,8 +53,6 @@ mcp77_ram_init(struct nvkm_ram *base) static const struct nvkm_ram_func mcp77_ram_func = { .init = mcp77_ram_init, - .get = nv50_ram_get, - .put = nv50_ram_put, }; int @@ -73,7 +71,7 @@ mcp77_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) *pram = &ram->base; ret = nvkm_ram_ctor(&mcp77_ram_func, fb, NVKM_RAM_TYPE_STOLEN, - size, 0, &ram->base); + size, &ram->base); if (ret) return ret; @@ -81,7 +79,8 @@ mcp77_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) ram->base.stolen = base; nvkm_mm_fini(&ram->base.vram); - return nvkm_mm_init(&ram->base.vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + return nvkm_mm_init(&ram->base.vram, NVKM_RAM_MM_NORMAL, + rsvd_head >> NVKM_RAM_MM_SHIFT, (size - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT, 1); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c index 6f053a03d61c..cc764a93f1a3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv04.c @@ -61,5 +61,5 @@ nv04_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) else type = NVKM_RAM_TYPE_SDRAM; - return nvkm_ram_new_(&nv04_ram_func, fb, type, size, 0, pram); + return nvkm_ram_new_(&nv04_ram_func, fb, type, size, pram); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c index dfd155c98dbb..afe54e323b18 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv10.c @@ -36,5 +36,5 @@ nv10_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) else type = NVKM_RAM_TYPE_SDRAM; - return nvkm_ram_new_(&nv04_ram_func, fb, type, size, 0, pram); + return nvkm_ram_new_(&nv04_ram_func, fb, type, size, pram); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c index 3c6a8710e812..4c07d10bb976 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c @@ -44,5 +44,5 @@ nv1a_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) } return nvkm_ram_new_(&nv04_ram_func, fb, NVKM_RAM_TYPE_STOLEN, - mib * 1024 * 1024, 0, pram); + mib * 1024 * 1024, pram); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c index 747e47c10cc7..71d63d7daa75 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv20.c @@ -29,7 +29,6 @@ nv20_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) struct nvkm_device *device = fb->subdev.device; u32 pbus1218 = nvkm_rd32(device, 0x001218); u32 size = (nvkm_rd32(device, 0x10020c) & 0xff000000); - u32 tags = nvkm_rd32(device, 0x100320); enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; @@ -40,7 +39,7 @@ nv20_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) case 0x00000300: type = NVKM_RAM_TYPE_GDDR2; break; } - ret = nvkm_ram_new_(&nv04_ram_func, fb, type, size, tags, pram); + ret = nvkm_ram_new_(&nv04_ram_func, fb, type, size, pram); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c index 70c63535d56b..2b12e388f47a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.c @@ -187,13 +187,13 @@ nv40_ram_func = { int nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type type, u64 size, - u32 tags, struct nvkm_ram **pram) + struct nvkm_ram **pram) { struct nv40_ram *ram; if (!(ram = kzalloc(sizeof(*ram), GFP_KERNEL))) return -ENOMEM; *pram = &ram->base; - return nvkm_ram_ctor(&nv40_ram_func, fb, type, size, tags, &ram->base); + return nvkm_ram_ctor(&nv40_ram_func, fb, type, size, &ram->base); } int @@ -202,7 +202,6 @@ nv40_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) struct nvkm_device *device = fb->subdev.device; u32 pbus1218 = nvkm_rd32(device, 0x001218); u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; - u32 tags = nvkm_rd32(device, 0x100320); enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; @@ -213,7 +212,7 @@ nv40_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) case 0x00000300: type = NVKM_RAM_TYPE_DDR2 ; break; } - ret = nv40_ram_new_(fb, type, size, tags, pram); + ret = nv40_ram_new_(fb, type, size, pram); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h index 8a0524566b48..ec5dcbfcaea8 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv40.h @@ -9,6 +9,6 @@ struct nv40_ram { u32 coef; }; -int nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type, u64, u32, +int nv40_ram_new_(struct nvkm_fb *fb, enum nvkm_ram_type, u64, struct nvkm_ram **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c index 114828be292e..d3fea3726461 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv41.c @@ -28,7 +28,6 @@ nv41_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { struct nvkm_device *device = fb->subdev.device; u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; - u32 tags = nvkm_rd32(device, 0x100320); u32 fb474 = nvkm_rd32(device, 0x100474); enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; @@ -40,7 +39,7 @@ nv41_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) if (fb474 & 0x00000001) type = NVKM_RAM_TYPE_DDR1; - ret = nv40_ram_new_(fb, type, size, tags, pram); + ret = nv40_ram_new_(fb, type, size, pram); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c index bc56fbf1c788..ab2630e5e6fb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv44.c @@ -38,5 +38,5 @@ nv44_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) if (fb474 & 0x00000001) type = NVKM_RAM_TYPE_DDR1; - return nv40_ram_new_(fb, type, size, 0, pram); + return nv40_ram_new_(fb, type, size, pram); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c index c01f4b1022b8..946ca7c2e0b6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv49.c @@ -28,7 +28,6 @@ nv49_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) { struct nvkm_device *device = fb->subdev.device; u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; - u32 tags = nvkm_rd32(device, 0x100320); u32 fb914 = nvkm_rd32(device, 0x100914); enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; @@ -40,7 +39,7 @@ nv49_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) case 0x00000003: break; } - ret = nv40_ram_new_(fb, type, size, tags, pram); + ret = nv40_ram_new_(fb, type, size, pram); if (ret) return ret; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c index fa3c2e06203d..02b8bdbc819f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv4e.c @@ -29,5 +29,5 @@ nv4e_ram_new(struct nvkm_fb *fb, struct nvkm_ram **pram) struct nvkm_device *device = fb->subdev.device; u32 size = nvkm_rd32(device, 0x10020c) & 0xff000000; return nvkm_ram_new_(&nv04_ram_func, fb, NVKM_RAM_TYPE_UNKNOWN, - size, 0, pram); + size, pram); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c index 6549b0588309..2ccb4b6be153 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv50.c @@ -493,100 +493,8 @@ nv50_ram_tidy(struct nvkm_ram *base) ram_exec(&ram->hwsq, false); } -void -__nv50_ram_put(struct nvkm_ram *ram, struct nvkm_mem *mem) -{ - struct nvkm_mm_node *next = mem->mem; - struct nvkm_mm_node *node; - while ((node = next)) { - next = node->next; - nvkm_mm_free(&ram->vram, &node); - } - nvkm_mm_free(&ram->tags, &mem->tag); -} - -void -nv50_ram_put(struct nvkm_ram *ram, struct nvkm_mem **pmem) -{ - struct nvkm_mem *mem = *pmem; - - *pmem = NULL; - if (unlikely(mem == NULL)) - return; - - mutex_lock(&ram->fb->subdev.mutex); - __nv50_ram_put(ram, mem); - mutex_unlock(&ram->fb->subdev.mutex); - - kfree(mem); -} - -int -nv50_ram_get(struct nvkm_ram *ram, u64 size, u32 align, u32 ncmin, - u32 memtype, struct nvkm_mem **pmem) -{ - struct nvkm_mm *heap = &ram->vram; - struct nvkm_mm *tags = &ram->tags; - struct nvkm_mm_node **node, *r; - struct nvkm_mem *mem; - int comp = (memtype & 0x300) >> 8; - int type = (memtype & 0x07f); - int back = (memtype & 0x800); - int min, max, ret; - - max = (size >> NVKM_RAM_MM_SHIFT); - min = ncmin ? (ncmin >> NVKM_RAM_MM_SHIFT) : max; - align >>= NVKM_RAM_MM_SHIFT; - - mem = kzalloc(sizeof(*mem), GFP_KERNEL); - if (!mem) - return -ENOMEM; - - mutex_lock(&ram->fb->subdev.mutex); - if (comp) { - if (align == (1 << (16 - NVKM_RAM_MM_SHIFT))) { - int n = (max >> 4) * comp; - - ret = nvkm_mm_head(tags, 0, 1, n, n, 1, &mem->tag); - if (ret) - mem->tag = NULL; - } - - if (unlikely(!mem->tag)) - comp = 0; - } - - mem->memtype = (comp << 7) | type; - mem->size = max; - - type = nv50_fb_memtype[type]; - node = &mem->mem; - do { - if (back) - ret = nvkm_mm_tail(heap, 0, type, max, min, align, &r); - else - ret = nvkm_mm_head(heap, 0, type, max, min, align, &r); - if (ret) { - mutex_unlock(&ram->fb->subdev.mutex); - ram->func->put(ram, &mem); - return ret; - } - - *node = r; - node = &r->next; - max -= r->length; - } while (max); - mutex_unlock(&ram->fb->subdev.mutex); - - mem->offset = (u64)mem->mem->offset << NVKM_RAM_MM_SHIFT; - *pmem = mem; - return 0; -} - static const struct nvkm_ram_func nv50_ram_func = { - .get = nv50_ram_get, - .put = nv50_ram_put, .calc = nv50_ram_calc, .prog = nv50_ram_prog, .tidy = nv50_ram_tidy, @@ -639,7 +547,6 @@ nv50_ram_ctor(const struct nvkm_ram_func *func, const u32 rsvd_head = ( 256 * 1024); /* vga memory */ const u32 rsvd_tail = (1024 * 1024); /* vbios etc */ u64 size = nvkm_rd32(device, 0x10020c); - u32 tags = nvkm_rd32(device, 0x100320); enum nvkm_ram_type type = NVKM_RAM_TYPE_UNKNOWN; int ret; @@ -660,7 +567,7 @@ nv50_ram_ctor(const struct nvkm_ram_func *func, size = (size & 0x000000ff) << 32 | (size & 0xffffff00); - ret = nvkm_ram_ctor(func, fb, type, size, tags, ram); + ret = nvkm_ram_ctor(func, fb, type, size, ram); if (ret) return ret; @@ -669,7 +576,8 @@ nv50_ram_ctor(const struct nvkm_ram_func *func, ram->ranks = (nvkm_rd32(device, 0x100200) & 0x4) ? 2 : 1; nvkm_mm_fini(&ram->vram); - return nvkm_mm_init(&ram->vram, rsvd_head >> NVKM_RAM_MM_SHIFT, + return nvkm_mm_init(&ram->vram, NVKM_RAM_MM_NORMAL, + rsvd_head >> NVKM_RAM_MM_SHIFT, (size - rsvd_head - rsvd_tail) >> NVKM_RAM_MM_SHIFT, nv50_fb_vram_rblock(ram) >> NVKM_RAM_MM_SHIFT); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c index 10c987a654ec..364ea4492acc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/base.c @@ -23,181 +23,90 @@ */ #include "priv.h" -#include <core/memory.h> #include <subdev/bar.h> /****************************************************************************** * instmem object base implementation *****************************************************************************/ -#define nvkm_instobj(p) container_of((p), struct nvkm_instobj, memory) - -struct nvkm_instobj { - struct nvkm_memory memory; - struct nvkm_memory *parent; - struct nvkm_instmem *imem; - struct list_head head; - u32 *suspend; - void __iomem *map; -}; - -static enum nvkm_memory_target -nvkm_instobj_target(struct nvkm_memory *memory) -{ - memory = nvkm_instobj(memory)->parent; - return nvkm_memory_target(memory); -} - -static u64 -nvkm_instobj_addr(struct nvkm_memory *memory) -{ - memory = nvkm_instobj(memory)->parent; - return nvkm_memory_addr(memory); -} - -static u64 -nvkm_instobj_size(struct nvkm_memory *memory) -{ - memory = nvkm_instobj(memory)->parent; - return nvkm_memory_size(memory); -} - static void -nvkm_instobj_release(struct nvkm_memory *memory) +nvkm_instobj_load(struct nvkm_instobj *iobj) { - struct nvkm_instobj *iobj = nvkm_instobj(memory); - nvkm_bar_flush(iobj->imem->subdev.device->bar); -} - -static void __iomem * -nvkm_instobj_acquire(struct nvkm_memory *memory) -{ - return nvkm_instobj(memory)->map; -} - -static u32 -nvkm_instobj_rd32(struct nvkm_memory *memory, u64 offset) -{ - return ioread32_native(nvkm_instobj(memory)->map + offset); -} - -static void -nvkm_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) -{ - iowrite32_native(data, nvkm_instobj(memory)->map + offset); -} + struct nvkm_memory *memory = &iobj->memory; + const u64 size = nvkm_memory_size(memory); + void __iomem *map; + int i; -static void -nvkm_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) -{ - memory = nvkm_instobj(memory)->parent; - nvkm_memory_map(memory, vma, offset); -} + if (!(map = nvkm_kmap(memory))) { + for (i = 0; i < size; i += 4) + nvkm_wo32(memory, i, iobj->suspend[i / 4]); + } else { + memcpy_toio(map, iobj->suspend, size); + } + nvkm_done(memory); -static void * -nvkm_instobj_dtor(struct nvkm_memory *memory) -{ - struct nvkm_instobj *iobj = nvkm_instobj(memory); - spin_lock(&iobj->imem->lock); - list_del(&iobj->head); - spin_unlock(&iobj->imem->lock); - nvkm_memory_del(&iobj->parent); - return iobj; + kvfree(iobj->suspend); + iobj->suspend = NULL; } -static const struct nvkm_memory_func -nvkm_instobj_func = { - .dtor = nvkm_instobj_dtor, - .target = nvkm_instobj_target, - .addr = nvkm_instobj_addr, - .size = nvkm_instobj_size, - .acquire = nvkm_instobj_acquire, - .release = nvkm_instobj_release, - .rd32 = nvkm_instobj_rd32, - .wr32 = nvkm_instobj_wr32, - .map = nvkm_instobj_map, -}; - -static void -nvkm_instobj_boot(struct nvkm_memory *memory, struct nvkm_vm *vm) +static int +nvkm_instobj_save(struct nvkm_instobj *iobj) { - memory = nvkm_instobj(memory)->parent; - nvkm_memory_boot(memory, vm); -} + struct nvkm_memory *memory = &iobj->memory; + const u64 size = nvkm_memory_size(memory); + void __iomem *map; + int i; -static void -nvkm_instobj_release_slow(struct nvkm_memory *memory) -{ - struct nvkm_instobj *iobj = nvkm_instobj(memory); - nvkm_instobj_release(memory); - nvkm_done(iobj->parent); -} + iobj->suspend = kvmalloc(size, GFP_KERNEL); + if (!iobj->suspend) + return -ENOMEM; -static void __iomem * -nvkm_instobj_acquire_slow(struct nvkm_memory *memory) -{ - struct nvkm_instobj *iobj = nvkm_instobj(memory); - iobj->map = nvkm_kmap(iobj->parent); - if (iobj->map) - memory->func = &nvkm_instobj_func; - return iobj->map; + if (!(map = nvkm_kmap(memory))) { + for (i = 0; i < size; i += 4) + iobj->suspend[i / 4] = nvkm_ro32(memory, i); + } else { + memcpy_fromio(iobj->suspend, map, size); + } + nvkm_done(memory); + return 0; } -static u32 -nvkm_instobj_rd32_slow(struct nvkm_memory *memory, u64 offset) +void +nvkm_instobj_dtor(struct nvkm_instmem *imem, struct nvkm_instobj *iobj) { - struct nvkm_instobj *iobj = nvkm_instobj(memory); - return nvkm_ro32(iobj->parent, offset); + spin_lock(&imem->lock); + list_del(&iobj->head); + spin_unlock(&imem->lock); } -static void -nvkm_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data) +void +nvkm_instobj_ctor(const struct nvkm_memory_func *func, + struct nvkm_instmem *imem, struct nvkm_instobj *iobj) { - struct nvkm_instobj *iobj = nvkm_instobj(memory); - return nvkm_wo32(iobj->parent, offset, data); + nvkm_memory_ctor(func, &iobj->memory); + iobj->suspend = NULL; + spin_lock(&imem->lock); + list_add_tail(&iobj->head, &imem->list); + spin_unlock(&imem->lock); } -static const struct nvkm_memory_func -nvkm_instobj_func_slow = { - .dtor = nvkm_instobj_dtor, - .target = nvkm_instobj_target, - .addr = nvkm_instobj_addr, - .size = nvkm_instobj_size, - .boot = nvkm_instobj_boot, - .acquire = nvkm_instobj_acquire_slow, - .release = nvkm_instobj_release_slow, - .rd32 = nvkm_instobj_rd32_slow, - .wr32 = nvkm_instobj_wr32_slow, - .map = nvkm_instobj_map, -}; - int nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, struct nvkm_memory **pmemory) { + struct nvkm_subdev *subdev = &imem->subdev; struct nvkm_memory *memory = NULL; - struct nvkm_instobj *iobj; u32 offset; int ret; ret = imem->func->memory_new(imem, size, align, zero, &memory); - if (ret) + if (ret) { + nvkm_error(subdev, "OOM: %08x %08x %d\n", size, align, ret); goto done; - - if (!imem->func->persistent) { - if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) { - ret = -ENOMEM; - goto done; - } - - nvkm_memory_ctor(&nvkm_instobj_func_slow, &iobj->memory); - iobj->parent = memory; - iobj->imem = imem; - spin_lock(&iobj->imem->lock); - list_add_tail(&iobj->head, &imem->list); - spin_unlock(&iobj->imem->lock); - memory = &iobj->memory; } + nvkm_trace(subdev, "new %08x %08x %d: %010llx %010llx\n", size, align, + zero, nvkm_memory_addr(memory), nvkm_memory_size(memory)); + if (!imem->func->zero && zero) { void __iomem *map = nvkm_kmap(memory); if (unlikely(!map)) { @@ -211,7 +120,7 @@ nvkm_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero, done: if (ret) - nvkm_memory_del(&memory); + nvkm_memory_unref(&memory); *pmemory = memory; return ret; } @@ -232,39 +141,46 @@ nvkm_instmem_wr32(struct nvkm_instmem *imem, u32 addr, u32 data) return imem->func->wr32(imem, addr, data); } +void +nvkm_instmem_boot(struct nvkm_instmem *imem) +{ + /* Separate bootstrapped objects from normal list, as we need + * to make sure they're accessed with the slowpath on suspend + * and resume. + */ + struct nvkm_instobj *iobj, *itmp; + spin_lock(&imem->lock); + list_for_each_entry_safe(iobj, itmp, &imem->list, head) { + list_move_tail(&iobj->head, &imem->boot); + } + spin_unlock(&imem->lock); +} + static int nvkm_instmem_fini(struct nvkm_subdev *subdev, bool suspend) { struct nvkm_instmem *imem = nvkm_instmem(subdev); struct nvkm_instobj *iobj; - int i; - - if (imem->func->fini) - imem->func->fini(imem); if (suspend) { list_for_each_entry(iobj, &imem->list, head) { - struct nvkm_memory *memory = iobj->parent; - u64 size = nvkm_memory_size(memory); + int ret = nvkm_instobj_save(iobj); + if (ret) + return ret; + } - iobj->suspend = vmalloc(size); - if (!iobj->suspend) - return -ENOMEM; + nvkm_bar_bar2_fini(subdev->device); - for (i = 0; i < size; i += 4) - iobj->suspend[i / 4] = nvkm_ro32(memory, i); + list_for_each_entry(iobj, &imem->boot, head) { + int ret = nvkm_instobj_save(iobj); + if (ret) + return ret; } } - return 0; -} + if (imem->func->fini) + imem->func->fini(imem); -static int -nvkm_instmem_oneinit(struct nvkm_subdev *subdev) -{ - struct nvkm_instmem *imem = nvkm_instmem(subdev); - if (imem->func->oneinit) - return imem->func->oneinit(imem); return 0; } @@ -273,22 +189,31 @@ nvkm_instmem_init(struct nvkm_subdev *subdev) { struct nvkm_instmem *imem = nvkm_instmem(subdev); struct nvkm_instobj *iobj; - int i; + + list_for_each_entry(iobj, &imem->boot, head) { + if (iobj->suspend) + nvkm_instobj_load(iobj); + } + + nvkm_bar_bar2_init(subdev->device); list_for_each_entry(iobj, &imem->list, head) { - if (iobj->suspend) { - struct nvkm_memory *memory = iobj->parent; - u64 size = nvkm_memory_size(memory); - for (i = 0; i < size; i += 4) - nvkm_wo32(memory, i, iobj->suspend[i / 4]); - vfree(iobj->suspend); - iobj->suspend = NULL; - } + if (iobj->suspend) + nvkm_instobj_load(iobj); } return 0; } +static int +nvkm_instmem_oneinit(struct nvkm_subdev *subdev) +{ + struct nvkm_instmem *imem = nvkm_instmem(subdev); + if (imem->func->oneinit) + return imem->func->oneinit(imem); + return 0; +} + static void * nvkm_instmem_dtor(struct nvkm_subdev *subdev) { @@ -315,4 +240,5 @@ nvkm_instmem_ctor(const struct nvkm_instmem_func *func, imem->func = func; spin_lock_init(&imem->lock); INIT_LIST_HEAD(&imem->list); + INIT_LIST_HEAD(&imem->boot); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c index cd5adbec5e57..985f2990ab0d 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/gk20a.c @@ -44,14 +44,13 @@ #include "priv.h" #include <core/memory.h> -#include <core/mm.h> #include <core/tegra.h> -#include <subdev/fb.h> #include <subdev/ltc.h> +#include <subdev/mmu.h> struct gk20a_instobj { struct nvkm_memory memory; - struct nvkm_mem mem; + struct nvkm_mm_node *mn; struct gk20a_instmem *imem; /* CPU mapping */ @@ -119,16 +118,22 @@ gk20a_instobj_target(struct nvkm_memory *memory) return NVKM_MEM_TARGET_NCOH; } +static u8 +gk20a_instobj_page(struct nvkm_memory *memory) +{ + return 12; +} + static u64 gk20a_instobj_addr(struct nvkm_memory *memory) { - return gk20a_instobj(memory)->mem.offset; + return (u64)gk20a_instobj(memory)->mn->offset << 12; } static u64 gk20a_instobj_size(struct nvkm_memory *memory) { - return (u64)gk20a_instobj(memory)->mem.size << 12; + return (u64)gk20a_instobj(memory)->mn->length << 12; } /* @@ -272,12 +277,18 @@ gk20a_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) node->vaddr[offset / 4] = data; } -static void -gk20a_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) +static int +gk20a_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, + struct nvkm_vma *vma, void *argv, u32 argc) { struct gk20a_instobj *node = gk20a_instobj(memory); + struct nvkm_vmm_map map = { + .memory = &node->memory, + .offset = offset, + .mem = node->mn, + }; - nvkm_vm_map_at(vma, offset, &node->mem); + return nvkm_vmm_map(vmm, vma, argv, argc, &map); } static void * @@ -290,8 +301,8 @@ gk20a_instobj_dtor_dma(struct nvkm_memory *memory) if (unlikely(!node->base.vaddr)) goto out; - dma_free_attrs(dev, node->base.mem.size << PAGE_SHIFT, node->base.vaddr, - node->handle, imem->attrs); + dma_free_attrs(dev, (u64)node->base.mn->length << PAGE_SHIFT, + node->base.vaddr, node->handle, imem->attrs); out: return node; @@ -303,7 +314,7 @@ gk20a_instobj_dtor_iommu(struct nvkm_memory *memory) struct gk20a_instobj_iommu *node = gk20a_instobj_iommu(memory); struct gk20a_instmem *imem = node->base.imem; struct device *dev = imem->base.subdev.device->dev; - struct nvkm_mm_node *r = node->base.mem.mem; + struct nvkm_mm_node *r = node->base.mn; int i; if (unlikely(!r)) @@ -321,7 +332,7 @@ gk20a_instobj_dtor_iommu(struct nvkm_memory *memory) r->offset &= ~BIT(imem->iommu_bit - imem->iommu_pgshift); /* Unmap pages from GPU address space and free them */ - for (i = 0; i < node->base.mem.size; i++) { + for (i = 0; i < node->base.mn->length; i++) { iommu_unmap(imem->domain, (r->offset + i) << imem->iommu_pgshift, PAGE_SIZE); dma_unmap_page(dev, node->dma_addrs[i], PAGE_SIZE, @@ -342,12 +353,11 @@ static const struct nvkm_memory_func gk20a_instobj_func_dma = { .dtor = gk20a_instobj_dtor_dma, .target = gk20a_instobj_target, + .page = gk20a_instobj_page, .addr = gk20a_instobj_addr, .size = gk20a_instobj_size, .acquire = gk20a_instobj_acquire_dma, .release = gk20a_instobj_release_dma, - .rd32 = gk20a_instobj_rd32, - .wr32 = gk20a_instobj_wr32, .map = gk20a_instobj_map, }; @@ -355,13 +365,18 @@ static const struct nvkm_memory_func gk20a_instobj_func_iommu = { .dtor = gk20a_instobj_dtor_iommu, .target = gk20a_instobj_target, + .page = gk20a_instobj_page, .addr = gk20a_instobj_addr, .size = gk20a_instobj_size, .acquire = gk20a_instobj_acquire_iommu, .release = gk20a_instobj_release_iommu, + .map = gk20a_instobj_map, +}; + +static const struct nvkm_memory_ptrs +gk20a_instobj_ptrs = { .rd32 = gk20a_instobj_rd32, .wr32 = gk20a_instobj_wr32, - .map = gk20a_instobj_map, }; static int @@ -377,6 +392,7 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align, *_node = &node->base; nvkm_memory_ctor(&gk20a_instobj_func_dma, &node->base.memory); + node->base.memory.ptrs = &gk20a_instobj_ptrs; node->base.vaddr = dma_alloc_attrs(dev, npages << PAGE_SHIFT, &node->handle, GFP_KERNEL, @@ -397,8 +413,7 @@ gk20a_instobj_ctor_dma(struct gk20a_instmem *imem, u32 npages, u32 align, node->r.offset = node->handle >> 12; node->r.length = (npages << PAGE_SHIFT) >> 12; - node->base.mem.offset = node->handle; - node->base.mem.mem = &node->r; + node->base.mn = &node->r; return 0; } @@ -424,6 +439,7 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align, node->dma_addrs = (void *)(node->pages + npages); nvkm_memory_ctor(&gk20a_instobj_func_iommu, &node->base.memory); + node->base.memory.ptrs = &gk20a_instobj_ptrs; /* Allocate backing memory */ for (i = 0; i < npages; i++) { @@ -474,8 +490,7 @@ gk20a_instobj_ctor_iommu(struct gk20a_instmem *imem, u32 npages, u32 align, /* IOMMU bit tells that an address is to be resolved through the IOMMU */ r->offset |= BIT(imem->iommu_bit - imem->iommu_pgshift); - node->base.mem.offset = ((u64)r->offset) << imem->iommu_pgshift; - node->base.mem.mem = r; + node->base.mn = r; return 0; release_area: @@ -523,13 +538,8 @@ gk20a_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, node->imem = imem; - /* present memory for being mapped using small pages */ - node->mem.size = size >> 12; - node->mem.memtype = 0; - node->mem.page_shift = 12; - nvkm_debug(subdev, "alloc size: 0x%x, align: 0x%x, gaddr: 0x%llx\n", - size, align, node->mem.offset); + size, align, (u64)node->mn->offset << 12); return 0; } @@ -554,7 +564,6 @@ static const struct nvkm_instmem_func gk20a_instmem = { .dtor = gk20a_instmem_dtor, .memory_new = gk20a_instobj_new, - .persistent = true, .zero = false, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c index 6133c8bb2d42..6bf0dad46919 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv04.c @@ -24,7 +24,6 @@ #define nv04_instmem(p) container_of((p), struct nv04_instmem, base) #include "priv.h" -#include <core/memory.h> #include <core/ramht.h> struct nv04_instmem { @@ -35,30 +34,39 @@ struct nv04_instmem { /****************************************************************************** * instmem object implementation *****************************************************************************/ -#define nv04_instobj(p) container_of((p), struct nv04_instobj, memory) +#define nv04_instobj(p) container_of((p), struct nv04_instobj, base.memory) struct nv04_instobj { - struct nvkm_memory memory; + struct nvkm_instobj base; struct nv04_instmem *imem; struct nvkm_mm_node *node; }; -static enum nvkm_memory_target -nv04_instobj_target(struct nvkm_memory *memory) +static void +nv04_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) { - return NVKM_MEM_TARGET_INST; + struct nv04_instobj *iobj = nv04_instobj(memory); + struct nvkm_device *device = iobj->imem->base.subdev.device; + nvkm_wr32(device, 0x700000 + iobj->node->offset + offset, data); } -static u64 -nv04_instobj_addr(struct nvkm_memory *memory) +static u32 +nv04_instobj_rd32(struct nvkm_memory *memory, u64 offset) { - return nv04_instobj(memory)->node->offset; + struct nv04_instobj *iobj = nv04_instobj(memory); + struct nvkm_device *device = iobj->imem->base.subdev.device; + return nvkm_rd32(device, 0x700000 + iobj->node->offset + offset); } -static u64 -nv04_instobj_size(struct nvkm_memory *memory) +static const struct nvkm_memory_ptrs +nv04_instobj_ptrs = { + .rd32 = nv04_instobj_rd32, + .wr32 = nv04_instobj_wr32, +}; + +static void +nv04_instobj_release(struct nvkm_memory *memory) { - return nv04_instobj(memory)->node->length; } static void __iomem * @@ -69,25 +77,22 @@ nv04_instobj_acquire(struct nvkm_memory *memory) return device->pri + 0x700000 + iobj->node->offset; } -static void -nv04_instobj_release(struct nvkm_memory *memory) +static u64 +nv04_instobj_size(struct nvkm_memory *memory) { + return nv04_instobj(memory)->node->length; } -static u32 -nv04_instobj_rd32(struct nvkm_memory *memory, u64 offset) +static u64 +nv04_instobj_addr(struct nvkm_memory *memory) { - struct nv04_instobj *iobj = nv04_instobj(memory); - struct nvkm_device *device = iobj->imem->base.subdev.device; - return nvkm_rd32(device, 0x700000 + iobj->node->offset + offset); + return nv04_instobj(memory)->node->offset; } -static void -nv04_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) +static enum nvkm_memory_target +nv04_instobj_target(struct nvkm_memory *memory) { - struct nv04_instobj *iobj = nv04_instobj(memory); - struct nvkm_device *device = iobj->imem->base.subdev.device; - nvkm_wr32(device, 0x700000 + iobj->node->offset + offset, data); + return NVKM_MEM_TARGET_INST; } static void * @@ -97,6 +102,7 @@ nv04_instobj_dtor(struct nvkm_memory *memory) mutex_lock(&iobj->imem->base.subdev.mutex); nvkm_mm_free(&iobj->imem->heap, &iobj->node); mutex_unlock(&iobj->imem->base.subdev.mutex); + nvkm_instobj_dtor(&iobj->imem->base, &iobj->base); return iobj; } @@ -108,8 +114,6 @@ nv04_instobj_func = { .addr = nv04_instobj_addr, .acquire = nv04_instobj_acquire, .release = nv04_instobj_release, - .rd32 = nv04_instobj_rd32, - .wr32 = nv04_instobj_wr32, }; static int @@ -122,9 +126,10 @@ nv04_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) return -ENOMEM; - *pmemory = &iobj->memory; + *pmemory = &iobj->base.memory; - nvkm_memory_ctor(&nv04_instobj_func, &iobj->memory); + nvkm_instobj_ctor(&nv04_instobj_func, &imem->base, &iobj->base); + iobj->base.memory.ptrs = &nv04_instobj_ptrs; iobj->imem = imem; mutex_lock(&imem->base.subdev.mutex); @@ -160,7 +165,7 @@ nv04_instmem_oneinit(struct nvkm_instmem *base) /* PRAMIN aperture maps over the end of VRAM, reserve it */ imem->base.reserved = 512 * 1024; - ret = nvkm_mm_init(&imem->heap, 0, imem->base.reserved, 1); + ret = nvkm_mm_init(&imem->heap, 0, 0, imem->base.reserved, 1); if (ret) return ret; @@ -194,10 +199,10 @@ static void * nv04_instmem_dtor(struct nvkm_instmem *base) { struct nv04_instmem *imem = nv04_instmem(base); - nvkm_memory_del(&imem->base.ramfc); - nvkm_memory_del(&imem->base.ramro); + nvkm_memory_unref(&imem->base.ramfc); + nvkm_memory_unref(&imem->base.ramro); nvkm_ramht_del(&imem->base.ramht); - nvkm_memory_del(&imem->base.vbios); + nvkm_memory_unref(&imem->base.vbios); nvkm_mm_fini(&imem->heap); return imem; } @@ -209,7 +214,6 @@ nv04_instmem = { .rd32 = nv04_instmem_rd32, .wr32 = nv04_instmem_wr32, .memory_new = nv04_instobj_new, - .persistent = false, .zero = false, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c index c0543875e490..086c118488ef 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv40.c @@ -24,7 +24,6 @@ #define nv40_instmem(p) container_of((p), struct nv40_instmem, base) #include "priv.h" -#include <core/memory.h> #include <core/ramht.h> #include <engine/gr/nv40.h> @@ -37,30 +36,38 @@ struct nv40_instmem { /****************************************************************************** * instmem object implementation *****************************************************************************/ -#define nv40_instobj(p) container_of((p), struct nv40_instobj, memory) +#define nv40_instobj(p) container_of((p), struct nv40_instobj, base.memory) struct nv40_instobj { - struct nvkm_memory memory; + struct nvkm_instobj base; struct nv40_instmem *imem; struct nvkm_mm_node *node; }; -static enum nvkm_memory_target -nv40_instobj_target(struct nvkm_memory *memory) +static void +nv40_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) { - return NVKM_MEM_TARGET_INST; + struct nv40_instobj *iobj = nv40_instobj(memory); + iowrite32_native(data, iobj->imem->iomem + iobj->node->offset + offset); } -static u64 -nv40_instobj_addr(struct nvkm_memory *memory) +static u32 +nv40_instobj_rd32(struct nvkm_memory *memory, u64 offset) { - return nv40_instobj(memory)->node->offset; + struct nv40_instobj *iobj = nv40_instobj(memory); + return ioread32_native(iobj->imem->iomem + iobj->node->offset + offset); } -static u64 -nv40_instobj_size(struct nvkm_memory *memory) +static const struct nvkm_memory_ptrs +nv40_instobj_ptrs = { + .rd32 = nv40_instobj_rd32, + .wr32 = nv40_instobj_wr32, +}; + +static void +nv40_instobj_release(struct nvkm_memory *memory) { - return nv40_instobj(memory)->node->length; + wmb(); } static void __iomem * @@ -70,23 +77,22 @@ nv40_instobj_acquire(struct nvkm_memory *memory) return iobj->imem->iomem + iobj->node->offset; } -static void -nv40_instobj_release(struct nvkm_memory *memory) +static u64 +nv40_instobj_size(struct nvkm_memory *memory) { + return nv40_instobj(memory)->node->length; } -static u32 -nv40_instobj_rd32(struct nvkm_memory *memory, u64 offset) +static u64 +nv40_instobj_addr(struct nvkm_memory *memory) { - struct nv40_instobj *iobj = nv40_instobj(memory); - return ioread32_native(iobj->imem->iomem + iobj->node->offset + offset); + return nv40_instobj(memory)->node->offset; } -static void -nv40_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) +static enum nvkm_memory_target +nv40_instobj_target(struct nvkm_memory *memory) { - struct nv40_instobj *iobj = nv40_instobj(memory); - iowrite32_native(data, iobj->imem->iomem + iobj->node->offset + offset); + return NVKM_MEM_TARGET_INST; } static void * @@ -96,6 +102,7 @@ nv40_instobj_dtor(struct nvkm_memory *memory) mutex_lock(&iobj->imem->base.subdev.mutex); nvkm_mm_free(&iobj->imem->heap, &iobj->node); mutex_unlock(&iobj->imem->base.subdev.mutex); + nvkm_instobj_dtor(&iobj->imem->base, &iobj->base); return iobj; } @@ -107,8 +114,6 @@ nv40_instobj_func = { .addr = nv40_instobj_addr, .acquire = nv40_instobj_acquire, .release = nv40_instobj_release, - .rd32 = nv40_instobj_rd32, - .wr32 = nv40_instobj_wr32, }; static int @@ -121,9 +126,10 @@ nv40_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) return -ENOMEM; - *pmemory = &iobj->memory; + *pmemory = &iobj->base.memory; - nvkm_memory_ctor(&nv40_instobj_func, &iobj->memory); + nvkm_instobj_ctor(&nv40_instobj_func, &imem->base, &iobj->base); + iobj->base.memory.ptrs = &nv40_instobj_ptrs; iobj->imem = imem; mutex_lock(&imem->base.subdev.mutex); @@ -171,7 +177,7 @@ nv40_instmem_oneinit(struct nvkm_instmem *base) imem->base.reserved += 512 * 1024; /* object storage */ imem->base.reserved = round_up(imem->base.reserved, 4096); - ret = nvkm_mm_init(&imem->heap, 0, imem->base.reserved, 1); + ret = nvkm_mm_init(&imem->heap, 0, 0, imem->base.reserved, 1); if (ret) return ret; @@ -209,10 +215,10 @@ static void * nv40_instmem_dtor(struct nvkm_instmem *base) { struct nv40_instmem *imem = nv40_instmem(base); - nvkm_memory_del(&imem->base.ramfc); - nvkm_memory_del(&imem->base.ramro); + nvkm_memory_unref(&imem->base.ramfc); + nvkm_memory_unref(&imem->base.ramro); nvkm_ramht_del(&imem->base.ramht); - nvkm_memory_del(&imem->base.vbios); + nvkm_memory_unref(&imem->base.vbios); nvkm_mm_fini(&imem->heap); if (imem->iomem) iounmap(imem->iomem); @@ -226,7 +232,6 @@ nv40_instmem = { .rd32 = nv40_instmem_rd32, .wr32 = nv40_instmem_wr32, .memory_new = nv40_instobj_new, - .persistent = false, .zero = false, }; @@ -248,8 +253,8 @@ nv40_instmem_new(struct nvkm_device *device, int index, else bar = 3; - imem->iomem = ioremap(device->func->resource_addr(device, bar), - device->func->resource_size(device, bar)); + imem->iomem = ioremap_wc(device->func->resource_addr(device, bar), + device->func->resource_size(device, bar)); if (!imem->iomem) { nvkm_error(&imem->base.subdev, "unable to map PRAMIN BAR\n"); return -EFAULT; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c index 6d512c062ae3..1ba7289684aa 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c @@ -31,147 +31,293 @@ struct nv50_instmem { struct nvkm_instmem base; - unsigned long lock_flags; - spinlock_t lock; u64 addr; + + /* Mappings that can be evicted when BAR2 space has been exhausted. */ + struct list_head lru; }; /****************************************************************************** * instmem object implementation *****************************************************************************/ -#define nv50_instobj(p) container_of((p), struct nv50_instobj, memory) +#define nv50_instobj(p) container_of((p), struct nv50_instobj, base.memory) struct nv50_instobj { - struct nvkm_memory memory; + struct nvkm_instobj base; struct nv50_instmem *imem; - struct nvkm_mem *mem; - struct nvkm_vma bar; + struct nvkm_memory *ram; + struct nvkm_vma *bar; + refcount_t maps; void *map; + struct list_head lru; }; -static enum nvkm_memory_target -nv50_instobj_target(struct nvkm_memory *memory) +static void +nv50_instobj_wr32_slow(struct nvkm_memory *memory, u64 offset, u32 data) { - return NVKM_MEM_TARGET_VRAM; + struct nv50_instobj *iobj = nv50_instobj(memory); + struct nv50_instmem *imem = iobj->imem; + struct nvkm_device *device = imem->base.subdev.device; + u64 base = (nvkm_memory_addr(iobj->ram) + offset) & 0xffffff00000ULL; + u64 addr = (nvkm_memory_addr(iobj->ram) + offset) & 0x000000fffffULL; + unsigned long flags; + + spin_lock_irqsave(&imem->base.lock, flags); + if (unlikely(imem->addr != base)) { + nvkm_wr32(device, 0x001700, base >> 16); + imem->addr = base; + } + nvkm_wr32(device, 0x700000 + addr, data); + spin_unlock_irqrestore(&imem->base.lock, flags); } -static u64 -nv50_instobj_addr(struct nvkm_memory *memory) +static u32 +nv50_instobj_rd32_slow(struct nvkm_memory *memory, u64 offset) { - return nv50_instobj(memory)->mem->offset; + struct nv50_instobj *iobj = nv50_instobj(memory); + struct nv50_instmem *imem = iobj->imem; + struct nvkm_device *device = imem->base.subdev.device; + u64 base = (nvkm_memory_addr(iobj->ram) + offset) & 0xffffff00000ULL; + u64 addr = (nvkm_memory_addr(iobj->ram) + offset) & 0x000000fffffULL; + u32 data; + unsigned long flags; + + spin_lock_irqsave(&imem->base.lock, flags); + if (unlikely(imem->addr != base)) { + nvkm_wr32(device, 0x001700, base >> 16); + imem->addr = base; + } + data = nvkm_rd32(device, 0x700000 + addr); + spin_unlock_irqrestore(&imem->base.lock, flags); + return data; } -static u64 -nv50_instobj_size(struct nvkm_memory *memory) +static const struct nvkm_memory_ptrs +nv50_instobj_slow = { + .rd32 = nv50_instobj_rd32_slow, + .wr32 = nv50_instobj_wr32_slow, +}; + +static void +nv50_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) { - return (u64)nv50_instobj(memory)->mem->size << NVKM_RAM_MM_SHIFT; + iowrite32_native(data, nv50_instobj(memory)->map + offset); } +static u32 +nv50_instobj_rd32(struct nvkm_memory *memory, u64 offset) +{ + return ioread32_native(nv50_instobj(memory)->map + offset); +} + +static const struct nvkm_memory_ptrs +nv50_instobj_fast = { + .rd32 = nv50_instobj_rd32, + .wr32 = nv50_instobj_wr32, +}; + static void -nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vm *vm) +nv50_instobj_kmap(struct nv50_instobj *iobj, struct nvkm_vmm *vmm) { - struct nv50_instobj *iobj = nv50_instobj(memory); - struct nvkm_subdev *subdev = &iobj->imem->base.subdev; + struct nv50_instmem *imem = iobj->imem; + struct nv50_instobj *eobj; + struct nvkm_memory *memory = &iobj->base.memory; + struct nvkm_subdev *subdev = &imem->base.subdev; struct nvkm_device *device = subdev->device; + struct nvkm_vma *bar = NULL, *ebar; u64 size = nvkm_memory_size(memory); - void __iomem *map; + void *emap; int ret; - iobj->map = ERR_PTR(-ENOMEM); - - ret = nvkm_vm_get(vm, size, 12, NV_MEM_ACCESS_RW, &iobj->bar); - if (ret == 0) { - map = ioremap(device->func->resource_addr(device, 3) + - (u32)iobj->bar.offset, size); - if (map) { - nvkm_memory_map(memory, &iobj->bar, 0); - iobj->map = map; - } else { - nvkm_warn(subdev, "PRAMIN ioremap failed\n"); - nvkm_vm_put(&iobj->bar); + /* Attempt to allocate BAR2 address-space and map the object + * into it. The lock has to be dropped while doing this due + * to the possibility of recursion for page table allocation. + */ + mutex_unlock(&subdev->mutex); + while ((ret = nvkm_vmm_get(vmm, 12, size, &bar))) { + /* Evict unused mappings, and keep retrying until we either + * succeed,or there's no more objects left on the LRU. + */ + mutex_lock(&subdev->mutex); + eobj = list_first_entry_or_null(&imem->lru, typeof(*eobj), lru); + if (eobj) { + nvkm_debug(subdev, "evict %016llx %016llx @ %016llx\n", + nvkm_memory_addr(&eobj->base.memory), + nvkm_memory_size(&eobj->base.memory), + eobj->bar->addr); + list_del_init(&eobj->lru); + ebar = eobj->bar; + eobj->bar = NULL; + emap = eobj->map; + eobj->map = NULL; } - } else { - nvkm_warn(subdev, "PRAMIN exhausted\n"); + mutex_unlock(&subdev->mutex); + if (!eobj) + break; + iounmap(emap); + nvkm_vmm_put(vmm, &ebar); } + + if (ret == 0) + ret = nvkm_memory_map(memory, 0, vmm, bar, NULL, 0); + mutex_lock(&subdev->mutex); + if (ret || iobj->bar) { + /* We either failed, or another thread beat us. */ + mutex_unlock(&subdev->mutex); + nvkm_vmm_put(vmm, &bar); + mutex_lock(&subdev->mutex); + return; + } + + /* Make the mapping visible to the host. */ + iobj->bar = bar; + iobj->map = ioremap_wc(device->func->resource_addr(device, 3) + + (u32)iobj->bar->addr, size); + if (!iobj->map) { + nvkm_warn(subdev, "PRAMIN ioremap failed\n"); + nvkm_vmm_put(vmm, &iobj->bar); + } +} + +static int +nv50_instobj_map(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, + struct nvkm_vma *vma, void *argv, u32 argc) +{ + memory = nv50_instobj(memory)->ram; + return nvkm_memory_map(memory, offset, vmm, vma, argv, argc); } static void nv50_instobj_release(struct nvkm_memory *memory) { - struct nv50_instmem *imem = nv50_instobj(memory)->imem; - spin_unlock_irqrestore(&imem->lock, imem->lock_flags); + struct nv50_instobj *iobj = nv50_instobj(memory); + struct nv50_instmem *imem = iobj->imem; + struct nvkm_subdev *subdev = &imem->base.subdev; + + wmb(); + nvkm_bar_flush(subdev->device->bar); + + if (refcount_dec_and_mutex_lock(&iobj->maps, &subdev->mutex)) { + /* Add the now-unused mapping to the LRU instead of directly + * unmapping it here, in case we need to map it again later. + */ + if (likely(iobj->lru.next) && iobj->map) { + BUG_ON(!list_empty(&iobj->lru)); + list_add_tail(&iobj->lru, &imem->lru); + } + + /* Switch back to NULL accessors when last map is gone. */ + iobj->base.memory.ptrs = NULL; + mutex_unlock(&subdev->mutex); + } } static void __iomem * nv50_instobj_acquire(struct nvkm_memory *memory) { struct nv50_instobj *iobj = nv50_instobj(memory); - struct nv50_instmem *imem = iobj->imem; - struct nvkm_bar *bar = imem->base.subdev.device->bar; - struct nvkm_vm *vm; - unsigned long flags; + struct nvkm_instmem *imem = &iobj->imem->base; + struct nvkm_vmm *vmm; + void __iomem *map = NULL; - if (!iobj->map && (vm = nvkm_bar_kmap(bar))) - nvkm_memory_boot(memory, vm); - if (!IS_ERR_OR_NULL(iobj->map)) + /* Already mapped? */ + if (refcount_inc_not_zero(&iobj->maps)) return iobj->map; - spin_lock_irqsave(&imem->lock, flags); - imem->lock_flags = flags; - return NULL; -} + /* Take the lock, and re-check that another thread hasn't + * already mapped the object in the meantime. + */ + mutex_lock(&imem->subdev.mutex); + if (refcount_inc_not_zero(&iobj->maps)) { + mutex_unlock(&imem->subdev.mutex); + return iobj->map; + } -static u32 -nv50_instobj_rd32(struct nvkm_memory *memory, u64 offset) -{ - struct nv50_instobj *iobj = nv50_instobj(memory); - struct nv50_instmem *imem = iobj->imem; - struct nvkm_device *device = imem->base.subdev.device; - u64 base = (iobj->mem->offset + offset) & 0xffffff00000ULL; - u64 addr = (iobj->mem->offset + offset) & 0x000000fffffULL; - u32 data; + /* Attempt to get a direct CPU mapping of the object. */ + if ((vmm = nvkm_bar_bar2_vmm(imem->subdev.device))) { + if (!iobj->map) + nv50_instobj_kmap(iobj, vmm); + map = iobj->map; + } - if (unlikely(imem->addr != base)) { - nvkm_wr32(device, 0x001700, base >> 16); - imem->addr = base; + if (!refcount_inc_not_zero(&iobj->maps)) { + /* Exclude object from eviction while it's being accessed. */ + if (likely(iobj->lru.next)) + list_del_init(&iobj->lru); + + if (map) + iobj->base.memory.ptrs = &nv50_instobj_fast; + else + iobj->base.memory.ptrs = &nv50_instobj_slow; + refcount_inc(&iobj->maps); } - data = nvkm_rd32(device, 0x700000 + addr); - return data; + + mutex_unlock(&imem->subdev.mutex); + return map; } static void -nv50_instobj_wr32(struct nvkm_memory *memory, u64 offset, u32 data) +nv50_instobj_boot(struct nvkm_memory *memory, struct nvkm_vmm *vmm) { struct nv50_instobj *iobj = nv50_instobj(memory); - struct nv50_instmem *imem = iobj->imem; - struct nvkm_device *device = imem->base.subdev.device; - u64 base = (iobj->mem->offset + offset) & 0xffffff00000ULL; - u64 addr = (iobj->mem->offset + offset) & 0x000000fffffULL; - - if (unlikely(imem->addr != base)) { - nvkm_wr32(device, 0x001700, base >> 16); - imem->addr = base; + struct nvkm_instmem *imem = &iobj->imem->base; + + /* Exclude bootstrapped objects (ie. the page tables for the + * instmem BAR itself) from eviction. + */ + mutex_lock(&imem->subdev.mutex); + if (likely(iobj->lru.next)) { + list_del_init(&iobj->lru); + iobj->lru.next = NULL; } - nvkm_wr32(device, 0x700000 + addr, data); + + nv50_instobj_kmap(iobj, vmm); + nvkm_instmem_boot(imem); + mutex_unlock(&imem->subdev.mutex); } -static void -nv50_instobj_map(struct nvkm_memory *memory, struct nvkm_vma *vma, u64 offset) +static u64 +nv50_instobj_size(struct nvkm_memory *memory) { - struct nv50_instobj *iobj = nv50_instobj(memory); - nvkm_vm_map_at(vma, offset, iobj->mem); + return nvkm_memory_size(nv50_instobj(memory)->ram); +} + +static u64 +nv50_instobj_addr(struct nvkm_memory *memory) +{ + return nvkm_memory_addr(nv50_instobj(memory)->ram); +} + +static enum nvkm_memory_target +nv50_instobj_target(struct nvkm_memory *memory) +{ + return nvkm_memory_target(nv50_instobj(memory)->ram); } static void * nv50_instobj_dtor(struct nvkm_memory *memory) { struct nv50_instobj *iobj = nv50_instobj(memory); - struct nvkm_ram *ram = iobj->imem->base.subdev.device->fb->ram; - if (!IS_ERR_OR_NULL(iobj->map)) { - nvkm_vm_put(&iobj->bar); - iounmap(iobj->map); + struct nvkm_instmem *imem = &iobj->imem->base; + struct nvkm_vma *bar; + void *map = map; + + mutex_lock(&imem->subdev.mutex); + if (likely(iobj->lru.next)) + list_del(&iobj->lru); + map = iobj->map; + bar = iobj->bar; + mutex_unlock(&imem->subdev.mutex); + + if (map) { + struct nvkm_vmm *vmm = nvkm_bar_bar2_vmm(imem->subdev.device); + iounmap(map); + if (likely(vmm)) /* Can be NULL during BAR destructor. */ + nvkm_vmm_put(vmm, &bar); } - ram->func->put(ram, &iobj->mem); + + nvkm_memory_unref(&iobj->ram); + nvkm_instobj_dtor(imem, &iobj->base); return iobj; } @@ -184,8 +330,6 @@ nv50_instobj_func = { .boot = nv50_instobj_boot, .acquire = nv50_instobj_acquire, .release = nv50_instobj_release, - .rd32 = nv50_instobj_rd32, - .wr32 = nv50_instobj_wr32, .map = nv50_instobj_map, }; @@ -195,25 +339,19 @@ nv50_instobj_new(struct nvkm_instmem *base, u32 size, u32 align, bool zero, { struct nv50_instmem *imem = nv50_instmem(base); struct nv50_instobj *iobj; - struct nvkm_ram *ram = imem->base.subdev.device->fb->ram; - int ret; + struct nvkm_device *device = imem->base.subdev.device; + u8 page = max(order_base_2(align), 12); if (!(iobj = kzalloc(sizeof(*iobj), GFP_KERNEL))) return -ENOMEM; - *pmemory = &iobj->memory; + *pmemory = &iobj->base.memory; - nvkm_memory_ctor(&nv50_instobj_func, &iobj->memory); + nvkm_instobj_ctor(&nv50_instobj_func, &imem->base, &iobj->base); iobj->imem = imem; + refcount_set(&iobj->maps, 0); + INIT_LIST_HEAD(&iobj->lru); - size = max((size + 4095) & ~4095, (u32)4096); - align = max((align + 4095) & ~4095, (u32)4096); - - ret = ram->func->get(ram, size, align, 0, 0x800, &iobj->mem); - if (ret) - return ret; - - iobj->mem->page_shift = 12; - return 0; + return nvkm_ram_get(device, 0, 1, page, size, true, true, &iobj->ram); } /****************************************************************************** @@ -230,7 +368,6 @@ static const struct nvkm_instmem_func nv50_instmem = { .fini = nv50_instmem_fini, .memory_new = nv50_instobj_new, - .persistent = false, .zero = false, }; @@ -243,7 +380,7 @@ nv50_instmem_new(struct nvkm_device *device, int index, if (!(imem = kzalloc(sizeof(*imem), GFP_KERNEL))) return -ENOMEM; nvkm_instmem_ctor(&nv50_instmem, device, index, &imem->base); - spin_lock_init(&imem->lock); + INIT_LIST_HEAD(&imem->lru); *pimem = &imem->base; return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h index ace4471864a3..44651ca42d52 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/priv.h @@ -11,10 +11,22 @@ struct nvkm_instmem_func { void (*wr32)(struct nvkm_instmem *, u32 addr, u32 data); int (*memory_new)(struct nvkm_instmem *, u32 size, u32 align, bool zero, struct nvkm_memory **); - bool persistent; bool zero; }; void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *, int index, struct nvkm_instmem *); +void nvkm_instmem_boot(struct nvkm_instmem *); + +#include <core/memory.h> + +struct nvkm_instobj { + struct nvkm_memory memory; + struct list_head head; + u32 *suspend; +}; + +void nvkm_instobj_ctor(const struct nvkm_memory_func *func, + struct nvkm_instmem *, struct nvkm_instobj *); +void nvkm_instobj_dtor(struct nvkm_instmem *, struct nvkm_instobj *); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c index 0c7ef250dcaf..1f185274d3e6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/base.c @@ -23,26 +23,12 @@ */ #include "priv.h" -#include <subdev/fb.h> - -int -nvkm_ltc_tags_alloc(struct nvkm_ltc *ltc, u32 n, struct nvkm_mm_node **pnode) -{ - int ret = nvkm_mm_head(<c->tags, 0, 1, n, n, 1, pnode); - if (ret) - *pnode = NULL; - return ret; -} - -void -nvkm_ltc_tags_free(struct nvkm_ltc *ltc, struct nvkm_mm_node **pnode) -{ - nvkm_mm_free(<c->tags, pnode); -} +#include <core/memory.h> void -nvkm_ltc_tags_clear(struct nvkm_ltc *ltc, u32 first, u32 count) +nvkm_ltc_tags_clear(struct nvkm_device *device, u32 first, u32 count) { + struct nvkm_ltc *ltc = device->ltc; const u32 limit = first + count - 1; BUG_ON((first > limit) || (limit >= ltc->num_tags)); @@ -116,10 +102,7 @@ static void * nvkm_ltc_dtor(struct nvkm_subdev *subdev) { struct nvkm_ltc *ltc = nvkm_ltc(subdev); - struct nvkm_ram *ram = ltc->subdev.device->fb->ram; - nvkm_mm_fini(<c->tags); - if (ram) - nvkm_mm_free(&ram->vram, <c->tag_ram); + nvkm_memory_unref(<c->tag_ram); return ltc; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c index 4a0fa0a9b802..a21ef45b8572 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gf100.c @@ -23,6 +23,7 @@ */ #include "priv.h" +#include <core/memory.h> #include <subdev/fb.h> #include <subdev/timer.h> @@ -152,7 +153,10 @@ gf100_ltc_flush(struct nvkm_ltc *ltc) int gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc) { - struct nvkm_ram *ram = ltc->subdev.device->fb->ram; + struct nvkm_device *device = ltc->subdev.device; + struct nvkm_fb *fb = device->fb; + struct nvkm_ram *ram = fb->ram; + u32 bits = (nvkm_rd32(device, 0x100c80) & 0x00001000) ? 16 : 17; u32 tag_size, tag_margin, tag_align; int ret; @@ -164,8 +168,8 @@ gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc) /* tags for 1/4 of VRAM should be enough (8192/4 per GiB of VRAM) */ ltc->num_tags = (ram->size >> 17) / 4; - if (ltc->num_tags > (1 << 17)) - ltc->num_tags = 1 << 17; /* we have 17 bits in PTE */ + if (ltc->num_tags > (1 << bits)) + ltc->num_tags = 1 << bits; /* we have 16/17 bits in PTE */ ltc->num_tags = (ltc->num_tags + 63) & ~63; /* round up to 64 */ tag_align = ltc->ltc_nr * 0x800; @@ -181,14 +185,13 @@ gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc) */ tag_size = (ltc->num_tags / 64) * 0x6000 + tag_margin; tag_size += tag_align; - tag_size = (tag_size + 0xfff) >> 12; /* round up */ - ret = nvkm_mm_tail(&ram->vram, 1, 1, tag_size, tag_size, 1, - <c->tag_ram); + ret = nvkm_ram_get(device, NVKM_RAM_MM_NORMAL, 0x01, 12, tag_size, + true, true, <c->tag_ram); if (ret) { ltc->num_tags = 0; } else { - u64 tag_base = ((u64)ltc->tag_ram->offset << 12) + tag_margin; + u64 tag_base = nvkm_memory_addr(ltc->tag_ram) + tag_margin; tag_base += tag_align - 1; do_div(tag_base, tag_align); @@ -197,7 +200,8 @@ gf100_ltc_oneinit_tag_ram(struct nvkm_ltc *ltc) } mm_init: - return nvkm_mm_init(<c->tags, 0, ltc->num_tags, 1); + nvkm_mm_fini(&fb->tags); + return nvkm_mm_init(&fb->tags, 0, 0, ltc->num_tags, 1); } int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c index 0bdfb2f40266..e34d42108019 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/ltc/gp100.c @@ -45,7 +45,7 @@ gp100_ltc_oneinit(struct nvkm_ltc *ltc) ltc->ltc_nr = nvkm_rd32(device, 0x12006c); ltc->lts_nr = nvkm_rd32(device, 0x17e280) >> 28; /*XXX: tagram allocation - TBD */ - return nvkm_mm_init(<c->tags, 0, 0, 1); + return 0; } static void diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild index 012c9db687b2..352a65f9371c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/Kbuild @@ -3,4 +3,33 @@ nvkm-y += nvkm/subdev/mmu/nv04.o nvkm-y += nvkm/subdev/mmu/nv41.o nvkm-y += nvkm/subdev/mmu/nv44.o nvkm-y += nvkm/subdev/mmu/nv50.o +nvkm-y += nvkm/subdev/mmu/g84.o nvkm-y += nvkm/subdev/mmu/gf100.o +nvkm-y += nvkm/subdev/mmu/gk104.o +nvkm-y += nvkm/subdev/mmu/gk20a.o +nvkm-y += nvkm/subdev/mmu/gm200.o +nvkm-y += nvkm/subdev/mmu/gm20b.o +nvkm-y += nvkm/subdev/mmu/gp100.o +nvkm-y += nvkm/subdev/mmu/gp10b.o + +nvkm-y += nvkm/subdev/mmu/mem.o +nvkm-y += nvkm/subdev/mmu/memnv04.o +nvkm-y += nvkm/subdev/mmu/memnv50.o +nvkm-y += nvkm/subdev/mmu/memgf100.o + +nvkm-y += nvkm/subdev/mmu/vmm.o +nvkm-y += nvkm/subdev/mmu/vmmnv04.o +nvkm-y += nvkm/subdev/mmu/vmmnv41.o +nvkm-y += nvkm/subdev/mmu/vmmnv44.o +nvkm-y += nvkm/subdev/mmu/vmmnv50.o +nvkm-y += nvkm/subdev/mmu/vmmgf100.o +nvkm-y += nvkm/subdev/mmu/vmmgk104.o +nvkm-y += nvkm/subdev/mmu/vmmgk20a.o +nvkm-y += nvkm/subdev/mmu/vmmgm200.o +nvkm-y += nvkm/subdev/mmu/vmmgm20b.o +nvkm-y += nvkm/subdev/mmu/vmmgp100.o +nvkm-y += nvkm/subdev/mmu/vmmgp10b.o + +nvkm-y += nvkm/subdev/mmu/umem.o +nvkm-y += nvkm/subdev/mmu/ummu.o +nvkm-y += nvkm/subdev/mmu/uvmm.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c index d06ad2c372bf..ee11ccaf0563 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/base.c @@ -21,478 +21,367 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "ummu.h" +#include "vmm.h" -#include <core/gpuobj.h> +#include <subdev/bar.h> #include <subdev/fb.h> -void -nvkm_vm_map_at(struct nvkm_vma *vma, u64 delta, struct nvkm_mem *node) -{ - struct nvkm_vm *vm = vma->vm; - struct nvkm_mmu *mmu = vm->mmu; - struct nvkm_mm_node *r = node->mem; - int big = vma->node->type != mmu->func->spg_shift; - u32 offset = vma->node->offset + (delta >> 12); - u32 bits = vma->node->type - 12; - u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; - u32 max = 1 << (mmu->func->pgt_bits - bits); - u32 end, len; - - delta = 0; - while (r) { - u64 phys = (u64)r->offset << 12; - u32 num = r->length >> bits; - - while (num) { - struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; - - end = (pte + num); - if (unlikely(end >= max)) - end = max; - len = end - pte; - - mmu->func->map(vma, pgt, node, pte, len, phys, delta); - - num -= len; - pte += len; - if (unlikely(end >= max)) { - phys += len << (bits + 12); - pde++; - pte = 0; - } - - delta += (u64)len << vma->node->type; - } - r = r->next; - }; +#include <nvif/if500d.h> +#include <nvif/if900d.h> - mmu->func->flush(vm); -} +struct nvkm_mmu_ptp { + struct nvkm_mmu_pt *pt; + struct list_head head; + u8 shift; + u16 mask; + u16 free; +}; static void -nvkm_vm_map_sg_table(struct nvkm_vma *vma, u64 delta, u64 length, - struct nvkm_mem *mem) +nvkm_mmu_ptp_put(struct nvkm_mmu *mmu, bool force, struct nvkm_mmu_pt *pt) { - struct nvkm_vm *vm = vma->vm; - struct nvkm_mmu *mmu = vm->mmu; - int big = vma->node->type != mmu->func->spg_shift; - u32 offset = vma->node->offset + (delta >> 12); - u32 bits = vma->node->type - 12; - u32 num = length >> vma->node->type; - u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; - u32 max = 1 << (mmu->func->pgt_bits - bits); - unsigned m, sglen; - u32 end, len; - int i; - struct scatterlist *sg; - - for_each_sg(mem->sg->sgl, sg, mem->sg->nents, i) { - struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; - sglen = sg_dma_len(sg) >> PAGE_SHIFT; - - end = pte + sglen; - if (unlikely(end >= max)) - end = max; - len = end - pte; - - for (m = 0; m < len; m++) { - dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); - - mmu->func->map_sg(vma, pgt, mem, pte, 1, &addr); - num--; - pte++; - - if (num == 0) - goto finish; - } - if (unlikely(end >= max)) { - pde++; - pte = 0; - } - if (m < sglen) { - for (; m < sglen; m++) { - dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); - - mmu->func->map_sg(vma, pgt, mem, pte, 1, &addr); - num--; - pte++; - if (num == 0) - goto finish; - } - } - + const int slot = pt->base >> pt->ptp->shift; + struct nvkm_mmu_ptp *ptp = pt->ptp; + + /* If there were no free slots in the parent allocation before, + * there will be now, so return PTP to the cache. + */ + if (!ptp->free) + list_add(&ptp->head, &mmu->ptp.list); + ptp->free |= BIT(slot); + + /* If there's no more sub-allocations, destroy PTP. */ + if (ptp->free == ptp->mask) { + nvkm_mmu_ptc_put(mmu, force, &ptp->pt); + list_del(&ptp->head); + kfree(ptp); } -finish: - mmu->func->flush(vm); + + kfree(pt); } -static void -nvkm_vm_map_sg(struct nvkm_vma *vma, u64 delta, u64 length, - struct nvkm_mem *mem) +struct nvkm_mmu_pt * +nvkm_mmu_ptp_get(struct nvkm_mmu *mmu, u32 size, bool zero) { - struct nvkm_vm *vm = vma->vm; - struct nvkm_mmu *mmu = vm->mmu; - dma_addr_t *list = mem->pages; - int big = vma->node->type != mmu->func->spg_shift; - u32 offset = vma->node->offset + (delta >> 12); - u32 bits = vma->node->type - 12; - u32 num = length >> vma->node->type; - u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; - u32 max = 1 << (mmu->func->pgt_bits - bits); - u32 end, len; - - while (num) { - struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; - - end = (pte + num); - if (unlikely(end >= max)) - end = max; - len = end - pte; - - mmu->func->map_sg(vma, pgt, mem, pte, len, list); - - num -= len; - pte += len; - list += len; - if (unlikely(end >= max)) { - pde++; - pte = 0; + struct nvkm_mmu_pt *pt; + struct nvkm_mmu_ptp *ptp; + int slot; + + if (!(pt = kzalloc(sizeof(*pt), GFP_KERNEL))) + return NULL; + + ptp = list_first_entry_or_null(&mmu->ptp.list, typeof(*ptp), head); + if (!ptp) { + /* Need to allocate a new parent to sub-allocate from. */ + if (!(ptp = kmalloc(sizeof(*ptp), GFP_KERNEL))) { + kfree(pt); + return NULL; } - } - mmu->func->flush(vm); -} + ptp->pt = nvkm_mmu_ptc_get(mmu, 0x1000, 0x1000, false); + if (!ptp->pt) { + kfree(ptp); + kfree(pt); + return NULL; + } -void -nvkm_vm_map(struct nvkm_vma *vma, struct nvkm_mem *node) -{ - if (node->sg) - nvkm_vm_map_sg_table(vma, 0, node->size << 12, node); - else - if (node->pages) - nvkm_vm_map_sg(vma, 0, node->size << 12, node); - else - nvkm_vm_map_at(vma, 0, node); + ptp->shift = order_base_2(size); + slot = nvkm_memory_size(ptp->pt->memory) >> ptp->shift; + ptp->mask = (1 << slot) - 1; + ptp->free = ptp->mask; + list_add(&ptp->head, &mmu->ptp.list); + } + pt->ptp = ptp; + pt->sub = true; + + /* Sub-allocate from parent object, removing PTP from cache + * if there's no more free slots left. + */ + slot = __ffs(ptp->free); + ptp->free &= ~BIT(slot); + if (!ptp->free) + list_del(&ptp->head); + + pt->memory = pt->ptp->pt->memory; + pt->base = slot << ptp->shift; + pt->addr = pt->ptp->pt->addr + pt->base; + return pt; } -void -nvkm_vm_unmap_at(struct nvkm_vma *vma, u64 delta, u64 length) +struct nvkm_mmu_ptc { + struct list_head head; + struct list_head item; + u32 size; + u32 refs; +}; + +static inline struct nvkm_mmu_ptc * +nvkm_mmu_ptc_find(struct nvkm_mmu *mmu, u32 size) { - struct nvkm_vm *vm = vma->vm; - struct nvkm_mmu *mmu = vm->mmu; - int big = vma->node->type != mmu->func->spg_shift; - u32 offset = vma->node->offset + (delta >> 12); - u32 bits = vma->node->type - 12; - u32 num = length >> vma->node->type; - u32 pde = (offset >> mmu->func->pgt_bits) - vm->fpde; - u32 pte = (offset & ((1 << mmu->func->pgt_bits) - 1)) >> bits; - u32 max = 1 << (mmu->func->pgt_bits - bits); - u32 end, len; - - while (num) { - struct nvkm_memory *pgt = vm->pgt[pde].mem[big]; - - end = (pte + num); - if (unlikely(end >= max)) - end = max; - len = end - pte; - - mmu->func->unmap(vma, pgt, pte, len); - - num -= len; - pte += len; - if (unlikely(end >= max)) { - pde++; - pte = 0; - } + struct nvkm_mmu_ptc *ptc; + + list_for_each_entry(ptc, &mmu->ptc.list, head) { + if (ptc->size == size) + return ptc; } - mmu->func->flush(vm); -} + ptc = kmalloc(sizeof(*ptc), GFP_KERNEL); + if (ptc) { + INIT_LIST_HEAD(&ptc->item); + ptc->size = size; + ptc->refs = 0; + list_add(&ptc->head, &mmu->ptc.list); + } -void -nvkm_vm_unmap(struct nvkm_vma *vma) -{ - nvkm_vm_unmap_at(vma, 0, (u64)vma->node->length << 12); + return ptc; } -static void -nvkm_vm_unmap_pgt(struct nvkm_vm *vm, int big, u32 fpde, u32 lpde) +void +nvkm_mmu_ptc_put(struct nvkm_mmu *mmu, bool force, struct nvkm_mmu_pt **ppt) { - struct nvkm_mmu *mmu = vm->mmu; - struct nvkm_vm_pgd *vpgd; - struct nvkm_vm_pgt *vpgt; - struct nvkm_memory *pgt; - u32 pde; - - for (pde = fpde; pde <= lpde; pde++) { - vpgt = &vm->pgt[pde - vm->fpde]; - if (--vpgt->refcount[big]) - continue; - - pgt = vpgt->mem[big]; - vpgt->mem[big] = NULL; - - list_for_each_entry(vpgd, &vm->pgd_list, head) { - mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem); + struct nvkm_mmu_pt *pt = *ppt; + if (pt) { + /* Handle sub-allocated page tables. */ + if (pt->sub) { + mutex_lock(&mmu->ptp.mutex); + nvkm_mmu_ptp_put(mmu, force, pt); + mutex_unlock(&mmu->ptp.mutex); + return; } - nvkm_memory_del(&pgt); + /* Either cache or free the object. */ + mutex_lock(&mmu->ptc.mutex); + if (pt->ptc->refs < 8 /* Heuristic. */ && !force) { + list_add_tail(&pt->head, &pt->ptc->item); + pt->ptc->refs++; + } else { + nvkm_memory_unref(&pt->memory); + kfree(pt); + } + mutex_unlock(&mmu->ptc.mutex); } } -static int -nvkm_vm_map_pgt(struct nvkm_vm *vm, u32 pde, u32 type) +struct nvkm_mmu_pt * +nvkm_mmu_ptc_get(struct nvkm_mmu *mmu, u32 size, u32 align, bool zero) { - struct nvkm_mmu *mmu = vm->mmu; - struct nvkm_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; - struct nvkm_vm_pgd *vpgd; - int big = (type != mmu->func->spg_shift); - u32 pgt_size; + struct nvkm_mmu_ptc *ptc; + struct nvkm_mmu_pt *pt; int ret; - pgt_size = (1 << (mmu->func->pgt_bits + 12)) >> type; - pgt_size *= 8; - - ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST, - pgt_size, 0x1000, true, &vpgt->mem[big]); - if (unlikely(ret)) - return ret; - - list_for_each_entry(vpgd, &vm->pgd_list, head) { - mmu->func->map_pgt(vpgd->obj, pde, vpgt->mem); + /* Sub-allocated page table (ie. GP100 LPT). */ + if (align < 0x1000) { + mutex_lock(&mmu->ptp.mutex); + pt = nvkm_mmu_ptp_get(mmu, align, zero); + mutex_unlock(&mmu->ptp.mutex); + return pt; } - vpgt->refcount[big]++; - return 0; -} - -int -nvkm_vm_get(struct nvkm_vm *vm, u64 size, u32 page_shift, u32 access, - struct nvkm_vma *vma) -{ - struct nvkm_mmu *mmu = vm->mmu; - u32 align = (1 << page_shift) >> 12; - u32 msize = size >> 12; - u32 fpde, lpde, pde; - int ret; - - mutex_lock(&vm->mutex); - ret = nvkm_mm_head(&vm->mm, 0, page_shift, msize, msize, align, - &vma->node); - if (unlikely(ret != 0)) { - mutex_unlock(&vm->mutex); - return ret; + /* Lookup cache for this page table size. */ + mutex_lock(&mmu->ptc.mutex); + ptc = nvkm_mmu_ptc_find(mmu, size); + if (!ptc) { + mutex_unlock(&mmu->ptc.mutex); + return NULL; } - fpde = (vma->node->offset >> mmu->func->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits; - - for (pde = fpde; pde <= lpde; pde++) { - struct nvkm_vm_pgt *vpgt = &vm->pgt[pde - vm->fpde]; - int big = (vma->node->type != mmu->func->spg_shift); + /* If there's a free PT in the cache, reuse it. */ + pt = list_first_entry_or_null(&ptc->item, typeof(*pt), head); + if (pt) { + if (zero) + nvkm_fo64(pt->memory, 0, 0, size >> 3); + list_del(&pt->head); + ptc->refs--; + mutex_unlock(&mmu->ptc.mutex); + return pt; + } + mutex_unlock(&mmu->ptc.mutex); - if (likely(vpgt->refcount[big])) { - vpgt->refcount[big]++; - continue; - } + /* No such luck, we need to allocate. */ + if (!(pt = kmalloc(sizeof(*pt), GFP_KERNEL))) + return NULL; + pt->ptc = ptc; + pt->sub = false; - ret = nvkm_vm_map_pgt(vm, pde, vma->node->type); - if (ret) { - if (pde != fpde) - nvkm_vm_unmap_pgt(vm, big, fpde, pde - 1); - nvkm_mm_free(&vm->mm, &vma->node); - mutex_unlock(&vm->mutex); - return ret; - } + ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST, + size, align, zero, &pt->memory); + if (ret) { + kfree(pt); + return NULL; } - mutex_unlock(&vm->mutex); - vma->vm = NULL; - nvkm_vm_ref(vm, &vma->vm, NULL); - vma->offset = (u64)vma->node->offset << 12; - vma->access = access; - return 0; + pt->base = 0; + pt->addr = nvkm_memory_addr(pt->memory); + return pt; } void -nvkm_vm_put(struct nvkm_vma *vma) +nvkm_mmu_ptc_dump(struct nvkm_mmu *mmu) { - struct nvkm_mmu *mmu; - struct nvkm_vm *vm; - u32 fpde, lpde; - - if (unlikely(vma->node == NULL)) - return; - vm = vma->vm; - mmu = vm->mmu; - - fpde = (vma->node->offset >> mmu->func->pgt_bits); - lpde = (vma->node->offset + vma->node->length - 1) >> mmu->func->pgt_bits; - - mutex_lock(&vm->mutex); - nvkm_vm_unmap_pgt(vm, vma->node->type != mmu->func->spg_shift, fpde, lpde); - nvkm_mm_free(&vm->mm, &vma->node); - mutex_unlock(&vm->mutex); - - nvkm_vm_ref(NULL, &vma->vm, NULL); -} - -int -nvkm_vm_boot(struct nvkm_vm *vm, u64 size) -{ - struct nvkm_mmu *mmu = vm->mmu; - struct nvkm_memory *pgt; - int ret; - - ret = nvkm_memory_new(mmu->subdev.device, NVKM_MEM_TARGET_INST, - (size >> mmu->func->spg_shift) * 8, 0x1000, true, &pgt); - if (ret == 0) { - vm->pgt[0].refcount[0] = 1; - vm->pgt[0].mem[0] = pgt; - nvkm_memory_boot(pgt, vm); + struct nvkm_mmu_ptc *ptc; + list_for_each_entry(ptc, &mmu->ptc.list, head) { + struct nvkm_mmu_pt *pt, *tt; + list_for_each_entry_safe(pt, tt, &ptc->item, head) { + nvkm_memory_unref(&pt->memory); + list_del(&pt->head); + kfree(pt); + } } - - return ret; } -int -nvkm_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, - u32 block, struct lock_class_key *key, struct nvkm_vm **pvm) +static void +nvkm_mmu_ptc_fini(struct nvkm_mmu *mmu) { - static struct lock_class_key _key; - struct nvkm_vm *vm; - u64 mm_length = (offset + length) - mm_offset; - int ret; - - vm = kzalloc(sizeof(*vm), GFP_KERNEL); - if (!vm) - return -ENOMEM; - - __mutex_init(&vm->mutex, "&vm->mutex", key ? key : &_key); - INIT_LIST_HEAD(&vm->pgd_list); - vm->mmu = mmu; - kref_init(&vm->refcount); - vm->fpde = offset >> (mmu->func->pgt_bits + 12); - vm->lpde = (offset + length - 1) >> (mmu->func->pgt_bits + 12); - - vm->pgt = vzalloc((vm->lpde - vm->fpde + 1) * sizeof(*vm->pgt)); - if (!vm->pgt) { - kfree(vm); - return -ENOMEM; - } + struct nvkm_mmu_ptc *ptc, *ptct; - ret = nvkm_mm_init(&vm->mm, mm_offset >> 12, mm_length >> 12, - block >> 12); - if (ret) { - vfree(vm->pgt); - kfree(vm); - return ret; + list_for_each_entry_safe(ptc, ptct, &mmu->ptc.list, head) { + WARN_ON(!list_empty(&ptc->item)); + list_del(&ptc->head); + kfree(ptc); } - - *pvm = vm; - - return 0; } -int -nvkm_vm_new(struct nvkm_device *device, u64 offset, u64 length, u64 mm_offset, - struct lock_class_key *key, struct nvkm_vm **pvm) +static void +nvkm_mmu_ptc_init(struct nvkm_mmu *mmu) { - struct nvkm_mmu *mmu = device->mmu; - if (!mmu->func->create) - return -EINVAL; - return mmu->func->create(mmu, offset, length, mm_offset, key, pvm); + mutex_init(&mmu->ptc.mutex); + INIT_LIST_HEAD(&mmu->ptc.list); + mutex_init(&mmu->ptp.mutex); + INIT_LIST_HEAD(&mmu->ptp.list); } -static int -nvkm_vm_link(struct nvkm_vm *vm, struct nvkm_gpuobj *pgd) +static void +nvkm_mmu_type(struct nvkm_mmu *mmu, int heap, u8 type) { - struct nvkm_mmu *mmu = vm->mmu; - struct nvkm_vm_pgd *vpgd; - int i; - - if (!pgd) - return 0; - - vpgd = kzalloc(sizeof(*vpgd), GFP_KERNEL); - if (!vpgd) - return -ENOMEM; - - vpgd->obj = pgd; - - mutex_lock(&vm->mutex); - for (i = vm->fpde; i <= vm->lpde; i++) - mmu->func->map_pgt(pgd, i, vm->pgt[i - vm->fpde].mem); - list_add(&vpgd->head, &vm->pgd_list); - mutex_unlock(&vm->mutex); - return 0; + if (heap >= 0 && !WARN_ON(mmu->type_nr == ARRAY_SIZE(mmu->type))) { + mmu->type[mmu->type_nr].type = type | mmu->heap[heap].type; + mmu->type[mmu->type_nr].heap = heap; + mmu->type_nr++; + } } -static void -nvkm_vm_unlink(struct nvkm_vm *vm, struct nvkm_gpuobj *mpgd) +static int +nvkm_mmu_heap(struct nvkm_mmu *mmu, u8 type, u64 size) { - struct nvkm_vm_pgd *vpgd, *tmp; - - if (!mpgd) - return; - - mutex_lock(&vm->mutex); - list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { - if (vpgd->obj == mpgd) { - list_del(&vpgd->head); - kfree(vpgd); - break; + if (size) { + if (!WARN_ON(mmu->heap_nr == ARRAY_SIZE(mmu->heap))) { + mmu->heap[mmu->heap_nr].type = type; + mmu->heap[mmu->heap_nr].size = size; + return mmu->heap_nr++; } } - mutex_unlock(&vm->mutex); + return -EINVAL; } static void -nvkm_vm_del(struct kref *kref) +nvkm_mmu_host(struct nvkm_mmu *mmu) { - struct nvkm_vm *vm = container_of(kref, typeof(*vm), refcount); - struct nvkm_vm_pgd *vpgd, *tmp; - - list_for_each_entry_safe(vpgd, tmp, &vm->pgd_list, head) { - nvkm_vm_unlink(vm, vpgd->obj); - } - - nvkm_mm_fini(&vm->mm); - vfree(vm->pgt); - kfree(vm); + struct nvkm_device *device = mmu->subdev.device; + u8 type = NVKM_MEM_KIND * !!mmu->func->kind_sys; + int heap; + + /* Non-mappable system memory. */ + heap = nvkm_mmu_heap(mmu, NVKM_MEM_HOST, ~0ULL); + nvkm_mmu_type(mmu, heap, type); + + /* Non-coherent, cached, system memory. + * + * Block-linear mappings of system memory must be done through + * BAR1, and cannot be supported on systems where we're unable + * to map BAR1 with write-combining. + */ + type |= NVKM_MEM_MAPPABLE; + if (!device->bar || device->bar->iomap_uncached) + nvkm_mmu_type(mmu, heap, type & ~NVKM_MEM_KIND); + else + nvkm_mmu_type(mmu, heap, type); + + /* Coherent, cached, system memory. + * + * Unsupported on systems that aren't able to support snooped + * mappings, and also for block-linear mappings which must be + * done through BAR1. + */ + type |= NVKM_MEM_COHERENT; + if (device->func->cpu_coherent) + nvkm_mmu_type(mmu, heap, type & ~NVKM_MEM_KIND); + + /* Uncached system memory. */ + nvkm_mmu_type(mmu, heap, type |= NVKM_MEM_UNCACHED); } -int -nvkm_vm_ref(struct nvkm_vm *ref, struct nvkm_vm **ptr, struct nvkm_gpuobj *pgd) +static void +nvkm_mmu_vram(struct nvkm_mmu *mmu) { - if (ref) { - int ret = nvkm_vm_link(ref, pgd); - if (ret) - return ret; - - kref_get(&ref->refcount); - } + struct nvkm_device *device = mmu->subdev.device; + struct nvkm_mm *mm = &device->fb->ram->vram; + const u32 sizeN = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NORMAL); + const u32 sizeU = nvkm_mm_heap_size(mm, NVKM_RAM_MM_NOMAP); + const u32 sizeM = nvkm_mm_heap_size(mm, NVKM_RAM_MM_MIXED); + u8 type = NVKM_MEM_KIND * !!mmu->func->kind; + u8 heap = NVKM_MEM_VRAM; + int heapM, heapN, heapU; + + /* Mixed-memory doesn't support compression or display. */ + heapM = nvkm_mmu_heap(mmu, heap, sizeM << NVKM_RAM_MM_SHIFT); + + heap |= NVKM_MEM_COMP; + heap |= NVKM_MEM_DISP; + heapN = nvkm_mmu_heap(mmu, heap, sizeN << NVKM_RAM_MM_SHIFT); + heapU = nvkm_mmu_heap(mmu, heap, sizeU << NVKM_RAM_MM_SHIFT); + + /* Add non-mappable VRAM types first so that they're preferred + * over anything else. Mixed-memory will be slower than other + * heaps, it's prioritised last. + */ + nvkm_mmu_type(mmu, heapU, type); + nvkm_mmu_type(mmu, heapN, type); + nvkm_mmu_type(mmu, heapM, type); + + /* Add host memory types next, under the assumption that users + * wanting mappable memory want to use them as staging buffers + * or the like. + */ + nvkm_mmu_host(mmu); + + /* Mappable VRAM types go last, as they're basically the worst + * possible type to ask for unless there's no other choice. + */ + if (device->bar) { + /* Write-combined BAR1 access. */ + type |= NVKM_MEM_MAPPABLE; + if (!device->bar->iomap_uncached) { + nvkm_mmu_type(mmu, heapN, type); + nvkm_mmu_type(mmu, heapM, type); + } - if (*ptr) { - nvkm_vm_unlink(*ptr, pgd); - kref_put(&(*ptr)->refcount, nvkm_vm_del); + /* Uncached BAR1 access. */ + type |= NVKM_MEM_COHERENT; + type |= NVKM_MEM_UNCACHED; + nvkm_mmu_type(mmu, heapN, type); + nvkm_mmu_type(mmu, heapM, type); } - - *ptr = ref; - return 0; } static int nvkm_mmu_oneinit(struct nvkm_subdev *subdev) { struct nvkm_mmu *mmu = nvkm_mmu(subdev); - if (mmu->func->oneinit) - return mmu->func->oneinit(mmu); + + /* Determine available memory types. */ + if (mmu->subdev.device->fb && mmu->subdev.device->fb->ram) + nvkm_mmu_vram(mmu); + else + nvkm_mmu_host(mmu); + + if (mmu->func->vmm.global) { + int ret = nvkm_vmm_new(subdev->device, 0, 0, NULL, 0, NULL, + "gart", &mmu->vmm); + if (ret) + return ret; + } + return 0; } @@ -509,8 +398,10 @@ static void * nvkm_mmu_dtor(struct nvkm_subdev *subdev) { struct nvkm_mmu *mmu = nvkm_mmu(subdev); - if (mmu->func->dtor) - return mmu->func->dtor(mmu); + + nvkm_vmm_unref(&mmu->vmm); + + nvkm_mmu_ptc_fini(mmu); return mmu; } @@ -527,9 +418,10 @@ nvkm_mmu_ctor(const struct nvkm_mmu_func *func, struct nvkm_device *device, { nvkm_subdev_ctor(&nvkm_mmu, device, index, &mmu->subdev); mmu->func = func; - mmu->limit = func->limit; mmu->dma_bits = func->dma_bits; - mmu->lpg_shift = func->lpg_shift; + nvkm_mmu_ptc_init(mmu); + mmu->user.ctor = nvkm_ummu_new; + mmu->user.base = func->mmu.user; } int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/g84.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/g84.c new file mode 100644 index 000000000000..8accda5a772b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/g84.c @@ -0,0 +1,41 @@ +/* + * 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 "mem.h" +#include "vmm.h" + +#include <nvif/class.h> + +static const struct nvkm_mmu_func +g84_mmu = { + .dma_bits = 40, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV50}}, + .mem = {{ -1, 0, NVIF_CLASS_MEM_NV50}, nv50_mem_new, nv50_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV50}, nv50_vmm_new, false, 0x0200 }, + .kind = nv50_mmu_kind, + .kind_sys = true, +}; + +int +g84_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + return nvkm_mmu_new_(&g84_mmu, device, index, pmmu); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c index 7ac507c927bb..2d075246dc46 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gf100.c @@ -21,197 +21,65 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "mem.h" +#include "vmm.h" -#include <subdev/fb.h> -#include <subdev/ltc.h> -#include <subdev/timer.h> - -#include <core/gpuobj.h> +#include <nvif/class.h> /* Map from compressed to corresponding uncompressed storage type. * The value 0xff represents an invalid storage type. */ -const u8 gf100_pte_storage_type_map[256] = -{ - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */ - 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */ - 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */ - 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */ - 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27, - 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */ - 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */ - 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */ - 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, - 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */ - 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3, - 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */ - 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, - 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */ - 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff, - 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */ - 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff -}; - - -static void -gf100_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 index, struct nvkm_memory *pgt[2]) -{ - u32 pde[2] = { 0, 0 }; - - if (pgt[0]) - pde[1] = 0x00000001 | (nvkm_memory_addr(pgt[0]) >> 8); - if (pgt[1]) - pde[0] = 0x00000001 | (nvkm_memory_addr(pgt[1]) >> 8); - - nvkm_kmap(pgd); - nvkm_wo32(pgd, (index * 8) + 0, pde[0]); - nvkm_wo32(pgd, (index * 8) + 4, pde[1]); - nvkm_done(pgd); -} - -static inline u64 -gf100_vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target) -{ - phys >>= 8; - - phys |= 0x00000001; /* present */ - if (vma->access & NV_MEM_ACCESS_SYS) - phys |= 0x00000002; - - phys |= ((u64)target << 32); - phys |= ((u64)memtype << 36); - return phys; -} - -static void -gf100_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt, - struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) -{ - u64 next = 1 << (vma->node->type - 8); - - phys = gf100_vm_addr(vma, phys, mem->memtype, 0); - pte <<= 3; - - if (mem->tag) { - struct nvkm_ltc *ltc = vma->vm->mmu->subdev.device->ltc; - u32 tag = mem->tag->offset + (delta >> 17); - phys |= (u64)tag << (32 + 12); - next |= (u64)1 << (32 + 12); - nvkm_ltc_tags_clear(ltc, tag, cnt); - } - - nvkm_kmap(pgt); - while (cnt--) { - nvkm_wo32(pgt, pte + 0, lower_32_bits(phys)); - nvkm_wo32(pgt, pte + 4, upper_32_bits(phys)); - phys += next; - pte += 8; - } - nvkm_done(pgt); -} - -static void -gf100_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, - struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) -{ - u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 7 : 5; - /* compressed storage types are invalid for system memory */ - u32 memtype = gf100_pte_storage_type_map[mem->memtype & 0xff]; - - nvkm_kmap(pgt); - pte <<= 3; - while (cnt--) { - u64 phys = gf100_vm_addr(vma, *list++, memtype, target); - nvkm_wo32(pgt, pte + 0, lower_32_bits(phys)); - nvkm_wo32(pgt, pte + 4, upper_32_bits(phys)); - pte += 8; - } - nvkm_done(pgt); -} - -static void -gf100_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) -{ - nvkm_kmap(pgt); - pte <<= 3; - while (cnt--) { - nvkm_wo32(pgt, pte + 0, 0x00000000); - nvkm_wo32(pgt, pte + 4, 0x00000000); - pte += 8; - } - nvkm_done(pgt); -} - -static void -gf100_vm_flush(struct nvkm_vm *vm) -{ - struct nvkm_mmu *mmu = vm->mmu; - struct nvkm_device *device = mmu->subdev.device; - struct nvkm_vm_pgd *vpgd; - u32 type; - - type = 0x00000001; /* PAGE_ALL */ - if (atomic_read(&vm->engref[NVKM_SUBDEV_BAR])) - type |= 0x00000004; /* HUB_ONLY */ - - mutex_lock(&mmu->subdev.mutex); - list_for_each_entry(vpgd, &vm->pgd_list, head) { - /* looks like maybe a "free flush slots" counter, the - * faster you write to 0x100cbc to more it decreases - */ - nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x100c80) & 0x00ff0000) - break; - ); - - nvkm_wr32(device, 0x100cb8, vpgd->obj->addr >> 8); - nvkm_wr32(device, 0x100cbc, 0x80000000 | type); - - /* wait for flush to be queued? */ - nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x100c80) & 0x00008000) - break; - ); - } - mutex_unlock(&mmu->subdev.mutex); -} - -static int -gf100_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, - struct lock_class_key *key, struct nvkm_vm **pvm) +const u8 * +gf100_mmu_kind(struct nvkm_mmu *mmu, int *count) { - return nvkm_vm_create(mmu, offset, length, mm_offset, 4096, key, pvm); + static const u8 + kind[256] = { + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */ + 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */ + 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */ + 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */ + 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27, + 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */ + 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */ + 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */ + 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, + 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */ + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3, + 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */ + 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, + 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */ + 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */ + 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff + }; + + *count = ARRAY_SIZE(kind); + return kind; } static const struct nvkm_mmu_func gf100_mmu = { - .limit = (1ULL << 40), .dma_bits = 40, - .pgt_bits = 27 - 12, - .spg_shift = 12, - .lpg_shift = 17, - .create = gf100_vm_create, - .map_pgt = gf100_vm_map_pgt, - .map = gf100_vm_map, - .map_sg = gf100_vm_map_sg, - .unmap = gf100_vm_unmap, - .flush = gf100_vm_flush, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_GF100}, gf100_vmm_new }, + .kind = gf100_mmu_kind, + .kind_sys = true, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk104.c new file mode 100644 index 000000000000..3d7d1eb1cff9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk104.c @@ -0,0 +1,41 @@ +/* + * 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 "mem.h" +#include "vmm.h" + +#include <nvif/class.h> + +static const struct nvkm_mmu_func +gk104_mmu = { + .dma_bits = 40, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_GF100}, gk104_vmm_new }, + .kind = gf100_mmu_kind, + .kind_sys = true, +}; + +int +gk104_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + return nvkm_mmu_new_(&gk104_mmu, device, index, pmmu); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk20a.c new file mode 100644 index 000000000000..ac74965a60d4 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gk20a.c @@ -0,0 +1,41 @@ +/* + * 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 "mem.h" +#include "vmm.h" + +#include <nvif/class.h> + +static const struct nvkm_mmu_func +gk20a_mmu = { + .dma_bits = 40, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_GF100}, gk20a_vmm_new }, + .kind = gf100_mmu_kind, + .kind_sys = true, +}; + +int +gk20a_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + return nvkm_mmu_new_(&gk20a_mmu, device, index, pmmu); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c new file mode 100644 index 000000000000..dbf644ebac97 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm200.c @@ -0,0 +1,97 @@ +/* + * 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 "mem.h" +#include "vmm.h" + +#include <subdev/fb.h> + +#include <nvif/class.h> + +const u8 * +gm200_mmu_kind(struct nvkm_mmu *mmu, int *count) +{ + static const u8 + kind[256] = { + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0xff, 0x01, /* 0x00 */ + 0x01, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, 0x11, /* 0x10 */ + 0x11, 0x11, 0x11, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x26, 0x27, /* 0x20 */ + 0x28, 0x29, 0x2a, 0x2b, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x30 */ + 0xff, 0xff, 0x26, 0x27, 0x28, 0x29, 0x26, 0x27, + 0x28, 0x29, 0xff, 0xff, 0xff, 0xff, 0x46, 0xff, /* 0x40 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x46, 0x46, 0x46, 0x46, 0xff, 0xff, 0xff, /* 0x50 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x60 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x70 */ + 0xff, 0xff, 0xff, 0x7b, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7b, 0x7b, /* 0x80 */ + 0x7b, 0x7b, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x90 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0x8b, 0x8c, 0x8d, 0x8e, 0xa7, /* 0xa0 */ + 0xa8, 0xa9, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa7, + 0xa8, 0xa9, 0xaa, 0xc3, 0xff, 0xff, 0xff, 0xff, /* 0xc0 */ + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xc3, 0xc3, + 0xc3, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xd0 */ + 0xfe, 0xff, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, + 0xfe, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xff, /* 0xe0 */ + 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xfe, 0xff, + 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xf0 */ + 0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xfd, 0xfe, 0xff + }; + *count = ARRAY_SIZE(kind); + return kind; +} + +static const struct nvkm_mmu_func +gm200_mmu = { + .dma_bits = 40, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, + .vmm = {{ -1, 0, NVIF_CLASS_VMM_GM200}, gm200_vmm_new }, + .kind = gm200_mmu_kind, + .kind_sys = true, +}; + +static const struct nvkm_mmu_func +gm200_mmu_fixed = { + .dma_bits = 40, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_GM200}, gm200_vmm_new_fixed }, + .kind = gm200_mmu_kind, + .kind_sys = true, +}; + +int +gm200_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + if (device->fb->page) + return nvkm_mmu_new_(&gm200_mmu_fixed, device, index, pmmu); + return nvkm_mmu_new_(&gm200_mmu, device, index, pmmu); +} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm20b.c index cc4176d2d25f..7353a94b4091 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/ci_smc.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gm20b.c @@ -1,5 +1,5 @@ /* - * Copyright 2017 Advanced Micro Devices, Inc. + * 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"), @@ -18,35 +18,38 @@ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. - * */ -#ifndef CI_SMC_H -#define CI_SMC_H - -#include <linux/types.h> - +#include "mem.h" +#include "vmm.h" -struct pp_smumgr; -struct pp_hwmgr; -struct amd_pp_profile; +#include <subdev/fb.h> -int ci_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, - uint16_t msg, uint32_t parameter); -int ci_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg); -int ci_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); -int ci_populate_all_memory_levels(struct pp_hwmgr *hwmgr); -int ci_init_smc_table(struct pp_hwmgr *hwmgr); -int ci_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); -int ci_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type); -int ci_update_sclk_threshold(struct pp_hwmgr *hwmgr); -uint32_t ci_get_offsetof(uint32_t type, uint32_t member); -uint32_t ci_get_mac_definition(uint32_t value); -int ci_process_firmware_header(struct pp_hwmgr *hwmgr); -int ci_initialize_mc_reg_table(struct pp_hwmgr *hwmgr); -bool ci_is_dpm_running(struct pp_hwmgr *hwmgr); -int ci_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request); +#include <nvif/class.h> +static const struct nvkm_mmu_func +gm20b_mmu = { + .dma_bits = 40, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map }, + .vmm = {{ -1, 0, NVIF_CLASS_VMM_GM200}, gm20b_vmm_new }, + .kind = gm200_mmu_kind, + .kind_sys = true, +}; -#endif +static const struct nvkm_mmu_func +gm20b_mmu_fixed = { + .dma_bits = 40, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_GM200}, gm20b_vmm_new_fixed }, + .kind = gm200_mmu_kind, + .kind_sys = true, +}; +int +gm20b_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + if (device->fb->page) + return nvkm_mmu_new_(&gm20b_mmu_fixed, device, index, pmmu); + return nvkm_mmu_new_(&gm20b_mmu, device, index, pmmu); +} diff --git a/drivers/gpu/drm/radeon/radeon_kfd.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp100.c index 9df1fea8e971..651b8805c67c 100644 --- a/drivers/gpu/drm/radeon/radeon_kfd.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp100.c @@ -1,5 +1,5 @@ /* - * Copyright 2014 Advanced Micro Devices, Inc. + * 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"), @@ -19,29 +19,27 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. */ +#include "mem.h" +#include "vmm.h" -/* - * radeon_kfd.h defines the private interface between the - * AMD kernel graphics drivers and the AMD KFD. - */ - -#ifndef RADEON_KFD_H_INCLUDED -#define RADEON_KFD_H_INCLUDED - -#include <linux/types.h> -#include "kgd_kfd_interface.h" - -struct radeon_device; +#include <core/option.h> -int radeon_kfd_init(void); -void radeon_kfd_fini(void); +#include <nvif/class.h> -void radeon_kfd_suspend(struct radeon_device *rdev); -int radeon_kfd_resume(struct radeon_device *rdev); -void radeon_kfd_interrupt(struct radeon_device *rdev, - const void *ih_ring_entry); -void radeon_kfd_device_probe(struct radeon_device *rdev); -void radeon_kfd_device_init(struct radeon_device *rdev); -void radeon_kfd_device_fini(struct radeon_device *rdev); +static const struct nvkm_mmu_func +gp100_mmu = { + .dma_bits = 47, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gp100_vmm_new }, + .kind = gm200_mmu_kind, + .kind_sys = true, +}; -#endif /* RADEON_KFD_H_INCLUDED */ +int +gp100_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + if (!nvkm_boolopt(device->cfgopt, "GP100MmuLayout", true)) + return gm200_mmu_new(device, index, pmmu); + return nvkm_mmu_new_(&gp100_mmu, device, index, pmmu); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b. b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b. new file mode 100644 index 000000000000..e69de29bb2d1 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b. diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c new file mode 100644 index 000000000000..3bd3db31e0bb --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/gp10b.c @@ -0,0 +1,45 @@ +/* + * 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 "mem.h" +#include "vmm.h" + +#include <core/option.h> + +#include <nvif/class.h> + +static const struct nvkm_mmu_func +gp10b_mmu = { + .dma_bits = 47, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}}, + .mem = {{ -1, -1, NVIF_CLASS_MEM_GF100}, .umap = gf100_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_GP100}, gp10b_vmm_new }, + .kind = gm200_mmu_kind, + .kind_sys = true, +}; + +int +gp10b_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) +{ + if (!nvkm_boolopt(device->cfgopt, "GP100MmuLayout", true)) + return gm20b_mmu_new(device, index, pmmu); + return nvkm_mmu_new_(&gp10b_mmu, device, index, pmmu); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c new file mode 100644 index 000000000000..39808489f21d --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.c @@ -0,0 +1,242 @@ +/* + * 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. + */ +#define nvkm_mem(p) container_of((p), struct nvkm_mem, memory) +#include "mem.h" + +#include <core/memory.h> + +#include <nvif/if000a.h> +#include <nvif/unpack.h> + +struct nvkm_mem { + struct nvkm_memory memory; + enum nvkm_memory_target target; + struct nvkm_mmu *mmu; + u64 pages; + struct page **mem; + union { + struct scatterlist *sgl; + dma_addr_t *dma; + }; +}; + +static enum nvkm_memory_target +nvkm_mem_target(struct nvkm_memory *memory) +{ + return nvkm_mem(memory)->target; +} + +static u8 +nvkm_mem_page(struct nvkm_memory *memory) +{ + return PAGE_SHIFT; +} + +static u64 +nvkm_mem_addr(struct nvkm_memory *memory) +{ + struct nvkm_mem *mem = nvkm_mem(memory); + if (mem->pages == 1 && mem->mem) + return mem->dma[0]; + return ~0ULL; +} + +static u64 +nvkm_mem_size(struct nvkm_memory *memory) +{ + return nvkm_mem(memory)->pages << PAGE_SHIFT; +} + +static int +nvkm_mem_map_dma(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, + struct nvkm_vma *vma, void *argv, u32 argc) +{ + struct nvkm_mem *mem = nvkm_mem(memory); + struct nvkm_vmm_map map = { + .memory = &mem->memory, + .offset = offset, + .dma = mem->dma, + }; + return nvkm_vmm_map(vmm, vma, argv, argc, &map); +} + +static void * +nvkm_mem_dtor(struct nvkm_memory *memory) +{ + struct nvkm_mem *mem = nvkm_mem(memory); + if (mem->mem) { + while (mem->pages--) { + dma_unmap_page(mem->mmu->subdev.device->dev, + mem->dma[mem->pages], PAGE_SIZE, + DMA_BIDIRECTIONAL); + __free_page(mem->mem[mem->pages]); + } + kvfree(mem->dma); + kvfree(mem->mem); + } + return mem; +} + +static const struct nvkm_memory_func +nvkm_mem_dma = { + .dtor = nvkm_mem_dtor, + .target = nvkm_mem_target, + .page = nvkm_mem_page, + .addr = nvkm_mem_addr, + .size = nvkm_mem_size, + .map = nvkm_mem_map_dma, +}; + +static int +nvkm_mem_map_sgl(struct nvkm_memory *memory, u64 offset, struct nvkm_vmm *vmm, + struct nvkm_vma *vma, void *argv, u32 argc) +{ + struct nvkm_mem *mem = nvkm_mem(memory); + struct nvkm_vmm_map map = { + .memory = &mem->memory, + .offset = offset, + .sgl = mem->sgl, + }; + return nvkm_vmm_map(vmm, vma, argv, argc, &map); +} + +static const struct nvkm_memory_func +nvkm_mem_sgl = { + .dtor = nvkm_mem_dtor, + .target = nvkm_mem_target, + .page = nvkm_mem_page, + .addr = nvkm_mem_addr, + .size = nvkm_mem_size, + .map = nvkm_mem_map_sgl, +}; + +int +nvkm_mem_map_host(struct nvkm_memory *memory, void **pmap) +{ + struct nvkm_mem *mem = nvkm_mem(memory); + if (mem->mem) { + *pmap = vmap(mem->mem, mem->pages, VM_MAP, PAGE_KERNEL); + return *pmap ? 0 : -EFAULT; + } + return -EINVAL; +} + +static int +nvkm_mem_new_host(struct nvkm_mmu *mmu, int type, u8 page, u64 size, + void *argv, u32 argc, struct nvkm_memory **pmemory) +{ + struct device *dev = mmu->subdev.device->dev; + union { + struct nvif_mem_ram_vn vn; + struct nvif_mem_ram_v0 v0; + } *args = argv; + int ret = -ENOSYS; + enum nvkm_memory_target target; + struct nvkm_mem *mem; + gfp_t gfp = GFP_USER | __GFP_ZERO; + + if ( (mmu->type[type].type & NVKM_MEM_COHERENT) && + !(mmu->type[type].type & NVKM_MEM_UNCACHED)) + target = NVKM_MEM_TARGET_HOST; + else + target = NVKM_MEM_TARGET_NCOH; + + if (page != PAGE_SHIFT) + return -EINVAL; + + if (!(mem = kzalloc(sizeof(*mem), GFP_KERNEL))) + return -ENOMEM; + mem->target = target; + mem->mmu = mmu; + *pmemory = &mem->memory; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + if (args->v0.dma) { + nvkm_memory_ctor(&nvkm_mem_dma, &mem->memory); + mem->dma = args->v0.dma; + } else { + nvkm_memory_ctor(&nvkm_mem_sgl, &mem->memory); + mem->sgl = args->v0.sgl; + } + + if (!IS_ALIGNED(size, PAGE_SIZE)) + return -EINVAL; + mem->pages = size >> PAGE_SHIFT; + return 0; + } else + if ( (ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + kfree(mem); + return ret; + } + + nvkm_memory_ctor(&nvkm_mem_dma, &mem->memory); + size = ALIGN(size, PAGE_SIZE) >> PAGE_SHIFT; + + if (!(mem->mem = kvmalloc(sizeof(*mem->mem) * size, GFP_KERNEL))) + return -ENOMEM; + if (!(mem->dma = kvmalloc(sizeof(*mem->dma) * size, GFP_KERNEL))) + return -ENOMEM; + + if (mmu->dma_bits > 32) + gfp |= GFP_HIGHUSER; + else + gfp |= GFP_DMA32; + + for (mem->pages = 0; size; size--, mem->pages++) { + struct page *p = alloc_page(gfp); + if (!p) + return -ENOMEM; + + mem->dma[mem->pages] = dma_map_page(mmu->subdev.device->dev, + p, 0, PAGE_SIZE, + DMA_BIDIRECTIONAL); + if (dma_mapping_error(dev, mem->dma[mem->pages])) { + __free_page(p); + return -ENOMEM; + } + + mem->mem[mem->pages] = p; + } + + return 0; +} + +int +nvkm_mem_new_type(struct nvkm_mmu *mmu, int type, u8 page, u64 size, + void *argv, u32 argc, struct nvkm_memory **pmemory) +{ + struct nvkm_memory *memory = NULL; + int ret; + + if (mmu->type[type].type & NVKM_MEM_VRAM) { + ret = mmu->func->mem.vram(mmu, type, page, size, + argv, argc, &memory); + } else { + ret = nvkm_mem_new_host(mmu, type, page, size, + argv, argc, &memory); + } + + if (ret) + nvkm_memory_unref(&memory); + *pmemory = memory; + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.h new file mode 100644 index 000000000000..234267e1b215 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/mem.h @@ -0,0 +1,23 @@ +#ifndef __NVKM_MEM_H__ +#define __NVKM_MEM_H__ +#include "priv.h" + +int nvkm_mem_new_type(struct nvkm_mmu *, int type, u8 page, u64 size, + void *argv, u32 argc, struct nvkm_memory **); +int nvkm_mem_map_host(struct nvkm_memory *, void **pmap); + +int nv04_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32, + struct nvkm_memory **); +int nv04_mem_map(struct nvkm_mmu *, struct nvkm_memory *, void *, u32, + u64 *, u64 *, struct nvkm_vma **); + +int nv50_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32, + struct nvkm_memory **); +int nv50_mem_map(struct nvkm_mmu *, struct nvkm_memory *, void *, u32, + u64 *, u64 *, struct nvkm_vma **); + +int gf100_mem_new(struct nvkm_mmu *, int, u8, u64, void *, u32, + struct nvkm_memory **); +int gf100_mem_map(struct nvkm_mmu *, struct nvkm_memory *, void *, u32, + u64 *, u64 *, struct nvkm_vma **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c new file mode 100644 index 000000000000..d9c9bee45222 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memgf100.c @@ -0,0 +1,94 @@ +/* + * 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 "mem.h" + +#include <core/memory.h> +#include <subdev/bar.h> +#include <subdev/fb.h> + +#include <nvif/class.h> +#include <nvif/if900b.h> +#include <nvif/if900d.h> +#include <nvif/unpack.h> + +int +gf100_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv, + u32 argc, u64 *paddr, u64 *psize, struct nvkm_vma **pvma) +{ + struct gf100_vmm_map_v0 uvmm = {}; + union { + struct gf100_mem_map_vn vn; + struct gf100_mem_map_v0 v0; + } *args = argv; + struct nvkm_device *device = mmu->subdev.device; + struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); + int ret = -ENOSYS; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + uvmm.ro = args->v0.ro; + uvmm.kind = args->v0.kind; + } else + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + } else + return ret; + + ret = nvkm_vmm_get(bar, nvkm_memory_page(memory), + nvkm_memory_size(memory), pvma); + if (ret) + return ret; + + ret = nvkm_memory_map(memory, 0, bar, *pvma, &uvmm, sizeof(uvmm)); + if (ret) + return ret; + + *paddr = device->func->resource_addr(device, 1) + (*pvma)->addr; + *psize = (*pvma)->size; + return 0; +} + +int +gf100_mem_new(struct nvkm_mmu *mmu, int type, u8 page, u64 size, + void *argv, u32 argc, struct nvkm_memory **pmemory) +{ + union { + struct gf100_mem_vn vn; + struct gf100_mem_v0 v0; + } *args = argv; + int ret = -ENOSYS; + bool contig; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + contig = args->v0.contig; + } else + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + contig = false; + } else + return ret; + + if (mmu->type[type].type & (NVKM_MEM_DISP | NVKM_MEM_COMP)) + type = NVKM_RAM_MM_NORMAL; + else + type = NVKM_RAM_MM_MIXED; + + return nvkm_ram_get(mmu->subdev.device, type, 0x01, page, + size, contig, false, pmemory); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c new file mode 100644 index 000000000000..79a3b0cc9f5b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv04.c @@ -0,0 +1,69 @@ +/* + * 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 "mem.h" + +#include <core/memory.h> +#include <subdev/fb.h> + +#include <nvif/if000b.h> +#include <nvif/unpack.h> + +int +nv04_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv, + u32 argc, u64 *paddr, u64 *psize, struct nvkm_vma **pvma) +{ + union { + struct nv04_mem_map_vn vn; + } *args = argv; + struct nvkm_device *device = mmu->subdev.device; + const u64 addr = nvkm_memory_addr(memory); + int ret = -ENOSYS; + + if ((ret = nvif_unvers(ret, &argv, &argc, args->vn))) + return ret; + + *paddr = device->func->resource_addr(device, 1) + addr; + *psize = nvkm_memory_size(memory); + *pvma = ERR_PTR(-ENODEV); + return 0; +} + +int +nv04_mem_new(struct nvkm_mmu *mmu, int type, u8 page, u64 size, + void *argv, u32 argc, struct nvkm_memory **pmemory) +{ + union { + struct nv04_mem_vn vn; + } *args = argv; + int ret = -ENOSYS; + + if ((ret = nvif_unvers(ret, &argv, &argc, args->vn))) + return ret; + + if (mmu->type[type].type & NVKM_MEM_MAPPABLE) + type = NVKM_RAM_MM_NORMAL; + else + type = NVKM_RAM_MM_NOMAP; + + return nvkm_ram_get(mmu->subdev.device, type, 0x01, page, + size, true, false, pmemory); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c new file mode 100644 index 000000000000..46759b89fc1f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/memnv50.c @@ -0,0 +1,88 @@ +/* + * 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 "mem.h" + +#include <core/memory.h> +#include <subdev/bar.h> +#include <subdev/fb.h> + +#include <nvif/class.h> +#include <nvif/if500b.h> +#include <nvif/if500d.h> +#include <nvif/unpack.h> + +int +nv50_mem_map(struct nvkm_mmu *mmu, struct nvkm_memory *memory, void *argv, + u32 argc, u64 *paddr, u64 *psize, struct nvkm_vma **pvma) +{ + struct nv50_vmm_map_v0 uvmm = {}; + union { + struct nv50_mem_map_vn vn; + struct nv50_mem_map_v0 v0; + } *args = argv; + struct nvkm_device *device = mmu->subdev.device; + struct nvkm_vmm *bar = nvkm_bar_bar1_vmm(device); + u64 size = nvkm_memory_size(memory); + int ret = -ENOSYS; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + uvmm.ro = args->v0.ro; + uvmm.kind = args->v0.kind; + uvmm.comp = args->v0.comp; + } else + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + } else + return ret; + + ret = nvkm_vmm_get(bar, 12, size, pvma); + if (ret) + return ret; + + *paddr = device->func->resource_addr(device, 1) + (*pvma)->addr; + *psize = (*pvma)->size; + return nvkm_memory_map(memory, 0, bar, *pvma, &uvmm, sizeof(uvmm)); +} + +int +nv50_mem_new(struct nvkm_mmu *mmu, int type, u8 page, u64 size, + void *argv, u32 argc, struct nvkm_memory **pmemory) +{ + union { + struct nv50_mem_vn vn; + struct nv50_mem_v0 v0; + } *args = argv; + int ret = -ENOSYS; + bool contig; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + type = args->v0.bankswz ? 0x02 : 0x01; + contig = args->v0.contig; + } else + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + type = 0x01; + contig = false; + } else + return -ENOSYS; + + return nvkm_ram_get(mmu->subdev.device, NVKM_RAM_MM_NORMAL, type, + page, size, contig, false, pmemory); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c index 37927c3fdc3e..d201c887c2cd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.c @@ -21,129 +21,21 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "mem.h" +#include "vmm.h" -#include <core/gpuobj.h> - -#define NV04_PDMA_SIZE (128 * 1024 * 1024) -#define NV04_PDMA_PAGE ( 4 * 1024) - -/******************************************************************************* - * VM map/unmap callbacks - ******************************************************************************/ - -static void -nv04_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, - struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) -{ - pte = 0x00008 + (pte * 4); - nvkm_kmap(pgt); - while (cnt) { - u32 page = PAGE_SIZE / NV04_PDMA_PAGE; - u32 phys = (u32)*list++; - while (cnt && page--) { - nvkm_wo32(pgt, pte, phys | 3); - phys += NV04_PDMA_PAGE; - pte += 4; - cnt -= 1; - } - } - nvkm_done(pgt); -} - -static void -nv04_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) -{ - pte = 0x00008 + (pte * 4); - nvkm_kmap(pgt); - while (cnt--) { - nvkm_wo32(pgt, pte, 0x00000000); - pte += 4; - } - nvkm_done(pgt); -} - -static void -nv04_vm_flush(struct nvkm_vm *vm) -{ -} - -/******************************************************************************* - * MMU subdev - ******************************************************************************/ - -static int -nv04_mmu_oneinit(struct nvkm_mmu *base) -{ - struct nv04_mmu *mmu = nv04_mmu(base); - struct nvkm_device *device = mmu->base.subdev.device; - struct nvkm_memory *dma; - int ret; - - ret = nvkm_vm_create(&mmu->base, 0, NV04_PDMA_SIZE, 0, 4096, NULL, - &mmu->vm); - if (ret) - return ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - (NV04_PDMA_SIZE / NV04_PDMA_PAGE) * 4 + 8, - 16, true, &dma); - mmu->vm->pgt[0].mem[0] = dma; - mmu->vm->pgt[0].refcount[0] = 1; - if (ret) - return ret; - - nvkm_kmap(dma); - nvkm_wo32(dma, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */ - nvkm_wo32(dma, 0x00004, NV04_PDMA_SIZE - 1); - nvkm_done(dma); - return 0; -} - -void * -nv04_mmu_dtor(struct nvkm_mmu *base) -{ - struct nv04_mmu *mmu = nv04_mmu(base); - struct nvkm_device *device = mmu->base.subdev.device; - if (mmu->vm) { - nvkm_memory_del(&mmu->vm->pgt[0].mem[0]); - nvkm_vm_ref(NULL, &mmu->vm, NULL); - } - if (mmu->nullp) { - dma_free_coherent(device->dev, 16 * 1024, - mmu->nullp, mmu->null); - } - return mmu; -} - -int -nv04_mmu_new_(const struct nvkm_mmu_func *func, struct nvkm_device *device, - int index, struct nvkm_mmu **pmmu) -{ - struct nv04_mmu *mmu; - if (!(mmu = kzalloc(sizeof(*mmu), GFP_KERNEL))) - return -ENOMEM; - *pmmu = &mmu->base; - nvkm_mmu_ctor(func, device, index, &mmu->base); - return 0; -} +#include <nvif/class.h> const struct nvkm_mmu_func nv04_mmu = { - .oneinit = nv04_mmu_oneinit, - .dtor = nv04_mmu_dtor, - .limit = NV04_PDMA_SIZE, .dma_bits = 32, - .pgt_bits = 32 - 12, - .spg_shift = 12, - .lpg_shift = 12, - .map_sg = nv04_vm_map_sg, - .unmap = nv04_vm_unmap, - .flush = nv04_vm_flush, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV04}}, + .mem = {{ -1, -1, NVIF_CLASS_MEM_NV04}, nv04_mem_new, nv04_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV04}, nv04_vmm_new, true }, }; int nv04_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) { - return nv04_mmu_new_(&nv04_mmu, device, index, pmmu); + return nvkm_mmu_new_(&nv04_mmu, device, index, pmmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h deleted file mode 100644 index 363e33b296d5..000000000000 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv04.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef __NV04_MMU_PRIV__ -#define __NV04_MMU_PRIV__ -#define nv04_mmu(p) container_of((p), struct nv04_mmu, base) -#include "priv.h" - -struct nv04_mmu { - struct nvkm_mmu base; - struct nvkm_vm *vm; - dma_addr_t null; - void *nullp; -}; - -int nv04_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *, - int index, struct nvkm_mmu **); -void *nv04_mmu_dtor(struct nvkm_mmu *); - -extern const struct nvkm_mmu_func nv04_mmu; -#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c index c6a26f907009..adca81895c09 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv41.c @@ -21,113 +21,29 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "mem.h" +#include "vmm.h" -#include <core/gpuobj.h> #include <core/option.h> -#include <subdev/timer.h> -#define NV41_GART_SIZE (512 * 1024 * 1024) -#define NV41_GART_PAGE ( 4 * 1024) - -/******************************************************************************* - * VM map/unmap callbacks - ******************************************************************************/ - -static void -nv41_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, - struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) -{ - pte = pte * 4; - nvkm_kmap(pgt); - while (cnt) { - u32 page = PAGE_SIZE / NV41_GART_PAGE; - u64 phys = (u64)*list++; - while (cnt && page--) { - nvkm_wo32(pgt, pte, (phys >> 7) | 1); - phys += NV41_GART_PAGE; - pte += 4; - cnt -= 1; - } - } - nvkm_done(pgt); -} - -static void -nv41_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) -{ - pte = pte * 4; - nvkm_kmap(pgt); - while (cnt--) { - nvkm_wo32(pgt, pte, 0x00000000); - pte += 4; - } - nvkm_done(pgt); -} - -static void -nv41_vm_flush(struct nvkm_vm *vm) -{ - struct nv04_mmu *mmu = nv04_mmu(vm->mmu); - struct nvkm_device *device = mmu->base.subdev.device; - - mutex_lock(&mmu->base.subdev.mutex); - nvkm_wr32(device, 0x100810, 0x00000022); - nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x100810) & 0x00000020) - break; - ); - nvkm_wr32(device, 0x100810, 0x00000000); - mutex_unlock(&mmu->base.subdev.mutex); -} - -/******************************************************************************* - * MMU subdev - ******************************************************************************/ - -static int -nv41_mmu_oneinit(struct nvkm_mmu *base) -{ - struct nv04_mmu *mmu = nv04_mmu(base); - struct nvkm_device *device = mmu->base.subdev.device; - int ret; - - ret = nvkm_vm_create(&mmu->base, 0, NV41_GART_SIZE, 0, 4096, NULL, - &mmu->vm); - if (ret) - return ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - (NV41_GART_SIZE / NV41_GART_PAGE) * 4, 16, true, - &mmu->vm->pgt[0].mem[0]); - mmu->vm->pgt[0].refcount[0] = 1; - return ret; -} +#include <nvif/class.h> static void -nv41_mmu_init(struct nvkm_mmu *base) +nv41_mmu_init(struct nvkm_mmu *mmu) { - struct nv04_mmu *mmu = nv04_mmu(base); - struct nvkm_device *device = mmu->base.subdev.device; - struct nvkm_memory *dma = mmu->vm->pgt[0].mem[0]; - nvkm_wr32(device, 0x100800, 0x00000002 | nvkm_memory_addr(dma)); + struct nvkm_device *device = mmu->subdev.device; + nvkm_wr32(device, 0x100800, 0x00000002 | mmu->vmm->pd->pt[0]->addr); nvkm_mask(device, 0x10008c, 0x00000100, 0x00000100); nvkm_wr32(device, 0x100820, 0x00000000); } static const struct nvkm_mmu_func nv41_mmu = { - .dtor = nv04_mmu_dtor, - .oneinit = nv41_mmu_oneinit, .init = nv41_mmu_init, - .limit = NV41_GART_SIZE, .dma_bits = 39, - .pgt_bits = 32 - 12, - .spg_shift = 12, - .lpg_shift = 12, - .map_sg = nv41_vm_map_sg, - .unmap = nv41_vm_unmap, - .flush = nv41_vm_flush, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV04}}, + .mem = {{ -1, -1, NVIF_CLASS_MEM_NV04}, nv04_mem_new, nv04_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV04}, nv41_vmm_new, true }, }; int @@ -137,5 +53,5 @@ nv41_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) return nv04_mmu_new(device, index, pmmu); - return nv04_mmu_new_(&nv41_mmu, device, index, pmmu); + return nvkm_mmu_new_(&nv41_mmu, device, index, pmmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c index a648c2395545..598c53a27bde 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv44.c @@ -21,176 +21,18 @@ * * Authors: Ben Skeggs */ -#include "nv04.h" +#include "mem.h" +#include "vmm.h" -#include <core/gpuobj.h> #include <core/option.h> -#include <subdev/timer.h> -#define NV44_GART_SIZE (512 * 1024 * 1024) -#define NV44_GART_PAGE ( 4 * 1024) - -/******************************************************************************* - * VM map/unmap callbacks - ******************************************************************************/ - -static void -nv44_vm_fill(struct nvkm_memory *pgt, dma_addr_t null, - dma_addr_t *list, u32 pte, u32 cnt) -{ - u32 base = (pte << 2) & ~0x0000000f; - u32 tmp[4]; - - tmp[0] = nvkm_ro32(pgt, base + 0x0); - tmp[1] = nvkm_ro32(pgt, base + 0x4); - tmp[2] = nvkm_ro32(pgt, base + 0x8); - tmp[3] = nvkm_ro32(pgt, base + 0xc); - - while (cnt--) { - u32 addr = list ? (*list++ >> 12) : (null >> 12); - switch (pte++ & 0x3) { - case 0: - tmp[0] &= ~0x07ffffff; - tmp[0] |= addr; - break; - case 1: - tmp[0] &= ~0xf8000000; - tmp[0] |= addr << 27; - tmp[1] &= ~0x003fffff; - tmp[1] |= addr >> 5; - break; - case 2: - tmp[1] &= ~0xffc00000; - tmp[1] |= addr << 22; - tmp[2] &= ~0x0001ffff; - tmp[2] |= addr >> 10; - break; - case 3: - tmp[2] &= ~0xfffe0000; - tmp[2] |= addr << 17; - tmp[3] &= ~0x00000fff; - tmp[3] |= addr >> 15; - break; - } - } - - nvkm_wo32(pgt, base + 0x0, tmp[0]); - nvkm_wo32(pgt, base + 0x4, tmp[1]); - nvkm_wo32(pgt, base + 0x8, tmp[2]); - nvkm_wo32(pgt, base + 0xc, tmp[3] | 0x40000000); -} - -static void -nv44_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, - struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) -{ - struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu); - u32 tmp[4]; - int i; - - nvkm_kmap(pgt); - if (pte & 3) { - u32 max = 4 - (pte & 3); - u32 part = (cnt > max) ? max : cnt; - nv44_vm_fill(pgt, mmu->null, list, pte, part); - pte += part; - list += part; - cnt -= part; - } - - while (cnt >= 4) { - for (i = 0; i < 4; i++) - tmp[i] = *list++ >> 12; - nvkm_wo32(pgt, pte++ * 4, tmp[0] >> 0 | tmp[1] << 27); - nvkm_wo32(pgt, pte++ * 4, tmp[1] >> 5 | tmp[2] << 22); - nvkm_wo32(pgt, pte++ * 4, tmp[2] >> 10 | tmp[3] << 17); - nvkm_wo32(pgt, pte++ * 4, tmp[3] >> 15 | 0x40000000); - cnt -= 4; - } - - if (cnt) - nv44_vm_fill(pgt, mmu->null, list, pte, cnt); - nvkm_done(pgt); -} - -static void -nv44_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) -{ - struct nv04_mmu *mmu = nv04_mmu(vma->vm->mmu); - - nvkm_kmap(pgt); - if (pte & 3) { - u32 max = 4 - (pte & 3); - u32 part = (cnt > max) ? max : cnt; - nv44_vm_fill(pgt, mmu->null, NULL, pte, part); - pte += part; - cnt -= part; - } - - while (cnt >= 4) { - nvkm_wo32(pgt, pte++ * 4, 0x00000000); - nvkm_wo32(pgt, pte++ * 4, 0x00000000); - nvkm_wo32(pgt, pte++ * 4, 0x00000000); - nvkm_wo32(pgt, pte++ * 4, 0x00000000); - cnt -= 4; - } - - if (cnt) - nv44_vm_fill(pgt, mmu->null, NULL, pte, cnt); - nvkm_done(pgt); -} - -static void -nv44_vm_flush(struct nvkm_vm *vm) -{ - struct nv04_mmu *mmu = nv04_mmu(vm->mmu); - struct nvkm_device *device = mmu->base.subdev.device; - nvkm_wr32(device, 0x100814, mmu->base.limit - NV44_GART_PAGE); - nvkm_wr32(device, 0x100808, 0x00000020); - nvkm_msec(device, 2000, - if (nvkm_rd32(device, 0x100808) & 0x00000001) - break; - ); - nvkm_wr32(device, 0x100808, 0x00000000); -} - -/******************************************************************************* - * MMU subdev - ******************************************************************************/ - -static int -nv44_mmu_oneinit(struct nvkm_mmu *base) -{ - struct nv04_mmu *mmu = nv04_mmu(base); - struct nvkm_device *device = mmu->base.subdev.device; - int ret; - - mmu->nullp = dma_alloc_coherent(device->dev, 16 * 1024, - &mmu->null, GFP_KERNEL); - if (!mmu->nullp) { - nvkm_warn(&mmu->base.subdev, "unable to allocate dummy pages\n"); - mmu->null = 0; - } - - ret = nvkm_vm_create(&mmu->base, 0, NV44_GART_SIZE, 0, 4096, NULL, - &mmu->vm); - if (ret) - return ret; - - ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, - (NV44_GART_SIZE / NV44_GART_PAGE) * 4, - 512 * 1024, true, - &mmu->vm->pgt[0].mem[0]); - mmu->vm->pgt[0].refcount[0] = 1; - return ret; -} +#include <nvif/class.h> static void -nv44_mmu_init(struct nvkm_mmu *base) +nv44_mmu_init(struct nvkm_mmu *mmu) { - struct nv04_mmu *mmu = nv04_mmu(base); - struct nvkm_device *device = mmu->base.subdev.device; - struct nvkm_memory *gart = mmu->vm->pgt[0].mem[0]; + struct nvkm_device *device = mmu->subdev.device; + struct nvkm_memory *pt = mmu->vmm->pd->pt[0]->memory; u32 addr; /* calculate vram address of this PRAMIN block, object must be @@ -198,11 +40,11 @@ nv44_mmu_init(struct nvkm_mmu *base) * of 512KiB for this to work correctly */ addr = nvkm_rd32(device, 0x10020c); - addr -= ((nvkm_memory_addr(gart) >> 19) + 1) << 19; + addr -= ((nvkm_memory_addr(pt) >> 19) + 1) << 19; nvkm_wr32(device, 0x100850, 0x80000000); - nvkm_wr32(device, 0x100818, mmu->null); - nvkm_wr32(device, 0x100804, NV44_GART_SIZE); + nvkm_wr32(device, 0x100818, mmu->vmm->null); + nvkm_wr32(device, 0x100804, (nvkm_memory_size(pt) / 4) * 4096); nvkm_wr32(device, 0x100850, 0x00008000); nvkm_mask(device, 0x10008c, 0x00000200, 0x00000200); nvkm_wr32(device, 0x100820, 0x00000000); @@ -212,17 +54,11 @@ nv44_mmu_init(struct nvkm_mmu *base) static const struct nvkm_mmu_func nv44_mmu = { - .dtor = nv04_mmu_dtor, - .oneinit = nv44_mmu_oneinit, .init = nv44_mmu_init, - .limit = NV44_GART_SIZE, .dma_bits = 39, - .pgt_bits = 32 - 12, - .spg_shift = 12, - .lpg_shift = 12, - .map_sg = nv44_vm_map_sg, - .unmap = nv44_vm_unmap, - .flush = nv44_vm_flush, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV04}}, + .mem = {{ -1, -1, NVIF_CLASS_MEM_NV04}, nv04_mem_new, nv04_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV04}, nv44_vmm_new, true }, }; int @@ -232,5 +68,5 @@ nv44_mmu_new(struct nvkm_device *device, int index, struct nvkm_mmu **pmmu) !nvkm_boolopt(device->cfgopt, "NvPCIE", true)) return nv04_mmu_new(device, index, pmmu); - return nv04_mmu_new_(&nv44_mmu, device, index, pmmu); + return nvkm_mmu_new_(&nv44_mmu, device, index, pmmu); } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c index a1f8d65f0276..db3dfbbb2aa0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/nv50.c @@ -21,207 +21,52 @@ * * Authors: Ben Skeggs */ -#include "priv.h" +#include "mem.h" +#include "vmm.h" -#include <core/gpuobj.h> -#include <subdev/fb.h> -#include <subdev/timer.h> -#include <engine/gr.h> +#include <nvif/class.h> -static void -nv50_vm_map_pgt(struct nvkm_gpuobj *pgd, u32 pde, struct nvkm_memory *pgt[2]) +const u8 * +nv50_mmu_kind(struct nvkm_mmu *base, int *count) { - u64 phys = 0xdeadcafe00000000ULL; - u32 coverage = 0; - - if (pgt[0]) { - /* present, 4KiB pages */ - phys = 0x00000003 | nvkm_memory_addr(pgt[0]); - coverage = (nvkm_memory_size(pgt[0]) >> 3) << 12; - } else - if (pgt[1]) { - /* present, 64KiB pages */ - phys = 0x00000001 | nvkm_memory_addr(pgt[1]); - coverage = (nvkm_memory_size(pgt[1]) >> 3) << 16; - } - - if (phys & 1) { - if (coverage <= 32 * 1024 * 1024) - phys |= 0x60; - else if (coverage <= 64 * 1024 * 1024) - phys |= 0x40; - else if (coverage <= 128 * 1024 * 1024) - phys |= 0x20; - } - - nvkm_kmap(pgd); - nvkm_wo32(pgd, (pde * 8) + 0, lower_32_bits(phys)); - nvkm_wo32(pgd, (pde * 8) + 4, upper_32_bits(phys)); - nvkm_done(pgd); -} - -static inline u64 -vm_addr(struct nvkm_vma *vma, u64 phys, u32 memtype, u32 target) -{ - phys |= 1; /* present */ - phys |= (u64)memtype << 40; - phys |= target << 4; - if (vma->access & NV_MEM_ACCESS_SYS) - phys |= (1 << 6); - if (!(vma->access & NV_MEM_ACCESS_WO)) - phys |= (1 << 3); - return phys; -} - -static void -nv50_vm_map(struct nvkm_vma *vma, struct nvkm_memory *pgt, - struct nvkm_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta) -{ - struct nvkm_ram *ram = vma->vm->mmu->subdev.device->fb->ram; - u32 comp = (mem->memtype & 0x180) >> 7; - u32 block, target; - int i; - - /* IGPs don't have real VRAM, re-target to stolen system memory */ - target = 0; - if (ram->stolen) { - phys += ram->stolen; - target = 3; - } - - phys = vm_addr(vma, phys, mem->memtype, target); - pte <<= 3; - cnt <<= 3; - - nvkm_kmap(pgt); - while (cnt) { - u32 offset_h = upper_32_bits(phys); - u32 offset_l = lower_32_bits(phys); - - for (i = 7; i >= 0; i--) { - block = 1 << (i + 3); - if (cnt >= block && !(pte & (block - 1))) - break; - } - offset_l |= (i << 7); - - phys += block << (vma->node->type - 3); - cnt -= block; - if (comp) { - u32 tag = mem->tag->offset + ((delta >> 16) * comp); - offset_h |= (tag << 17); - delta += block << (vma->node->type - 3); - } - - while (block) { - nvkm_wo32(pgt, pte + 0, offset_l); - nvkm_wo32(pgt, pte + 4, offset_h); - pte += 8; - block -= 8; - } - } - nvkm_done(pgt); -} - -static void -nv50_vm_map_sg(struct nvkm_vma *vma, struct nvkm_memory *pgt, - struct nvkm_mem *mem, u32 pte, u32 cnt, dma_addr_t *list) -{ - u32 target = (vma->access & NV_MEM_ACCESS_NOSNOOP) ? 3 : 2; - pte <<= 3; - nvkm_kmap(pgt); - while (cnt--) { - u64 phys = vm_addr(vma, (u64)*list++, mem->memtype, target); - nvkm_wo32(pgt, pte + 0, lower_32_bits(phys)); - nvkm_wo32(pgt, pte + 4, upper_32_bits(phys)); - pte += 8; - } - nvkm_done(pgt); -} - -static void -nv50_vm_unmap(struct nvkm_vma *vma, struct nvkm_memory *pgt, u32 pte, u32 cnt) -{ - pte <<= 3; - nvkm_kmap(pgt); - while (cnt--) { - nvkm_wo32(pgt, pte + 0, 0x00000000); - nvkm_wo32(pgt, pte + 4, 0x00000000); - pte += 8; - } - nvkm_done(pgt); -} - -static void -nv50_vm_flush(struct nvkm_vm *vm) -{ - struct nvkm_mmu *mmu = vm->mmu; - struct nvkm_subdev *subdev = &mmu->subdev; - struct nvkm_device *device = subdev->device; - int i, vme; - - mutex_lock(&subdev->mutex); - for (i = 0; i < NVKM_SUBDEV_NR; i++) { - if (!atomic_read(&vm->engref[i])) - continue; - - /* unfortunate hw bug workaround... */ - if (i == NVKM_ENGINE_GR && device->gr) { - int ret = nvkm_gr_tlb_flush(device->gr); - if (ret != -ENODEV) - continue; - } - - switch (i) { - case NVKM_ENGINE_GR : vme = 0x00; break; - case NVKM_ENGINE_VP : - case NVKM_ENGINE_MSPDEC: vme = 0x01; break; - case NVKM_SUBDEV_BAR : vme = 0x06; break; - case NVKM_ENGINE_MSPPP : - case NVKM_ENGINE_MPEG : vme = 0x08; break; - case NVKM_ENGINE_BSP : - case NVKM_ENGINE_MSVLD : vme = 0x09; break; - case NVKM_ENGINE_CIPHER: - case NVKM_ENGINE_SEC : vme = 0x0a; break; - case NVKM_ENGINE_CE0 : vme = 0x0d; break; - default: - continue; - } - - nvkm_wr32(device, 0x100c80, (vme << 16) | 1); - if (nvkm_msec(device, 2000, - if (!(nvkm_rd32(device, 0x100c80) & 0x00000001)) - break; - ) < 0) - nvkm_error(subdev, "vm flush timeout: engine %d\n", vme); - } - mutex_unlock(&subdev->mutex); -} - -static int -nv50_vm_create(struct nvkm_mmu *mmu, u64 offset, u64 length, u64 mm_offset, - struct lock_class_key *key, struct nvkm_vm **pvm) -{ - u32 block = (1 << (mmu->func->pgt_bits + 12)); - if (block > length) - block = length; - - return nvkm_vm_create(mmu, offset, length, mm_offset, block, key, pvm); + /* 0x01: no bank swizzle + * 0x02: bank swizzled + * 0x7f: invalid + * + * 0x01/0x02 are values understood by the VRAM allocator, + * and are required to avoid mixing the two types within + * a certain range. + */ + static const u8 + kind[128] = { + 0x01, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x00 */ + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x01, 0x01, 0x01, 0x01, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x10 */ + 0x02, 0x02, 0x02, 0x02, 0x7f, 0x7f, 0x7f, 0x7f, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, /* 0x20 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x30 */ + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, /* 0x40 */ + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x01, 0x01, 0x01, 0x7f, /* 0x50 */ + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x7f, /* 0x60 */ + 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, + 0x01, 0x7f, 0x02, 0x7f, 0x01, 0x7f, 0x02, 0x7f, /* 0x70 */ + 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x7f, 0x7f + }; + *count = ARRAY_SIZE(kind); + return kind; } static const struct nvkm_mmu_func nv50_mmu = { - .limit = (1ULL << 40), .dma_bits = 40, - .pgt_bits = 29 - 12, - .spg_shift = 12, - .lpg_shift = 16, - .create = nv50_vm_create, - .map_pgt = nv50_vm_map_pgt, - .map = nv50_vm_map, - .map_sg = nv50_vm_map_sg, - .unmap = nv50_vm_unmap, - .flush = nv50_vm_flush, + .mmu = {{ -1, -1, NVIF_CLASS_MMU_NV50}}, + .mem = {{ -1, 0, NVIF_CLASS_MEM_NV50}, nv50_mem_new, nv50_mem_map }, + .vmm = {{ -1, -1, NVIF_CLASS_VMM_NV50}, nv50_vmm_new, false, 0x1400 }, + .kind = nv50_mmu_kind, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h index 27cedc60b507..d024d8055fcb 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/priv.h @@ -9,31 +9,57 @@ int nvkm_mmu_new_(const struct nvkm_mmu_func *, struct nvkm_device *, int index, struct nvkm_mmu **); struct nvkm_mmu_func { - void *(*dtor)(struct nvkm_mmu *); - int (*oneinit)(struct nvkm_mmu *); void (*init)(struct nvkm_mmu *); - u64 limit; u8 dma_bits; - u32 pgt_bits; - u8 spg_shift; - u8 lpg_shift; - - int (*create)(struct nvkm_mmu *, u64 offset, u64 length, u64 mm_offset, - struct lock_class_key *, struct nvkm_vm **); - - void (*map_pgt)(struct nvkm_gpuobj *pgd, u32 pde, - struct nvkm_memory *pgt[2]); - void (*map)(struct nvkm_vma *, struct nvkm_memory *, - struct nvkm_mem *, u32 pte, u32 cnt, - u64 phys, u64 delta); - void (*map_sg)(struct nvkm_vma *, struct nvkm_memory *, - struct nvkm_mem *, u32 pte, u32 cnt, dma_addr_t *); - void (*unmap)(struct nvkm_vma *, struct nvkm_memory *pgt, - u32 pte, u32 cnt); - void (*flush)(struct nvkm_vm *); + + struct { + struct nvkm_sclass user; + } mmu; + + struct { + struct nvkm_sclass user; + int (*vram)(struct nvkm_mmu *, int type, u8 page, u64 size, + void *argv, u32 argc, struct nvkm_memory **); + int (*umap)(struct nvkm_mmu *, struct nvkm_memory *, void *argv, + u32 argc, u64 *addr, u64 *size, struct nvkm_vma **); + } mem; + + struct { + struct nvkm_sclass user; + int (*ctor)(struct nvkm_mmu *, u64 addr, u64 size, + void *argv, u32 argc, struct lock_class_key *, + const char *name, struct nvkm_vmm **); + bool global; + u32 pd_offset; + } vmm; + + const u8 *(*kind)(struct nvkm_mmu *, int *count); + bool kind_sys; +}; + +extern const struct nvkm_mmu_func nv04_mmu; + +const u8 *nv50_mmu_kind(struct nvkm_mmu *, int *count); + +const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count); + +const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *); + +struct nvkm_mmu_pt { + union { + struct nvkm_mmu_ptc *ptc; + struct nvkm_mmu_ptp *ptp; + }; + struct nvkm_memory *memory; + bool sub; + u16 base; + u64 addr; + struct list_head head; }; -int nvkm_vm_create(struct nvkm_mmu *, u64, u64, u64, u32, - struct lock_class_key *, struct nvkm_vm **); +void nvkm_mmu_ptc_dump(struct nvkm_mmu *); +struct nvkm_mmu_pt * +nvkm_mmu_ptc_get(struct nvkm_mmu *, u32 size, u32 align, bool zero); +void nvkm_mmu_ptc_put(struct nvkm_mmu *, bool force, struct nvkm_mmu_pt **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c new file mode 100644 index 000000000000..fac2f9a45ea6 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.c @@ -0,0 +1,192 @@ +/* + * 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 "umem.h" +#include "ummu.h" + +#include <core/client.h> +#include <core/memory.h> +#include <subdev/bar.h> + +#include <nvif/class.h> +#include <nvif/if000a.h> +#include <nvif/unpack.h> + +static const struct nvkm_object_func nvkm_umem; +struct nvkm_memory * +nvkm_umem_search(struct nvkm_client *client, u64 handle) +{ + struct nvkm_client *master = client->object.client; + struct nvkm_memory *memory = NULL; + struct nvkm_object *object; + struct nvkm_umem *umem; + + object = nvkm_object_search(client, handle, &nvkm_umem); + if (IS_ERR(object)) { + if (client->super && client != master) { + spin_lock(&master->lock); + list_for_each_entry(umem, &master->umem, head) { + if (umem->object.object == handle) { + memory = nvkm_memory_ref(umem->memory); + break; + } + } + spin_unlock(&master->lock); + } + } else { + umem = nvkm_umem(object); + if (!umem->priv || client->super) + memory = nvkm_memory_ref(umem->memory); + } + + return memory ? memory : ERR_PTR(-ENOENT); +} + +static int +nvkm_umem_unmap(struct nvkm_object *object) +{ + struct nvkm_umem *umem = nvkm_umem(object); + + if (!umem->map) + return -EEXIST; + + if (umem->io) { + if (!IS_ERR(umem->bar)) { + struct nvkm_device *device = umem->mmu->subdev.device; + nvkm_vmm_put(nvkm_bar_bar1_vmm(device), &umem->bar); + } else { + umem->bar = NULL; + } + } else { + vunmap(umem->map); + umem->map = NULL; + } + + return 0; +} + +static int +nvkm_umem_map(struct nvkm_object *object, void *argv, u32 argc, + enum nvkm_object_map *type, u64 *handle, u64 *length) +{ + struct nvkm_umem *umem = nvkm_umem(object); + struct nvkm_mmu *mmu = umem->mmu; + + if (!umem->mappable) + return -EINVAL; + if (umem->map) + return -EEXIST; + + if ((umem->type & NVKM_MEM_HOST) && !argc) { + int ret = nvkm_mem_map_host(umem->memory, &umem->map); + if (ret) + return ret; + + *handle = (unsigned long)(void *)umem->map; + *length = nvkm_memory_size(umem->memory); + *type = NVKM_OBJECT_MAP_VA; + return 0; + } else + if ((umem->type & NVKM_MEM_VRAM) || + (umem->type & NVKM_MEM_KIND)) { + int ret = mmu->func->mem.umap(mmu, umem->memory, argv, argc, + handle, length, &umem->bar); + if (ret) + return ret; + + *type = NVKM_OBJECT_MAP_IO; + } else { + return -EINVAL; + } + + umem->io = (*type == NVKM_OBJECT_MAP_IO); + return 0; +} + +static void * +nvkm_umem_dtor(struct nvkm_object *object) +{ + struct nvkm_umem *umem = nvkm_umem(object); + spin_lock(&umem->object.client->lock); + list_del_init(&umem->head); + spin_unlock(&umem->object.client->lock); + nvkm_memory_unref(&umem->memory); + return umem; +} + +static const struct nvkm_object_func +nvkm_umem = { + .dtor = nvkm_umem_dtor, + .map = nvkm_umem_map, + .unmap = nvkm_umem_unmap, +}; + +int +nvkm_umem_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_mmu *mmu = nvkm_ummu(oclass->parent)->mmu; + union { + struct nvif_mem_v0 v0; + } *args = argv; + struct nvkm_umem *umem; + int type, ret = -ENOSYS; + u8 page; + u64 size; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) { + type = args->v0.type; + page = args->v0.page; + size = args->v0.size; + } else + return ret; + + if (type >= mmu->type_nr) + return -EINVAL; + + if (!(umem = kzalloc(sizeof(*umem), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nvkm_umem, oclass, &umem->object); + umem->mmu = mmu; + umem->type = mmu->type[type].type; + umem->priv = oclass->client->super; + INIT_LIST_HEAD(&umem->head); + *pobject = &umem->object; + + if (mmu->type[type].type & NVKM_MEM_MAPPABLE) { + page = max_t(u8, page, PAGE_SHIFT); + umem->mappable = true; + } + + ret = nvkm_mem_new_type(mmu, type, page, size, argv, argc, + &umem->memory); + if (ret) + return ret; + + spin_lock(&umem->object.client->lock); + list_add(&umem->head, &umem->object.client->umem); + spin_unlock(&umem->object.client->lock); + + args->v0.page = nvkm_memory_page(umem->memory); + args->v0.addr = nvkm_memory_addr(umem->memory); + args->v0.size = nvkm_memory_size(umem->memory); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h new file mode 100644 index 000000000000..85cf692d620a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/umem.h @@ -0,0 +1,26 @@ +#ifndef __NVKM_UMEM_H__ +#define __NVKM_UMEM_H__ +#define nvkm_umem(p) container_of((p), struct nvkm_umem, object) +#include <core/object.h> +#include "mem.h" + +struct nvkm_umem { + struct nvkm_object object; + struct nvkm_mmu *mmu; + u8 type:8; + bool priv:1; + bool mappable:1; + bool io:1; + + struct nvkm_memory *memory; + struct list_head head; + + union { + struct nvkm_vma *bar; + void *map; + }; +}; + +int nvkm_umem_new(const struct nvkm_oclass *, void *argv, u32 argc, + struct nvkm_object **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c new file mode 100644 index 000000000000..353f10f92b77 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.c @@ -0,0 +1,178 @@ +/* + * 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 "ummu.h" +#include "umem.h" +#include "uvmm.h" + +#include <core/client.h> + +#include <nvif/if0008.h> +#include <nvif/unpack.h> + +static int +nvkm_ummu_sclass(struct nvkm_object *object, int index, + struct nvkm_oclass *oclass) +{ + struct nvkm_mmu *mmu = nvkm_ummu(object)->mmu; + + if (mmu->func->mem.user.oclass && oclass->client->super) { + if (index-- == 0) { + oclass->base = mmu->func->mem.user; + oclass->ctor = nvkm_umem_new; + return 0; + } + } + + if (mmu->func->vmm.user.oclass) { + if (index-- == 0) { + oclass->base = mmu->func->vmm.user; + oclass->ctor = nvkm_uvmm_new; + return 0; + } + } + + return -EINVAL; +} + +static int +nvkm_ummu_heap(struct nvkm_ummu *ummu, void *argv, u32 argc) +{ + struct nvkm_mmu *mmu = ummu->mmu; + union { + struct nvif_mmu_heap_v0 v0; + } *args = argv; + int ret = -ENOSYS; + u8 index; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + if ((index = args->v0.index) >= mmu->heap_nr) + return -EINVAL; + args->v0.size = mmu->heap[index].size; + } else + return ret; + + return 0; +} + +static int +nvkm_ummu_type(struct nvkm_ummu *ummu, void *argv, u32 argc) +{ + struct nvkm_mmu *mmu = ummu->mmu; + union { + struct nvif_mmu_type_v0 v0; + } *args = argv; + int ret = -ENOSYS; + u8 type, index; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + if ((index = args->v0.index) >= mmu->type_nr) + return -EINVAL; + type = mmu->type[index].type; + args->v0.heap = mmu->type[index].heap; + args->v0.vram = !!(type & NVKM_MEM_VRAM); + args->v0.host = !!(type & NVKM_MEM_HOST); + args->v0.comp = !!(type & NVKM_MEM_COMP); + args->v0.disp = !!(type & NVKM_MEM_DISP); + args->v0.kind = !!(type & NVKM_MEM_KIND); + args->v0.mappable = !!(type & NVKM_MEM_MAPPABLE); + args->v0.coherent = !!(type & NVKM_MEM_COHERENT); + args->v0.uncached = !!(type & NVKM_MEM_UNCACHED); + } else + return ret; + + return 0; +} + +static int +nvkm_ummu_kind(struct nvkm_ummu *ummu, void *argv, u32 argc) +{ + struct nvkm_mmu *mmu = ummu->mmu; + union { + struct nvif_mmu_kind_v0 v0; + } *args = argv; + const u8 *kind = NULL; + int ret = -ENOSYS, count = 0; + + if (mmu->func->kind) + kind = mmu->func->kind(mmu, &count); + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) { + if (argc != args->v0.count * sizeof(*args->v0.data)) + return -EINVAL; + if (args->v0.count > count) + return -EINVAL; + memcpy(args->v0.data, kind, args->v0.count); + } else + return ret; + + return 0; +} + +static int +nvkm_ummu_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_ummu *ummu = nvkm_ummu(object); + switch (mthd) { + case NVIF_MMU_V0_HEAP: return nvkm_ummu_heap(ummu, argv, argc); + case NVIF_MMU_V0_TYPE: return nvkm_ummu_type(ummu, argv, argc); + case NVIF_MMU_V0_KIND: return nvkm_ummu_kind(ummu, argv, argc); + default: + break; + } + return -EINVAL; +} + +static const struct nvkm_object_func +nvkm_ummu = { + .mthd = nvkm_ummu_mthd, + .sclass = nvkm_ummu_sclass, +}; + +int +nvkm_ummu_new(struct nvkm_device *device, const struct nvkm_oclass *oclass, + void *argv, u32 argc, struct nvkm_object **pobject) +{ + union { + struct nvif_mmu_v0 v0; + } *args = argv; + struct nvkm_mmu *mmu = device->mmu; + struct nvkm_ummu *ummu; + int ret = -ENOSYS, kinds = 0; + + if (mmu->func->kind) + mmu->func->kind(mmu, &kinds); + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + args->v0.dmabits = mmu->dma_bits; + args->v0.heap_nr = mmu->heap_nr; + args->v0.type_nr = mmu->type_nr; + args->v0.kind_nr = kinds; + } else + return ret; + + if (!(ummu = kzalloc(sizeof(*ummu), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nvkm_ummu, oclass, &ummu->object); + ummu->mmu = mmu; + *pobject = &ummu->object; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.h new file mode 100644 index 000000000000..0cd510dcfc68 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/ummu.h @@ -0,0 +1,14 @@ +#ifndef __NVKM_UMMU_H__ +#define __NVKM_UMMU_H__ +#define nvkm_ummu(p) container_of((p), struct nvkm_ummu, object) +#include <core/object.h> +#include "priv.h" + +struct nvkm_ummu { + struct nvkm_object object; + struct nvkm_mmu *mmu; +}; + +int nvkm_ummu_new(struct nvkm_device *, const struct nvkm_oclass *, + void *argv, u32 argc, struct nvkm_object **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c new file mode 100644 index 000000000000..fa81d0c1ba41 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c @@ -0,0 +1,352 @@ +/* + * 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 "uvmm.h" +#include "umem.h" +#include "ummu.h" + +#include <core/client.h> +#include <core/memory.h> + +#include <nvif/if000c.h> +#include <nvif/unpack.h> + +static const struct nvkm_object_func nvkm_uvmm; +struct nvkm_vmm * +nvkm_uvmm_search(struct nvkm_client *client, u64 handle) +{ + struct nvkm_object *object; + + object = nvkm_object_search(client, handle, &nvkm_uvmm); + if (IS_ERR(object)) + return (void *)object; + + return nvkm_uvmm(object)->vmm; +} + +static int +nvkm_uvmm_mthd_unmap(struct nvkm_uvmm *uvmm, void *argv, u32 argc) +{ + struct nvkm_client *client = uvmm->object.client; + union { + struct nvif_vmm_unmap_v0 v0; + } *args = argv; + struct nvkm_vmm *vmm = uvmm->vmm; + struct nvkm_vma *vma; + int ret = -ENOSYS; + u64 addr; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + addr = args->v0.addr; + } else + return ret; + + mutex_lock(&vmm->mutex); + vma = nvkm_vmm_node_search(vmm, addr); + if (ret = -ENOENT, !vma || vma->addr != addr) { + VMM_DEBUG(vmm, "lookup %016llx: %016llx", + addr, vma ? vma->addr : ~0ULL); + goto done; + } + + if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) { + VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr, + vma->user, !client->super, vma->busy); + goto done; + } + + if (ret = -EINVAL, !vma->memory) { + VMM_DEBUG(vmm, "unmapped"); + goto done; + } + + nvkm_vmm_unmap_locked(vmm, vma); + ret = 0; +done: + mutex_unlock(&vmm->mutex); + return ret; +} + +static int +nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc) +{ + struct nvkm_client *client = uvmm->object.client; + union { + struct nvif_vmm_map_v0 v0; + } *args = argv; + u64 addr, size, handle, offset; + struct nvkm_vmm *vmm = uvmm->vmm; + struct nvkm_vma *vma; + struct nvkm_memory *memory; + int ret = -ENOSYS; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, true))) { + addr = args->v0.addr; + size = args->v0.size; + handle = args->v0.memory; + offset = args->v0.offset; + } else + return ret; + + if (IS_ERR((memory = nvkm_umem_search(client, handle)))) { + VMM_DEBUG(vmm, "memory %016llx %ld\n", handle, PTR_ERR(memory)); + return PTR_ERR(memory); + } + + mutex_lock(&vmm->mutex); + if (ret = -ENOENT, !(vma = nvkm_vmm_node_search(vmm, addr))) { + VMM_DEBUG(vmm, "lookup %016llx", addr); + goto fail; + } + + if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) { + VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr, + vma->user, !client->super, vma->busy); + goto fail; + } + + if (ret = -EINVAL, vma->addr != addr || vma->size != size) { + if (addr + size > vma->addr + vma->size || vma->memory || + (vma->refd == NVKM_VMA_PAGE_NONE && !vma->mapref)) { + VMM_DEBUG(vmm, "split %d %d %d " + "%016llx %016llx %016llx %016llx", + !!vma->memory, vma->refd, vma->mapref, + addr, size, vma->addr, (u64)vma->size); + goto fail; + } + + if (vma->addr != addr) { + const u64 tail = vma->size + vma->addr - addr; + if (ret = -ENOMEM, !(vma = nvkm_vma_tail(vma, tail))) + goto fail; + vma->part = true; + nvkm_vmm_node_insert(vmm, vma); + } + + if (vma->size != size) { + const u64 tail = vma->size - size; + struct nvkm_vma *tmp; + if (ret = -ENOMEM, !(tmp = nvkm_vma_tail(vma, tail))) { + nvkm_vmm_unmap_region(vmm, vma); + goto fail; + } + tmp->part = true; + nvkm_vmm_node_insert(vmm, tmp); + } + } + vma->busy = true; + mutex_unlock(&vmm->mutex); + + ret = nvkm_memory_map(memory, offset, vmm, vma, argv, argc); + if (ret == 0) { + /* Successful map will clear vma->busy. */ + nvkm_memory_unref(&memory); + return 0; + } + + mutex_lock(&vmm->mutex); + vma->busy = false; + nvkm_vmm_unmap_region(vmm, vma); +fail: + mutex_unlock(&vmm->mutex); + nvkm_memory_unref(&memory); + return ret; +} + +static int +nvkm_uvmm_mthd_put(struct nvkm_uvmm *uvmm, void *argv, u32 argc) +{ + struct nvkm_client *client = uvmm->object.client; + union { + struct nvif_vmm_put_v0 v0; + } *args = argv; + struct nvkm_vmm *vmm = uvmm->vmm; + struct nvkm_vma *vma; + int ret = -ENOSYS; + u64 addr; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + addr = args->v0.addr; + } else + return ret; + + mutex_lock(&vmm->mutex); + vma = nvkm_vmm_node_search(vmm, args->v0.addr); + if (ret = -ENOENT, !vma || vma->addr != addr || vma->part) { + VMM_DEBUG(vmm, "lookup %016llx: %016llx %d", addr, + vma ? vma->addr : ~0ULL, vma ? vma->part : 0); + goto done; + } + + if (ret = -ENOENT, (!vma->user && !client->super) || vma->busy) { + VMM_DEBUG(vmm, "denied %016llx: %d %d %d", addr, + vma->user, !client->super, vma->busy); + goto done; + } + + nvkm_vmm_put_locked(vmm, vma); + ret = 0; +done: + mutex_unlock(&vmm->mutex); + return ret; +} + +static int +nvkm_uvmm_mthd_get(struct nvkm_uvmm *uvmm, void *argv, u32 argc) +{ + struct nvkm_client *client = uvmm->object.client; + union { + struct nvif_vmm_get_v0 v0; + } *args = argv; + struct nvkm_vmm *vmm = uvmm->vmm; + struct nvkm_vma *vma; + int ret = -ENOSYS; + bool getref, mapref, sparse; + u8 page, align; + u64 size; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + getref = args->v0.type == NVIF_VMM_GET_V0_PTES; + mapref = args->v0.type == NVIF_VMM_GET_V0_ADDR; + sparse = args->v0.sparse; + page = args->v0.page; + align = args->v0.align; + size = args->v0.size; + } else + return ret; + + mutex_lock(&vmm->mutex); + ret = nvkm_vmm_get_locked(vmm, getref, mapref, sparse, + page, align, size, &vma); + mutex_unlock(&vmm->mutex); + if (ret) + return ret; + + args->v0.addr = vma->addr; + vma->user = !client->super; + return ret; +} + +static int +nvkm_uvmm_mthd_page(struct nvkm_uvmm *uvmm, void *argv, u32 argc) +{ + union { + struct nvif_vmm_page_v0 v0; + } *args = argv; + const struct nvkm_vmm_page *page; + int ret = -ENOSYS; + u8 type, index, nr; + + page = uvmm->vmm->func->page; + for (nr = 0; page[nr].shift; nr++); + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + if ((index = args->v0.index) >= nr) + return -EINVAL; + type = page[index].type; + args->v0.shift = page[index].shift; + args->v0.sparse = !!(type & NVKM_VMM_PAGE_SPARSE); + args->v0.vram = !!(type & NVKM_VMM_PAGE_VRAM); + args->v0.host = !!(type & NVKM_VMM_PAGE_HOST); + args->v0.comp = !!(type & NVKM_VMM_PAGE_COMP); + } else + return -ENOSYS; + + return 0; +} + +static int +nvkm_uvmm_mthd(struct nvkm_object *object, u32 mthd, void *argv, u32 argc) +{ + struct nvkm_uvmm *uvmm = nvkm_uvmm(object); + switch (mthd) { + case NVIF_VMM_V0_PAGE : return nvkm_uvmm_mthd_page (uvmm, argv, argc); + case NVIF_VMM_V0_GET : return nvkm_uvmm_mthd_get (uvmm, argv, argc); + case NVIF_VMM_V0_PUT : return nvkm_uvmm_mthd_put (uvmm, argv, argc); + case NVIF_VMM_V0_MAP : return nvkm_uvmm_mthd_map (uvmm, argv, argc); + case NVIF_VMM_V0_UNMAP : return nvkm_uvmm_mthd_unmap (uvmm, argv, argc); + default: + break; + } + return -EINVAL; +} + +static void * +nvkm_uvmm_dtor(struct nvkm_object *object) +{ + struct nvkm_uvmm *uvmm = nvkm_uvmm(object); + nvkm_vmm_unref(&uvmm->vmm); + return uvmm; +} + +static const struct nvkm_object_func +nvkm_uvmm = { + .dtor = nvkm_uvmm_dtor, + .mthd = nvkm_uvmm_mthd, +}; + +int +nvkm_uvmm_new(const struct nvkm_oclass *oclass, void *argv, u32 argc, + struct nvkm_object **pobject) +{ + struct nvkm_mmu *mmu = nvkm_ummu(oclass->parent)->mmu; + const bool more = oclass->base.maxver >= 0; + union { + struct nvif_vmm_v0 v0; + } *args = argv; + const struct nvkm_vmm_page *page; + struct nvkm_uvmm *uvmm; + int ret = -ENOSYS; + u64 addr, size; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, more))) { + addr = args->v0.addr; + size = args->v0.size; + } else + return ret; + + if (!(uvmm = kzalloc(sizeof(*uvmm), GFP_KERNEL))) + return -ENOMEM; + nvkm_object_ctor(&nvkm_uvmm, oclass, &uvmm->object); + *pobject = &uvmm->object; + + if (!mmu->vmm) { + ret = mmu->func->vmm.ctor(mmu, addr, size, argv, argc, + NULL, "user", &uvmm->vmm); + if (ret) + return ret; + + uvmm->vmm->debug = max(uvmm->vmm->debug, oclass->client->debug); + } else { + if (size) + return -EINVAL; + + uvmm->vmm = nvkm_vmm_ref(mmu->vmm); + } + + page = uvmm->vmm->func->page; + args->v0.page_nr = 0; + while (page && (page++)->shift) + args->v0.page_nr++; + args->v0.addr = uvmm->vmm->start; + args->v0.size = uvmm->vmm->limit; + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.h new file mode 100644 index 000000000000..71dab55e18a9 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.h @@ -0,0 +1,14 @@ +#ifndef __NVKM_UVMM_H__ +#define __NVKM_UVMM_H__ +#define nvkm_uvmm(p) container_of((p), struct nvkm_uvmm, object) +#include <core/object.h> +#include "vmm.h" + +struct nvkm_uvmm { + struct nvkm_object object; + struct nvkm_vmm *vmm; +}; + +int nvkm_uvmm_new(const struct nvkm_oclass *, void *argv, u32 argc, + struct nvkm_object **); +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c new file mode 100644 index 000000000000..e35d3e17cd7c --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c @@ -0,0 +1,1513 @@ +/* + * 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. + */ +#define NVKM_VMM_LEVELS_MAX 5 +#include "vmm.h" + +#include <subdev/fb.h> + +static void +nvkm_vmm_pt_del(struct nvkm_vmm_pt **ppgt) +{ + struct nvkm_vmm_pt *pgt = *ppgt; + if (pgt) { + kvfree(pgt->pde); + kfree(pgt); + *ppgt = NULL; + } +} + + +static struct nvkm_vmm_pt * +nvkm_vmm_pt_new(const struct nvkm_vmm_desc *desc, bool sparse, + const struct nvkm_vmm_page *page) +{ + const u32 pten = 1 << desc->bits; + struct nvkm_vmm_pt *pgt; + u32 lpte = 0; + + if (desc->type > PGT) { + if (desc->type == SPT) { + const struct nvkm_vmm_desc *pair = page[-1].desc; + lpte = pten >> (desc->bits - pair->bits); + } else { + lpte = pten; + } + } + + if (!(pgt = kzalloc(sizeof(*pgt) + lpte, GFP_KERNEL))) + return NULL; + pgt->page = page ? page->shift : 0; + pgt->sparse = sparse; + + if (desc->type == PGD) { + pgt->pde = kvzalloc(sizeof(*pgt->pde) * pten, GFP_KERNEL); + if (!pgt->pde) { + kfree(pgt); + return NULL; + } + } + + return pgt; +} + +struct nvkm_vmm_iter { + const struct nvkm_vmm_page *page; + const struct nvkm_vmm_desc *desc; + struct nvkm_vmm *vmm; + u64 cnt; + u16 max, lvl; + u32 pte[NVKM_VMM_LEVELS_MAX]; + struct nvkm_vmm_pt *pt[NVKM_VMM_LEVELS_MAX]; + int flush; +}; + +#ifdef CONFIG_NOUVEAU_DEBUG_MMU +static const char * +nvkm_vmm_desc_type(const struct nvkm_vmm_desc *desc) +{ + switch (desc->type) { + case PGD: return "PGD"; + case PGT: return "PGT"; + case SPT: return "SPT"; + case LPT: return "LPT"; + default: + return "UNKNOWN"; + } +} + +static void +nvkm_vmm_trace(struct nvkm_vmm_iter *it, char *buf) +{ + int lvl; + for (lvl = it->max; lvl >= 0; lvl--) { + if (lvl >= it->lvl) + buf += sprintf(buf, "%05x:", it->pte[lvl]); + else + buf += sprintf(buf, "xxxxx:"); + } +} + +#define TRA(i,f,a...) do { \ + char _buf[NVKM_VMM_LEVELS_MAX * 7]; \ + struct nvkm_vmm_iter *_it = (i); \ + nvkm_vmm_trace(_it, _buf); \ + VMM_TRACE(_it->vmm, "%s "f, _buf, ##a); \ +} while(0) +#else +#define TRA(i,f,a...) +#endif + +static inline void +nvkm_vmm_flush_mark(struct nvkm_vmm_iter *it) +{ + it->flush = min(it->flush, it->max - it->lvl); +} + +static inline void +nvkm_vmm_flush(struct nvkm_vmm_iter *it) +{ + if (it->flush != NVKM_VMM_LEVELS_MAX) { + if (it->vmm->func->flush) { + TRA(it, "flush: %d", it->flush); + it->vmm->func->flush(it->vmm, it->flush); + } + it->flush = NVKM_VMM_LEVELS_MAX; + } +} + +static void +nvkm_vmm_unref_pdes(struct nvkm_vmm_iter *it) +{ + const struct nvkm_vmm_desc *desc = it->desc; + const int type = desc[it->lvl].type == SPT; + struct nvkm_vmm_pt *pgd = it->pt[it->lvl + 1]; + struct nvkm_vmm_pt *pgt = it->pt[it->lvl]; + struct nvkm_mmu_pt *pt = pgt->pt[type]; + struct nvkm_vmm *vmm = it->vmm; + u32 pdei = it->pte[it->lvl + 1]; + + /* Recurse up the tree, unreferencing/destroying unneeded PDs. */ + it->lvl++; + if (--pgd->refs[0]) { + const struct nvkm_vmm_desc_func *func = desc[it->lvl].func; + /* PD has other valid PDEs, so we need a proper update. */ + TRA(it, "PDE unmap %s", nvkm_vmm_desc_type(&desc[it->lvl - 1])); + pgt->pt[type] = NULL; + if (!pgt->refs[!type]) { + /* PDE no longer required. */ + if (pgd->pt[0]) { + if (pgt->sparse) { + func->sparse(vmm, pgd->pt[0], pdei, 1); + pgd->pde[pdei] = NVKM_VMM_PDE_SPARSE; + } else { + func->unmap(vmm, pgd->pt[0], pdei, 1); + pgd->pde[pdei] = NULL; + } + } else { + /* Special handling for Tesla-class GPUs, + * where there's no central PD, but each + * instance has its own embedded PD. + */ + func->pde(vmm, pgd, pdei); + pgd->pde[pdei] = NULL; + } + } else { + /* PDE was pointing at dual-PTs and we're removing + * one of them, leaving the other in place. + */ + func->pde(vmm, pgd, pdei); + } + + /* GPU may have cached the PTs, flush before freeing. */ + nvkm_vmm_flush_mark(it); + nvkm_vmm_flush(it); + } else { + /* PD has no valid PDEs left, so we can just destroy it. */ + nvkm_vmm_unref_pdes(it); + } + + /* Destroy PD/PT. */ + TRA(it, "PDE free %s", nvkm_vmm_desc_type(&desc[it->lvl - 1])); + nvkm_mmu_ptc_put(vmm->mmu, vmm->bootstrapped, &pt); + if (!pgt->refs[!type]) + nvkm_vmm_pt_del(&pgt); + it->lvl--; +} + +static void +nvkm_vmm_unref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt, + const struct nvkm_vmm_desc *desc, u32 ptei, u32 ptes) +{ + const struct nvkm_vmm_desc *pair = it->page[-1].desc; + const u32 sptb = desc->bits - pair->bits; + const u32 sptn = 1 << sptb; + struct nvkm_vmm *vmm = it->vmm; + u32 spti = ptei & (sptn - 1), lpti, pteb; + + /* Determine how many SPTEs are being touched under each LPTE, + * and drop reference counts. + */ + for (lpti = ptei >> sptb; ptes; spti = 0, lpti++) { + const u32 pten = min(sptn - spti, ptes); + pgt->pte[lpti] -= pten; + ptes -= pten; + } + + /* We're done here if there's no corresponding LPT. */ + if (!pgt->refs[0]) + return; + + for (ptei = pteb = ptei >> sptb; ptei < lpti; pteb = ptei) { + /* Skip over any LPTEs that still have valid SPTEs. */ + if (pgt->pte[pteb] & NVKM_VMM_PTE_SPTES) { + for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { + if (!(pgt->pte[ptei] & NVKM_VMM_PTE_SPTES)) + break; + } + continue; + } + + /* As there's no more non-UNMAPPED SPTEs left in the range + * covered by a number of LPTEs, the LPTEs once again take + * control over their address range. + * + * Determine how many LPTEs need to transition state. + */ + pgt->pte[ptei] &= ~NVKM_VMM_PTE_VALID; + for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { + if (pgt->pte[ptei] & NVKM_VMM_PTE_SPTES) + break; + pgt->pte[ptei] &= ~NVKM_VMM_PTE_VALID; + } + + if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) { + TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes); + pair->func->sparse(vmm, pgt->pt[0], pteb, ptes); + } else + if (pair->func->invalid) { + /* If the MMU supports it, restore the LPTE to the + * INVALID state to tell the MMU there is no point + * trying to fetch the corresponding SPTEs. + */ + TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes); + pair->func->invalid(vmm, pgt->pt[0], pteb, ptes); + } + } +} + +static bool +nvkm_vmm_unref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) +{ + const struct nvkm_vmm_desc *desc = it->desc; + const int type = desc->type == SPT; + struct nvkm_vmm_pt *pgt = it->pt[0]; + + /* Drop PTE references. */ + pgt->refs[type] -= ptes; + + /* Dual-PTs need special handling, unless PDE becoming invalid. */ + if (desc->type == SPT && (pgt->refs[0] || pgt->refs[1])) + nvkm_vmm_unref_sptes(it, pgt, desc, ptei, ptes); + + /* PT no longer neeed? Destroy it. */ + if (!pgt->refs[type]) { + it->lvl++; + TRA(it, "%s empty", nvkm_vmm_desc_type(desc)); + it->lvl--; + nvkm_vmm_unref_pdes(it); + return false; /* PTE writes for unmap() not necessary. */ + } + + return true; +} + +static void +nvkm_vmm_ref_sptes(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgt, + const struct nvkm_vmm_desc *desc, u32 ptei, u32 ptes) +{ + const struct nvkm_vmm_desc *pair = it->page[-1].desc; + const u32 sptb = desc->bits - pair->bits; + const u32 sptn = 1 << sptb; + struct nvkm_vmm *vmm = it->vmm; + u32 spti = ptei & (sptn - 1), lpti, pteb; + + /* Determine how many SPTEs are being touched under each LPTE, + * and increase reference counts. + */ + for (lpti = ptei >> sptb; ptes; spti = 0, lpti++) { + const u32 pten = min(sptn - spti, ptes); + pgt->pte[lpti] += pten; + ptes -= pten; + } + + /* We're done here if there's no corresponding LPT. */ + if (!pgt->refs[0]) + return; + + for (ptei = pteb = ptei >> sptb; ptei < lpti; pteb = ptei) { + /* Skip over any LPTEs that already have valid SPTEs. */ + if (pgt->pte[pteb] & NVKM_VMM_PTE_VALID) { + for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { + if (!(pgt->pte[ptei] & NVKM_VMM_PTE_VALID)) + break; + } + continue; + } + + /* As there are now non-UNMAPPED SPTEs in the range covered + * by a number of LPTEs, we need to transfer control of the + * address range to the SPTEs. + * + * Determine how many LPTEs need to transition state. + */ + pgt->pte[ptei] |= NVKM_VMM_PTE_VALID; + for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { + if (pgt->pte[ptei] & NVKM_VMM_PTE_VALID) + break; + pgt->pte[ptei] |= NVKM_VMM_PTE_VALID; + } + + if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) { + const u32 spti = pteb * sptn; + const u32 sptc = ptes * sptn; + /* The entire LPTE is marked as sparse, we need + * to make sure that the SPTEs are too. + */ + TRA(it, "SPTE %05x: U -> S %d PTEs", spti, sptc); + desc->func->sparse(vmm, pgt->pt[1], spti, sptc); + /* Sparse LPTEs prevent SPTEs from being accessed. */ + TRA(it, "LPTE %05x: S -> U %d PTEs", pteb, ptes); + pair->func->unmap(vmm, pgt->pt[0], pteb, ptes); + } else + if (pair->func->invalid) { + /* MMU supports blocking SPTEs by marking an LPTE + * as INVALID. We need to reverse that here. + */ + TRA(it, "LPTE %05x: I -> U %d PTEs", pteb, ptes); + pair->func->unmap(vmm, pgt->pt[0], pteb, ptes); + } + } +} + +static bool +nvkm_vmm_ref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) +{ + const struct nvkm_vmm_desc *desc = it->desc; + const int type = desc->type == SPT; + struct nvkm_vmm_pt *pgt = it->pt[0]; + + /* Take PTE references. */ + pgt->refs[type] += ptes; + + /* Dual-PTs need special handling. */ + if (desc->type == SPT) + nvkm_vmm_ref_sptes(it, pgt, desc, ptei, ptes); + + return true; +} + +static void +nvkm_vmm_sparse_ptes(const struct nvkm_vmm_desc *desc, + struct nvkm_vmm_pt *pgt, u32 ptei, u32 ptes) +{ + if (desc->type == PGD) { + while (ptes--) + pgt->pde[ptei++] = NVKM_VMM_PDE_SPARSE; + } else + if (desc->type == LPT) { + memset(&pgt->pte[ptei], NVKM_VMM_PTE_SPARSE, ptes); + } +} + +static bool +nvkm_vmm_sparse_unref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) +{ + struct nvkm_vmm_pt *pt = it->pt[0]; + if (it->desc->type == PGD) + memset(&pt->pde[ptei], 0x00, sizeof(pt->pde[0]) * ptes); + else + if (it->desc->type == LPT) + memset(&pt->pte[ptei], 0x00, sizeof(pt->pte[0]) * ptes); + return nvkm_vmm_unref_ptes(it, ptei, ptes); +} + +static bool +nvkm_vmm_sparse_ref_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) +{ + nvkm_vmm_sparse_ptes(it->desc, it->pt[0], ptei, ptes); + return nvkm_vmm_ref_ptes(it, ptei, ptes); +} + +static bool +nvkm_vmm_ref_hwpt(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgd, u32 pdei) +{ + const struct nvkm_vmm_desc *desc = &it->desc[it->lvl - 1]; + const int type = desc->type == SPT; + struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; + const bool zero = !pgt->sparse && !desc->func->invalid; + struct nvkm_vmm *vmm = it->vmm; + struct nvkm_mmu *mmu = vmm->mmu; + struct nvkm_mmu_pt *pt; + u32 pten = 1 << desc->bits; + u32 pteb, ptei, ptes; + u32 size = desc->size * pten; + + pgd->refs[0]++; + + pgt->pt[type] = nvkm_mmu_ptc_get(mmu, size, desc->align, zero); + if (!pgt->pt[type]) { + it->lvl--; + nvkm_vmm_unref_pdes(it); + return false; + } + + if (zero) + goto done; + + pt = pgt->pt[type]; + + if (desc->type == LPT && pgt->refs[1]) { + /* SPT already exists covering the same range as this LPT, + * which means we need to be careful that any LPTEs which + * overlap valid SPTEs are unmapped as opposed to invalid + * or sparse, which would prevent the MMU from looking at + * the SPTEs on some GPUs. + */ + for (ptei = pteb = 0; ptei < pten; pteb = ptei) { + bool spte = pgt->pte[ptei] & NVKM_VMM_PTE_SPTES; + for (ptes = 1, ptei++; ptei < pten; ptes++, ptei++) { + bool next = pgt->pte[ptei] & NVKM_VMM_PTE_SPTES; + if (spte != next) + break; + } + + if (!spte) { + if (pgt->sparse) + desc->func->sparse(vmm, pt, pteb, ptes); + else + desc->func->invalid(vmm, pt, pteb, ptes); + memset(&pgt->pte[pteb], 0x00, ptes); + } else { + desc->func->unmap(vmm, pt, pteb, ptes); + while (ptes--) + pgt->pte[pteb++] |= NVKM_VMM_PTE_VALID; + } + } + } else { + if (pgt->sparse) { + nvkm_vmm_sparse_ptes(desc, pgt, 0, pten); + desc->func->sparse(vmm, pt, 0, pten); + } else { + desc->func->invalid(vmm, pt, 0, pten); + } + } + +done: + TRA(it, "PDE write %s", nvkm_vmm_desc_type(desc)); + it->desc[it->lvl].func->pde(it->vmm, pgd, pdei); + nvkm_vmm_flush_mark(it); + return true; +} + +static bool +nvkm_vmm_ref_swpt(struct nvkm_vmm_iter *it, struct nvkm_vmm_pt *pgd, u32 pdei) +{ + const struct nvkm_vmm_desc *desc = &it->desc[it->lvl - 1]; + struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; + + pgt = nvkm_vmm_pt_new(desc, NVKM_VMM_PDE_SPARSED(pgt), it->page); + if (!pgt) { + if (!pgd->refs[0]) + nvkm_vmm_unref_pdes(it); + return false; + } + + pgd->pde[pdei] = pgt; + return true; +} + +static inline u64 +nvkm_vmm_iter(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, const char *name, bool ref, + bool (*REF_PTES)(struct nvkm_vmm_iter *, u32, u32), + nvkm_vmm_pte_func MAP_PTES, struct nvkm_vmm_map *map, + nvkm_vmm_pxe_func CLR_PTES) +{ + const struct nvkm_vmm_desc *desc = page->desc; + struct nvkm_vmm_iter it; + u64 bits = addr >> page->shift; + + it.page = page; + it.desc = desc; + it.vmm = vmm; + it.cnt = size >> page->shift; + it.flush = NVKM_VMM_LEVELS_MAX; + + /* Deconstruct address into PTE indices for each mapping level. */ + for (it.lvl = 0; desc[it.lvl].bits; it.lvl++) { + it.pte[it.lvl] = bits & ((1 << desc[it.lvl].bits) - 1); + bits >>= desc[it.lvl].bits; + } + it.max = --it.lvl; + it.pt[it.max] = vmm->pd; + + it.lvl = 0; + TRA(&it, "%s: %016llx %016llx %d %lld PTEs", name, + addr, size, page->shift, it.cnt); + it.lvl = it.max; + + /* Depth-first traversal of page tables. */ + while (it.cnt) { + struct nvkm_vmm_pt *pgt = it.pt[it.lvl]; + const int type = desc->type == SPT; + const u32 pten = 1 << desc->bits; + const u32 ptei = it.pte[0]; + const u32 ptes = min_t(u64, it.cnt, pten - ptei); + + /* Walk down the tree, finding page tables for each level. */ + for (; it.lvl; it.lvl--) { + const u32 pdei = it.pte[it.lvl]; + struct nvkm_vmm_pt *pgd = pgt; + + /* Software PT. */ + if (ref && NVKM_VMM_PDE_INVALID(pgd->pde[pdei])) { + if (!nvkm_vmm_ref_swpt(&it, pgd, pdei)) + goto fail; + } + it.pt[it.lvl - 1] = pgt = pgd->pde[pdei]; + + /* Hardware PT. + * + * This is a separate step from above due to GF100 and + * newer having dual page tables at some levels, which + * are refcounted independently. + */ + if (ref && !pgt->refs[desc[it.lvl - 1].type == SPT]) { + if (!nvkm_vmm_ref_hwpt(&it, pgd, pdei)) + goto fail; + } + } + + /* Handle PTE updates. */ + if (!REF_PTES || REF_PTES(&it, ptei, ptes)) { + struct nvkm_mmu_pt *pt = pgt->pt[type]; + if (MAP_PTES || CLR_PTES) { + if (MAP_PTES) + MAP_PTES(vmm, pt, ptei, ptes, map); + else + CLR_PTES(vmm, pt, ptei, ptes); + nvkm_vmm_flush_mark(&it); + } + } + + /* Walk back up the tree to the next position. */ + it.pte[it.lvl] += ptes; + it.cnt -= ptes; + if (it.cnt) { + while (it.pte[it.lvl] == (1 << desc[it.lvl].bits)) { + it.pte[it.lvl++] = 0; + it.pte[it.lvl]++; + } + } + }; + + nvkm_vmm_flush(&it); + return ~0ULL; + +fail: + /* Reconstruct the failure address so the caller is able to + * reverse any partially completed operations. + */ + addr = it.pte[it.max--]; + do { + addr = addr << desc[it.max].bits; + addr |= it.pte[it.max]; + } while (it.max--); + + return addr << page->shift; +} + +static void +nvkm_vmm_ptes_sparse_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size) +{ + nvkm_vmm_iter(vmm, page, addr, size, "sparse unref", false, + nvkm_vmm_sparse_unref_ptes, NULL, NULL, + page->desc->func->invalid ? + page->desc->func->invalid : page->desc->func->unmap); +} + +static int +nvkm_vmm_ptes_sparse_get(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size) +{ + if ((page->type & NVKM_VMM_PAGE_SPARSE)) { + u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "sparse ref", + true, nvkm_vmm_sparse_ref_ptes, NULL, + NULL, page->desc->func->sparse); + if (fail != ~0ULL) { + if ((size = fail - addr)) + nvkm_vmm_ptes_sparse_put(vmm, page, addr, size); + return -ENOMEM; + } + return 0; + } + return -EINVAL; +} + +static int +nvkm_vmm_ptes_sparse(struct nvkm_vmm *vmm, u64 addr, u64 size, bool ref) +{ + const struct nvkm_vmm_page *page = vmm->func->page; + int m = 0, i; + u64 start = addr; + u64 block; + + while (size) { + /* Limit maximum page size based on remaining size. */ + while (size < (1ULL << page[m].shift)) + m++; + i = m; + + /* Find largest page size suitable for alignment. */ + while (!IS_ALIGNED(addr, 1ULL << page[i].shift)) + i++; + + /* Determine number of PTEs at this page size. */ + if (i != m) { + /* Limited to alignment boundary of next page size. */ + u64 next = 1ULL << page[i - 1].shift; + u64 part = ALIGN(addr, next) - addr; + if (size - part >= next) + block = (part >> page[i].shift) << page[i].shift; + else + block = (size >> page[i].shift) << page[i].shift; + } else { + block = (size >> page[i].shift) << page[i].shift;; + } + + /* Perform operation. */ + if (ref) { + int ret = nvkm_vmm_ptes_sparse_get(vmm, &page[i], addr, block); + if (ret) { + if ((size = addr - start)) + nvkm_vmm_ptes_sparse(vmm, start, size, false); + return ret; + } + } else { + nvkm_vmm_ptes_sparse_put(vmm, &page[i], addr, block); + } + + size -= block; + addr += block; + } + + return 0; +} + +static void +nvkm_vmm_ptes_unmap_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, bool sparse) +{ + const struct nvkm_vmm_desc_func *func = page->desc->func; + nvkm_vmm_iter(vmm, page, addr, size, "unmap + unref", + false, nvkm_vmm_unref_ptes, NULL, NULL, + sparse ? func->sparse : func->invalid ? func->invalid : + func->unmap); +} + +static int +nvkm_vmm_ptes_get_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, struct nvkm_vmm_map *map, + nvkm_vmm_pte_func func) +{ + u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref + map", true, + nvkm_vmm_ref_ptes, func, map, NULL); + if (fail != ~0ULL) { + if ((size = fail - addr)) + nvkm_vmm_ptes_unmap_put(vmm, page, addr, size, false); + return -ENOMEM; + } + return 0; +} + +static void +nvkm_vmm_ptes_unmap(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, bool sparse) +{ + const struct nvkm_vmm_desc_func *func = page->desc->func; + nvkm_vmm_iter(vmm, page, addr, size, "unmap", false, NULL, NULL, NULL, + sparse ? func->sparse : func->invalid ? func->invalid : + func->unmap); +} + +static void +nvkm_vmm_ptes_map(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size, struct nvkm_vmm_map *map, + nvkm_vmm_pte_func func) +{ + nvkm_vmm_iter(vmm, page, addr, size, "map", false, + NULL, func, map, NULL); +} + +static void +nvkm_vmm_ptes_put(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size) +{ + nvkm_vmm_iter(vmm, page, addr, size, "unref", false, + nvkm_vmm_unref_ptes, NULL, NULL, NULL); +} + +static int +nvkm_vmm_ptes_get(struct nvkm_vmm *vmm, const struct nvkm_vmm_page *page, + u64 addr, u64 size) +{ + u64 fail = nvkm_vmm_iter(vmm, page, addr, size, "ref", true, + nvkm_vmm_ref_ptes, NULL, NULL, NULL); + if (fail != ~0ULL) { + if (fail != addr) + nvkm_vmm_ptes_put(vmm, page, addr, fail - addr); + return -ENOMEM; + } + return 0; +} + +static inline struct nvkm_vma * +nvkm_vma_new(u64 addr, u64 size) +{ + struct nvkm_vma *vma = kzalloc(sizeof(*vma), GFP_KERNEL); + if (vma) { + vma->addr = addr; + vma->size = size; + vma->page = NVKM_VMA_PAGE_NONE; + vma->refd = NVKM_VMA_PAGE_NONE; + } + return vma; +} + +struct nvkm_vma * +nvkm_vma_tail(struct nvkm_vma *vma, u64 tail) +{ + struct nvkm_vma *new; + + BUG_ON(vma->size == tail); + + if (!(new = nvkm_vma_new(vma->addr + (vma->size - tail), tail))) + return NULL; + vma->size -= tail; + + new->mapref = vma->mapref; + new->sparse = vma->sparse; + new->page = vma->page; + new->refd = vma->refd; + new->used = vma->used; + new->part = vma->part; + new->user = vma->user; + new->busy = vma->busy; + list_add(&new->head, &vma->head); + return new; +} + +static void +nvkm_vmm_free_insert(struct nvkm_vmm *vmm, struct nvkm_vma *vma) +{ + struct rb_node **ptr = &vmm->free.rb_node; + struct rb_node *parent = NULL; + + while (*ptr) { + struct nvkm_vma *this = rb_entry(*ptr, typeof(*this), tree); + parent = *ptr; + if (vma->size < this->size) + ptr = &parent->rb_left; + else + if (vma->size > this->size) + ptr = &parent->rb_right; + else + if (vma->addr < this->addr) + ptr = &parent->rb_left; + else + if (vma->addr > this->addr) + ptr = &parent->rb_right; + else + BUG(); + } + + rb_link_node(&vma->tree, parent, ptr); + rb_insert_color(&vma->tree, &vmm->free); +} + +void +nvkm_vmm_node_insert(struct nvkm_vmm *vmm, struct nvkm_vma *vma) +{ + struct rb_node **ptr = &vmm->root.rb_node; + struct rb_node *parent = NULL; + + while (*ptr) { + struct nvkm_vma *this = rb_entry(*ptr, typeof(*this), tree); + parent = *ptr; + if (vma->addr < this->addr) + ptr = &parent->rb_left; + else + if (vma->addr > this->addr) + ptr = &parent->rb_right; + else + BUG(); + } + + rb_link_node(&vma->tree, parent, ptr); + rb_insert_color(&vma->tree, &vmm->root); +} + +struct nvkm_vma * +nvkm_vmm_node_search(struct nvkm_vmm *vmm, u64 addr) +{ + struct rb_node *node = vmm->root.rb_node; + while (node) { + struct nvkm_vma *vma = rb_entry(node, typeof(*vma), tree); + if (addr < vma->addr) + node = node->rb_left; + else + if (addr >= vma->addr + vma->size) + node = node->rb_right; + else + return vma; + } + return NULL; +} + +static void +nvkm_vmm_dtor(struct nvkm_vmm *vmm) +{ + struct nvkm_vma *vma; + struct rb_node *node; + + while ((node = rb_first(&vmm->root))) { + struct nvkm_vma *vma = rb_entry(node, typeof(*vma), tree); + nvkm_vmm_put(vmm, &vma); + } + + if (vmm->bootstrapped) { + const struct nvkm_vmm_page *page = vmm->func->page; + const u64 limit = vmm->limit - vmm->start; + + while (page[1].shift) + page++; + + nvkm_mmu_ptc_dump(vmm->mmu); + nvkm_vmm_ptes_put(vmm, page, vmm->start, limit); + } + + vma = list_first_entry(&vmm->list, typeof(*vma), head); + list_del(&vma->head); + kfree(vma); + WARN_ON(!list_empty(&vmm->list)); + + if (vmm->nullp) { + dma_free_coherent(vmm->mmu->subdev.device->dev, 16 * 1024, + vmm->nullp, vmm->null); + } + + if (vmm->pd) { + nvkm_mmu_ptc_put(vmm->mmu, true, &vmm->pd->pt[0]); + nvkm_vmm_pt_del(&vmm->pd); + } +} + +int +nvkm_vmm_ctor(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, + u32 pd_header, u64 addr, u64 size, struct lock_class_key *key, + const char *name, struct nvkm_vmm *vmm) +{ + static struct lock_class_key _key; + const struct nvkm_vmm_page *page = func->page; + const struct nvkm_vmm_desc *desc; + struct nvkm_vma *vma; + int levels, bits = 0; + + vmm->func = func; + vmm->mmu = mmu; + vmm->name = name; + vmm->debug = mmu->subdev.debug; + kref_init(&vmm->kref); + + __mutex_init(&vmm->mutex, "&vmm->mutex", key ? key : &_key); + + /* Locate the smallest page size supported by the backend, it will + * have the the deepest nesting of page tables. + */ + while (page[1].shift) + page++; + + /* Locate the structure that describes the layout of the top-level + * page table, and determine the number of valid bits in a virtual + * address. + */ + for (levels = 0, desc = page->desc; desc->bits; desc++, levels++) + bits += desc->bits; + bits += page->shift; + desc--; + + if (WARN_ON(levels > NVKM_VMM_LEVELS_MAX)) + return -EINVAL; + + vmm->start = addr; + vmm->limit = size ? (addr + size) : (1ULL << bits); + if (vmm->start > vmm->limit || vmm->limit > (1ULL << bits)) + return -EINVAL; + + /* Allocate top-level page table. */ + vmm->pd = nvkm_vmm_pt_new(desc, false, NULL); + if (!vmm->pd) + return -ENOMEM; + vmm->pd->refs[0] = 1; + INIT_LIST_HEAD(&vmm->join); + + /* ... and the GPU storage for it, except on Tesla-class GPUs that + * have the PD embedded in the instance structure. + */ + if (desc->size) { + const u32 size = pd_header + desc->size * (1 << desc->bits); + vmm->pd->pt[0] = nvkm_mmu_ptc_get(mmu, size, desc->align, true); + if (!vmm->pd->pt[0]) + return -ENOMEM; + } + + /* Initialise address-space MM. */ + INIT_LIST_HEAD(&vmm->list); + vmm->free = RB_ROOT; + vmm->root = RB_ROOT; + + if (!(vma = nvkm_vma_new(vmm->start, vmm->limit - vmm->start))) + return -ENOMEM; + + nvkm_vmm_free_insert(vmm, vma); + list_add(&vma->head, &vmm->list); + return 0; +} + +int +nvkm_vmm_new_(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, + u32 hdr, u64 addr, u64 size, struct lock_class_key *key, + const char *name, struct nvkm_vmm **pvmm) +{ + if (!(*pvmm = kzalloc(sizeof(**pvmm), GFP_KERNEL))) + return -ENOMEM; + return nvkm_vmm_ctor(func, mmu, hdr, addr, size, key, name, *pvmm); +} + +#define node(root, dir) ((root)->head.dir == &vmm->list) ? NULL : \ + list_entry((root)->head.dir, struct nvkm_vma, head) + +void +nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma) +{ + struct nvkm_vma *next; + + nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags); + nvkm_memory_unref(&vma->memory); + + if (vma->part) { + struct nvkm_vma *prev = node(vma, prev); + if (!prev->memory) { + prev->size += vma->size; + rb_erase(&vma->tree, &vmm->root); + list_del(&vma->head); + kfree(vma); + vma = prev; + } + } + + next = node(vma, next); + if (next && next->part) { + if (!next->memory) { + vma->size += next->size; + rb_erase(&next->tree, &vmm->root); + list_del(&next->head); + kfree(next); + } + } +} + +void +nvkm_vmm_unmap_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma) +{ + const struct nvkm_vmm_page *page = &vmm->func->page[vma->refd]; + + if (vma->mapref) { + nvkm_vmm_ptes_unmap_put(vmm, page, vma->addr, vma->size, vma->sparse); + vma->refd = NVKM_VMA_PAGE_NONE; + } else { + nvkm_vmm_ptes_unmap(vmm, page, vma->addr, vma->size, vma->sparse); + } + + nvkm_vmm_unmap_region(vmm, vma); +} + +void +nvkm_vmm_unmap(struct nvkm_vmm *vmm, struct nvkm_vma *vma) +{ + if (vma->memory) { + mutex_lock(&vmm->mutex); + nvkm_vmm_unmap_locked(vmm, vma); + mutex_unlock(&vmm->mutex); + } +} + +static int +nvkm_vmm_map_valid(struct nvkm_vmm *vmm, struct nvkm_vma *vma, + void *argv, u32 argc, struct nvkm_vmm_map *map) +{ + switch (nvkm_memory_target(map->memory)) { + case NVKM_MEM_TARGET_VRAM: + if (!(map->page->type & NVKM_VMM_PAGE_VRAM)) { + VMM_DEBUG(vmm, "%d !VRAM", map->page->shift); + return -EINVAL; + } + break; + case NVKM_MEM_TARGET_HOST: + case NVKM_MEM_TARGET_NCOH: + if (!(map->page->type & NVKM_VMM_PAGE_HOST)) { + VMM_DEBUG(vmm, "%d !HOST", map->page->shift); + return -EINVAL; + } + break; + default: + WARN_ON(1); + return -ENOSYS; + } + + if (!IS_ALIGNED( vma->addr, 1ULL << map->page->shift) || + !IS_ALIGNED((u64)vma->size, 1ULL << map->page->shift) || + !IS_ALIGNED( map->offset, 1ULL << map->page->shift) || + nvkm_memory_page(map->memory) < map->page->shift) { + VMM_DEBUG(vmm, "alignment %016llx %016llx %016llx %d %d", + vma->addr, (u64)vma->size, map->offset, map->page->shift, + nvkm_memory_page(map->memory)); + return -EINVAL; + } + + return vmm->func->valid(vmm, argv, argc, map); +} + +static int +nvkm_vmm_map_choose(struct nvkm_vmm *vmm, struct nvkm_vma *vma, + void *argv, u32 argc, struct nvkm_vmm_map *map) +{ + for (map->page = vmm->func->page; map->page->shift; map->page++) { + VMM_DEBUG(vmm, "trying %d", map->page->shift); + if (!nvkm_vmm_map_valid(vmm, vma, argv, argc, map)) + return 0; + } + return -EINVAL; +} + +static int +nvkm_vmm_map_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma, + void *argv, u32 argc, struct nvkm_vmm_map *map) +{ + nvkm_vmm_pte_func func; + int ret; + + /* Make sure we won't overrun the end of the memory object. */ + if (unlikely(nvkm_memory_size(map->memory) < map->offset + vma->size)) { + VMM_DEBUG(vmm, "overrun %016llx %016llx %016llx", + nvkm_memory_size(map->memory), + map->offset, (u64)vma->size); + return -EINVAL; + } + + /* Check remaining arguments for validity. */ + if (vma->page == NVKM_VMA_PAGE_NONE && + vma->refd == NVKM_VMA_PAGE_NONE) { + /* Find the largest page size we can perform the mapping at. */ + const u32 debug = vmm->debug; + vmm->debug = 0; + ret = nvkm_vmm_map_choose(vmm, vma, argv, argc, map); + vmm->debug = debug; + if (ret) { + VMM_DEBUG(vmm, "invalid at any page size"); + nvkm_vmm_map_choose(vmm, vma, argv, argc, map); + return -EINVAL; + } + } else { + /* Page size of the VMA is already pre-determined. */ + if (vma->refd != NVKM_VMA_PAGE_NONE) + map->page = &vmm->func->page[vma->refd]; + else + map->page = &vmm->func->page[vma->page]; + + ret = nvkm_vmm_map_valid(vmm, vma, argv, argc, map); + if (ret) { + VMM_DEBUG(vmm, "invalid %d\n", ret); + return ret; + } + } + + /* Deal with the 'offset' argument, and fetch the backend function. */ + map->off = map->offset; + if (map->mem) { + for (; map->off; map->mem = map->mem->next) { + u64 size = (u64)map->mem->length << NVKM_RAM_MM_SHIFT; + if (size > map->off) + break; + map->off -= size; + } + func = map->page->desc->func->mem; + } else + if (map->sgl) { + for (; map->off; map->sgl = sg_next(map->sgl)) { + u64 size = sg_dma_len(map->sgl); + if (size > map->off) + break; + map->off -= size; + } + func = map->page->desc->func->sgl; + } else { + map->dma += map->offset >> PAGE_SHIFT; + map->off = map->offset & PAGE_MASK; + func = map->page->desc->func->dma; + } + + /* Perform the map. */ + if (vma->refd == NVKM_VMA_PAGE_NONE) { + ret = nvkm_vmm_ptes_get_map(vmm, map->page, vma->addr, vma->size, map, func); + if (ret) + return ret; + + vma->refd = map->page - vmm->func->page; + } else { + nvkm_vmm_ptes_map(vmm, map->page, vma->addr, vma->size, map, func); + } + + nvkm_memory_tags_put(vma->memory, vmm->mmu->subdev.device, &vma->tags); + nvkm_memory_unref(&vma->memory); + vma->memory = nvkm_memory_ref(map->memory); + vma->tags = map->tags; + return 0; +} + +int +nvkm_vmm_map(struct nvkm_vmm *vmm, struct nvkm_vma *vma, void *argv, u32 argc, + struct nvkm_vmm_map *map) +{ + int ret; + mutex_lock(&vmm->mutex); + ret = nvkm_vmm_map_locked(vmm, vma, argv, argc, map); + vma->busy = false; + mutex_unlock(&vmm->mutex); + return ret; +} + +static void +nvkm_vmm_put_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma) +{ + struct nvkm_vma *prev, *next; + + if ((prev = node(vma, prev)) && !prev->used) { + rb_erase(&prev->tree, &vmm->free); + list_del(&prev->head); + vma->addr = prev->addr; + vma->size += prev->size; + kfree(prev); + } + + if ((next = node(vma, next)) && !next->used) { + rb_erase(&next->tree, &vmm->free); + list_del(&next->head); + vma->size += next->size; + kfree(next); + } + + nvkm_vmm_free_insert(vmm, vma); +} + +void +nvkm_vmm_put_locked(struct nvkm_vmm *vmm, struct nvkm_vma *vma) +{ + const struct nvkm_vmm_page *page = vmm->func->page; + struct nvkm_vma *next = vma; + + BUG_ON(vma->part); + + if (vma->mapref || !vma->sparse) { + do { + const bool map = next->memory != NULL; + const u8 refd = next->refd; + const u64 addr = next->addr; + u64 size = next->size; + + /* Merge regions that are in the same state. */ + while ((next = node(next, next)) && next->part && + (next->memory != NULL) == map && + (next->refd == refd)) + size += next->size; + + if (map) { + /* Region(s) are mapped, merge the unmap + * and dereference into a single walk of + * the page tree. + */ + nvkm_vmm_ptes_unmap_put(vmm, &page[refd], addr, + size, vma->sparse); + } else + if (refd != NVKM_VMA_PAGE_NONE) { + /* Drop allocation-time PTE references. */ + nvkm_vmm_ptes_put(vmm, &page[refd], addr, size); + } + } while (next && next->part); + } + + /* Merge any mapped regions that were split from the initial + * address-space allocation back into the allocated VMA, and + * release memory/compression resources. + */ + next = vma; + do { + if (next->memory) + nvkm_vmm_unmap_region(vmm, next); + } while ((next = node(vma, next)) && next->part); + + if (vma->sparse && !vma->mapref) { + /* Sparse region that was allocated with a fixed page size, + * meaning all relevant PTEs were referenced once when the + * region was allocated, and remained that way, regardless + * of whether memory was mapped into it afterwards. + * + * The process of unmapping, unsparsing, and dereferencing + * PTEs can be done in a single page tree walk. + */ + nvkm_vmm_ptes_sparse_put(vmm, &page[vma->refd], vma->addr, vma->size); + } else + if (vma->sparse) { + /* Sparse region that wasn't allocated with a fixed page size, + * PTE references were taken both at allocation time (to make + * the GPU see the region as sparse), and when mapping memory + * into the region. + * + * The latter was handled above, and the remaining references + * are dealt with here. + */ + nvkm_vmm_ptes_sparse(vmm, vma->addr, vma->size, false); + } + + /* Remove VMA from the list of allocated nodes. */ + rb_erase(&vma->tree, &vmm->root); + + /* Merge VMA back into the free list. */ + vma->page = NVKM_VMA_PAGE_NONE; + vma->refd = NVKM_VMA_PAGE_NONE; + vma->used = false; + vma->user = false; + nvkm_vmm_put_region(vmm, vma); +} + +void +nvkm_vmm_put(struct nvkm_vmm *vmm, struct nvkm_vma **pvma) +{ + struct nvkm_vma *vma = *pvma; + if (vma) { + mutex_lock(&vmm->mutex); + nvkm_vmm_put_locked(vmm, vma); + mutex_unlock(&vmm->mutex); + *pvma = NULL; + } +} + +int +nvkm_vmm_get_locked(struct nvkm_vmm *vmm, bool getref, bool mapref, bool sparse, + u8 shift, u8 align, u64 size, struct nvkm_vma **pvma) +{ + const struct nvkm_vmm_page *page = &vmm->func->page[NVKM_VMA_PAGE_NONE]; + struct rb_node *node = NULL, *temp; + struct nvkm_vma *vma = NULL, *tmp; + u64 addr, tail; + int ret; + + VMM_TRACE(vmm, "getref %d mapref %d sparse %d " + "shift: %d align: %d size: %016llx", + getref, mapref, sparse, shift, align, size); + + /* Zero-sized, or lazily-allocated sparse VMAs, make no sense. */ + if (unlikely(!size || (!getref && !mapref && sparse))) { + VMM_DEBUG(vmm, "args %016llx %d %d %d", + size, getref, mapref, sparse); + return -EINVAL; + } + + /* Tesla-class GPUs can only select page size per-PDE, which means + * we're required to know the mapping granularity up-front to find + * a suitable region of address-space. + * + * The same goes if we're requesting up-front allocation of PTES. + */ + if (unlikely((getref || vmm->func->page_block) && !shift)) { + VMM_DEBUG(vmm, "page size required: %d %016llx", + getref, vmm->func->page_block); + return -EINVAL; + } + + /* If a specific page size was requested, determine its index and + * make sure the requested size is a multiple of the page size. + */ + if (shift) { + for (page = vmm->func->page; page->shift; page++) { + if (shift == page->shift) + break; + } + + if (!page->shift || !IS_ALIGNED(size, 1ULL << page->shift)) { + VMM_DEBUG(vmm, "page %d %016llx", shift, size); + return -EINVAL; + } + align = max_t(u8, align, shift); + } else { + align = max_t(u8, align, 12); + } + + /* Locate smallest block that can possibly satisfy the allocation. */ + temp = vmm->free.rb_node; + while (temp) { + struct nvkm_vma *this = rb_entry(temp, typeof(*this), tree); + if (this->size < size) { + temp = temp->rb_right; + } else { + node = temp; + temp = temp->rb_left; + } + } + + if (unlikely(!node)) + return -ENOSPC; + + /* Take into account alignment restrictions, trying larger blocks + * in turn until we find a suitable free block. + */ + do { + struct nvkm_vma *this = rb_entry(node, typeof(*this), tree); + struct nvkm_vma *prev = node(this, prev); + struct nvkm_vma *next = node(this, next); + const int p = page - vmm->func->page; + + addr = this->addr; + if (vmm->func->page_block && prev && prev->page != p) + addr = ALIGN(addr, vmm->func->page_block); + addr = ALIGN(addr, 1ULL << align); + + tail = this->addr + this->size; + if (vmm->func->page_block && next && next->page != p) + tail = ALIGN_DOWN(addr, vmm->func->page_block); + + if (addr <= tail && tail - addr >= size) { + rb_erase(&this->tree, &vmm->free); + vma = this; + break; + } + } while ((node = rb_next(node))); + + if (unlikely(!vma)) + return -ENOSPC; + + /* If the VMA we found isn't already exactly the requested size, + * it needs to be split, and the remaining free blocks returned. + */ + if (addr != vma->addr) { + if (!(tmp = nvkm_vma_tail(vma, vma->size + vma->addr - addr))) { + nvkm_vmm_put_region(vmm, vma); + return -ENOMEM; + } + nvkm_vmm_free_insert(vmm, vma); + vma = tmp; + } + + if (size != vma->size) { + if (!(tmp = nvkm_vma_tail(vma, vma->size - size))) { + nvkm_vmm_put_region(vmm, vma); + return -ENOMEM; + } + nvkm_vmm_free_insert(vmm, tmp); + } + + /* Pre-allocate page tables and/or setup sparse mappings. */ + if (sparse && getref) + ret = nvkm_vmm_ptes_sparse_get(vmm, page, vma->addr, vma->size); + else if (sparse) + ret = nvkm_vmm_ptes_sparse(vmm, vma->addr, vma->size, true); + else if (getref) + ret = nvkm_vmm_ptes_get(vmm, page, vma->addr, vma->size); + else + ret = 0; + if (ret) { + nvkm_vmm_put_region(vmm, vma); + return ret; + } + + vma->mapref = mapref && !getref; + vma->sparse = sparse; + vma->page = page - vmm->func->page; + vma->refd = getref ? vma->page : NVKM_VMA_PAGE_NONE; + vma->used = true; + nvkm_vmm_node_insert(vmm, vma); + *pvma = vma; + return 0; +} + +int +nvkm_vmm_get(struct nvkm_vmm *vmm, u8 page, u64 size, struct nvkm_vma **pvma) +{ + int ret; + mutex_lock(&vmm->mutex); + ret = nvkm_vmm_get_locked(vmm, false, true, false, page, 0, size, pvma); + mutex_unlock(&vmm->mutex); + return ret; +} + +void +nvkm_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + if (vmm->func->part && inst) { + mutex_lock(&vmm->mutex); + vmm->func->part(vmm, inst); + mutex_unlock(&vmm->mutex); + } +} + +int +nvkm_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + int ret = 0; + if (vmm->func->join) { + mutex_lock(&vmm->mutex); + ret = vmm->func->join(vmm, inst); + mutex_unlock(&vmm->mutex); + } + return ret; +} + +static bool +nvkm_vmm_boot_ptes(struct nvkm_vmm_iter *it, u32 ptei, u32 ptes) +{ + const struct nvkm_vmm_desc *desc = it->desc; + const int type = desc->type == SPT; + nvkm_memory_boot(it->pt[0]->pt[type]->memory, it->vmm); + return false; +} + +int +nvkm_vmm_boot(struct nvkm_vmm *vmm) +{ + const struct nvkm_vmm_page *page = vmm->func->page; + const u64 limit = vmm->limit - vmm->start; + int ret; + + while (page[1].shift) + page++; + + ret = nvkm_vmm_ptes_get(vmm, page, vmm->start, limit); + if (ret) + return ret; + + nvkm_vmm_iter(vmm, page, vmm->start, limit, "bootstrap", false, + nvkm_vmm_boot_ptes, NULL, NULL, NULL); + vmm->bootstrapped = true; + return 0; +} + +static void +nvkm_vmm_del(struct kref *kref) +{ + struct nvkm_vmm *vmm = container_of(kref, typeof(*vmm), kref); + nvkm_vmm_dtor(vmm); + kfree(vmm); +} + +void +nvkm_vmm_unref(struct nvkm_vmm **pvmm) +{ + struct nvkm_vmm *vmm = *pvmm; + if (vmm) { + kref_put(&vmm->kref, nvkm_vmm_del); + *pvmm = NULL; + } +} + +struct nvkm_vmm * +nvkm_vmm_ref(struct nvkm_vmm *vmm) +{ + if (vmm) + kref_get(&vmm->kref); + return vmm; +} + +int +nvkm_vmm_new(struct nvkm_device *device, u64 addr, u64 size, void *argv, + u32 argc, struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + struct nvkm_mmu *mmu = device->mmu; + struct nvkm_vmm *vmm = NULL; + int ret; + ret = mmu->func->vmm.ctor(mmu, addr, size, argv, argc, key, name, &vmm); + if (ret) + nvkm_vmm_unref(&vmm); + *pvmm = vmm; + return ret; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h new file mode 100644 index 000000000000..6d8f61ea467a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h @@ -0,0 +1,310 @@ +#ifndef __NVKM_VMM_H__ +#define __NVKM_VMM_H__ +#include "priv.h" +#include <core/memory.h> +enum nvkm_memory_target; + +struct nvkm_vmm_pt { + /* Some GPUs have a mapping level with a dual page tables to + * support large and small pages in the same address-range. + * + * We track the state of both page tables in one place, which + * is why there's multiple PT pointers/refcounts here. + */ + struct nvkm_mmu_pt *pt[2]; + u32 refs[2]; + + /* Page size handled by this PT. + * + * Tesla backend needs to know this when writinge PDEs, + * otherwise unnecessary. + */ + u8 page; + + /* Entire page table sparse. + * + * Used to propagate sparseness to child page tables. + */ + bool sparse:1; + + /* Tracking for page directories. + * + * The array is indexed by PDE, and will either point to the + * child page table, or indicate the PDE is marked as sparse. + **/ +#define NVKM_VMM_PDE_INVALID(pde) IS_ERR_OR_NULL(pde) +#define NVKM_VMM_PDE_SPARSED(pde) IS_ERR(pde) +#define NVKM_VMM_PDE_SPARSE ERR_PTR(-EBUSY) + struct nvkm_vmm_pt **pde; + + /* Tracking for dual page tables. + * + * There's one entry for each LPTE, keeping track of whether + * there are valid SPTEs in the same address-range. + * + * This information is used to manage LPTE state transitions. + */ +#define NVKM_VMM_PTE_SPARSE 0x80 +#define NVKM_VMM_PTE_VALID 0x40 +#define NVKM_VMM_PTE_SPTES 0x3f + u8 pte[]; +}; + +typedef void (*nvkm_vmm_pxe_func)(struct nvkm_vmm *, + struct nvkm_mmu_pt *, u32 ptei, u32 ptes); +typedef void (*nvkm_vmm_pde_func)(struct nvkm_vmm *, + struct nvkm_vmm_pt *, u32 pdei); +typedef void (*nvkm_vmm_pte_func)(struct nvkm_vmm *, struct nvkm_mmu_pt *, + u32 ptei, u32 ptes, struct nvkm_vmm_map *); + +struct nvkm_vmm_desc_func { + nvkm_vmm_pxe_func invalid; + nvkm_vmm_pxe_func unmap; + nvkm_vmm_pxe_func sparse; + + nvkm_vmm_pde_func pde; + + nvkm_vmm_pte_func mem; + nvkm_vmm_pte_func dma; + nvkm_vmm_pte_func sgl; +}; + +extern const struct nvkm_vmm_desc_func gf100_vmm_pgd; +void gf100_vmm_pgd_pde(struct nvkm_vmm *, struct nvkm_vmm_pt *, u32); +extern const struct nvkm_vmm_desc_func gf100_vmm_pgt; +void gf100_vmm_pgt_unmap(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32); +void gf100_vmm_pgt_mem(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32, + struct nvkm_vmm_map *); +void gf100_vmm_pgt_dma(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32, + struct nvkm_vmm_map *); +void gf100_vmm_pgt_sgl(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32, + struct nvkm_vmm_map *); + +void gk104_vmm_lpt_invalid(struct nvkm_vmm *, struct nvkm_mmu_pt *, u32, u32); + +struct nvkm_vmm_desc { + enum { + PGD, + PGT, + SPT, + LPT, + } type; + u8 bits; /* VMA bits covered by PT. */ + u8 size; /* Bytes-per-PTE. */ + u32 align; /* PT address alignment. */ + const struct nvkm_vmm_desc_func *func; +}; + +extern const struct nvkm_vmm_desc gk104_vmm_desc_16_12[]; +extern const struct nvkm_vmm_desc gk104_vmm_desc_16_16[]; +extern const struct nvkm_vmm_desc gk104_vmm_desc_17_12[]; +extern const struct nvkm_vmm_desc gk104_vmm_desc_17_17[]; + +extern const struct nvkm_vmm_desc gm200_vmm_desc_16_12[]; +extern const struct nvkm_vmm_desc gm200_vmm_desc_16_16[]; +extern const struct nvkm_vmm_desc gm200_vmm_desc_17_12[]; +extern const struct nvkm_vmm_desc gm200_vmm_desc_17_17[]; + +extern const struct nvkm_vmm_desc gp100_vmm_desc_12[]; +extern const struct nvkm_vmm_desc gp100_vmm_desc_16[]; + +struct nvkm_vmm_page { + u8 shift; + const struct nvkm_vmm_desc *desc; +#define NVKM_VMM_PAGE_SPARSE 0x01 +#define NVKM_VMM_PAGE_VRAM 0x02 +#define NVKM_VMM_PAGE_HOST 0x04 +#define NVKM_VMM_PAGE_COMP 0x08 +#define NVKM_VMM_PAGE_Sxxx (NVKM_VMM_PAGE_SPARSE) +#define NVKM_VMM_PAGE_xVxx (NVKM_VMM_PAGE_VRAM) +#define NVKM_VMM_PAGE_SVxx (NVKM_VMM_PAGE_Sxxx | NVKM_VMM_PAGE_VRAM) +#define NVKM_VMM_PAGE_xxHx (NVKM_VMM_PAGE_HOST) +#define NVKM_VMM_PAGE_SxHx (NVKM_VMM_PAGE_Sxxx | NVKM_VMM_PAGE_HOST) +#define NVKM_VMM_PAGE_xVHx (NVKM_VMM_PAGE_xVxx | NVKM_VMM_PAGE_HOST) +#define NVKM_VMM_PAGE_SVHx (NVKM_VMM_PAGE_SVxx | NVKM_VMM_PAGE_HOST) +#define NVKM_VMM_PAGE_xVxC (NVKM_VMM_PAGE_xVxx | NVKM_VMM_PAGE_COMP) +#define NVKM_VMM_PAGE_SVxC (NVKM_VMM_PAGE_SVxx | NVKM_VMM_PAGE_COMP) +#define NVKM_VMM_PAGE_xxHC (NVKM_VMM_PAGE_xxHx | NVKM_VMM_PAGE_COMP) +#define NVKM_VMM_PAGE_SxHC (NVKM_VMM_PAGE_SxHx | NVKM_VMM_PAGE_COMP) + u8 type; +}; + +struct nvkm_vmm_func { + int (*join)(struct nvkm_vmm *, struct nvkm_memory *inst); + void (*part)(struct nvkm_vmm *, struct nvkm_memory *inst); + + int (*aper)(enum nvkm_memory_target); + int (*valid)(struct nvkm_vmm *, void *argv, u32 argc, + struct nvkm_vmm_map *); + void (*flush)(struct nvkm_vmm *, int depth); + + u64 page_block; + const struct nvkm_vmm_page page[]; +}; + +struct nvkm_vmm_join { + struct nvkm_memory *inst; + struct list_head head; +}; + +int nvkm_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, + u32 pd_header, u64 addr, u64 size, struct lock_class_key *, + const char *name, struct nvkm_vmm **); +int nvkm_vmm_ctor(const struct nvkm_vmm_func *, struct nvkm_mmu *, + u32 pd_header, u64 addr, u64 size, struct lock_class_key *, + const char *name, struct nvkm_vmm *); +struct nvkm_vma *nvkm_vmm_node_search(struct nvkm_vmm *, u64 addr); +int nvkm_vmm_get_locked(struct nvkm_vmm *, bool getref, bool mapref, + bool sparse, u8 page, u8 align, u64 size, + struct nvkm_vma **pvma); +void nvkm_vmm_put_locked(struct nvkm_vmm *, struct nvkm_vma *); +void nvkm_vmm_unmap_locked(struct nvkm_vmm *, struct nvkm_vma *); +void nvkm_vmm_unmap_region(struct nvkm_vmm *vmm, struct nvkm_vma *vma); + +struct nvkm_vma *nvkm_vma_tail(struct nvkm_vma *, u64 tail); +void nvkm_vmm_node_insert(struct nvkm_vmm *, struct nvkm_vma *); + +int nv04_vmm_new_(const struct nvkm_vmm_func *, struct nvkm_mmu *, u32, + u64, u64, void *, u32, struct lock_class_key *, + const char *, struct nvkm_vmm **); +int nv04_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); + +int gf100_vmm_new_(const struct nvkm_vmm_func *, const struct nvkm_vmm_func *, + struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int gf100_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base); +int gf100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); +void gf100_vmm_part(struct nvkm_vmm *, struct nvkm_memory *); +int gf100_vmm_aper(enum nvkm_memory_target); +int gf100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); +void gf100_vmm_flush_(struct nvkm_vmm *, int); +void gf100_vmm_flush(struct nvkm_vmm *, int); + +int gk20a_vmm_aper(enum nvkm_memory_target); + +int gm200_vmm_new_(const struct nvkm_vmm_func *, const struct nvkm_vmm_func *, + struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int gm200_vmm_join_(struct nvkm_vmm *, struct nvkm_memory *, u64 base); +int gm200_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); + +int gp100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *); +int gp100_vmm_valid(struct nvkm_vmm *, void *, u32, struct nvkm_vmm_map *); +void gp100_vmm_flush(struct nvkm_vmm *, int); + +int nv04_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int nv41_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int nv44_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int nv50_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int g84_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int gf100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int gk104_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int gk20a_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, struct nvkm_vmm **); +int gm200_vmm_new_fixed(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, + struct nvkm_vmm **); +int gm200_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, + struct nvkm_vmm **); +int gm20b_vmm_new_fixed(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, + struct nvkm_vmm **); +int gm20b_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, + struct nvkm_vmm **); +int gp100_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, + struct nvkm_vmm **); +int gp10b_vmm_new(struct nvkm_mmu *, u64, u64, void *, u32, + struct lock_class_key *, const char *, + struct nvkm_vmm **); + +#define VMM_PRINT(l,v,p,f,a...) do { \ + struct nvkm_vmm *_vmm = (v); \ + if (CONFIG_NOUVEAU_DEBUG >= (l) && _vmm->debug >= (l)) { \ + nvkm_printk_(&_vmm->mmu->subdev, 0, p, "%s: "f"\n", \ + _vmm->name, ##a); \ + } \ +} while(0) +#define VMM_DEBUG(v,f,a...) VMM_PRINT(NV_DBG_DEBUG, (v), info, f, ##a) +#define VMM_TRACE(v,f,a...) VMM_PRINT(NV_DBG_TRACE, (v), info, f, ##a) +#define VMM_SPAM(v,f,a...) VMM_PRINT(NV_DBG_SPAM , (v), dbg, f, ##a) + +#define VMM_MAP_ITER(VMM,PT,PTEI,PTEN,MAP,FILL,BASE,SIZE,NEXT) do { \ + nvkm_kmap((PT)->memory); \ + while (PTEN) { \ + u64 _ptes = ((SIZE) - MAP->off) >> MAP->page->shift; \ + u64 _addr = ((BASE) + MAP->off); \ + \ + if (_ptes > PTEN) { \ + MAP->off += PTEN << MAP->page->shift; \ + _ptes = PTEN; \ + } else { \ + MAP->off = 0; \ + NEXT; \ + } \ + \ + VMM_SPAM(VMM, "ITER %08x %08x PTE(s)", PTEI, (u32)_ptes); \ + \ + FILL(VMM, PT, PTEI, _ptes, MAP, _addr); \ + PTEI += _ptes; \ + PTEN -= _ptes; \ + }; \ + nvkm_done((PT)->memory); \ +} while(0) + +#define VMM_MAP_ITER_MEM(VMM,PT,PTEI,PTEN,MAP,FILL) \ + VMM_MAP_ITER(VMM,PT,PTEI,PTEN,MAP,FILL, \ + ((u64)MAP->mem->offset << NVKM_RAM_MM_SHIFT), \ + ((u64)MAP->mem->length << NVKM_RAM_MM_SHIFT), \ + (MAP->mem = MAP->mem->next)) +#define VMM_MAP_ITER_DMA(VMM,PT,PTEI,PTEN,MAP,FILL) \ + VMM_MAP_ITER(VMM,PT,PTEI,PTEN,MAP,FILL, \ + *MAP->dma, PAGE_SIZE, MAP->dma++) +#define VMM_MAP_ITER_SGL(VMM,PT,PTEI,PTEN,MAP,FILL) \ + VMM_MAP_ITER(VMM,PT,PTEI,PTEN,MAP,FILL, \ + sg_dma_address(MAP->sgl), sg_dma_len(MAP->sgl), \ + (MAP->sgl = sg_next(MAP->sgl))) + +#define VMM_FO(m,o,d,c,b) nvkm_fo##b((m)->memory, (o), (d), (c)) +#define VMM_WO(m,o,d,c,b) nvkm_wo##b((m)->memory, (o), (d)) +#define VMM_XO(m,v,o,d,c,b,fn,f,a...) do { \ + const u32 _pteo = (o); u##b _data = (d); \ + VMM_SPAM((v), " %010llx "f, (m)->addr + _pteo, _data, ##a); \ + VMM_##fn((m), (m)->base + _pteo, _data, (c), b); \ +} while(0) + +#define VMM_WO032(m,v,o,d) VMM_XO((m),(v),(o),(d), 1, 32, WO, "%08x") +#define VMM_FO032(m,v,o,d,c) \ + VMM_XO((m),(v),(o),(d),(c), 32, FO, "%08x %08x", (c)) + +#define VMM_WO064(m,v,o,d) VMM_XO((m),(v),(o),(d), 1, 64, WO, "%016llx") +#define VMM_FO064(m,v,o,d,c) \ + VMM_XO((m),(v),(o),(d),(c), 64, FO, "%016llx %08x", (c)) + +#define VMM_XO128(m,v,o,lo,hi,c,f,a...) do { \ + u32 _pteo = (o), _ptes = (c); \ + const u64 _addr = (m)->addr + _pteo; \ + VMM_SPAM((v), " %010llx %016llx%016llx"f, _addr, (hi), (lo), ##a); \ + while (_ptes--) { \ + nvkm_wo64((m)->memory, (m)->base + _pteo + 0, (lo)); \ + nvkm_wo64((m)->memory, (m)->base + _pteo + 8, (hi)); \ + _pteo += 0x10; \ + } \ +} while(0) + +#define VMM_WO128(m,v,o,lo,hi) VMM_XO128((m),(v),(o),(lo),(hi), 1, "") +#define VMM_FO128(m,v,o,lo,hi,c) do { \ + nvkm_kmap((m)->memory); \ + VMM_XO128((m),(v),(o),(lo),(hi),(c), " %08x", (c)); \ + nvkm_done((m)->memory); \ +} while(0) +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c new file mode 100644 index 000000000000..faf5a7e9265e --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgf100.c @@ -0,0 +1,403 @@ +/* + * 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 "vmm.h" + +#include <subdev/fb.h> +#include <subdev/ltc.h> +#include <subdev/timer.h> + +#include <nvif/if900d.h> +#include <nvif/unpack.h> + +static inline void +gf100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) +{ + u64 base = (addr >> 8) | map->type; + u64 data = base; + + if (map->ctag && !(map->next & (1ULL << 44))) { + while (ptes--) { + data = base | ((map->ctag >> 1) << 44); + if (!(map->ctag++ & 1)) + data |= BIT_ULL(60); + + VMM_WO064(pt, vmm, ptei++ * 8, data); + base += map->next; + } + } else { + map->type += ptes * map->ctag; + + while (ptes--) { + VMM_WO064(pt, vmm, ptei++ * 8, data); + data += map->next; + } + } +} + +void +gf100_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, gf100_vmm_pgt_pte); +} + +void +gf100_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + if (map->page->shift == PAGE_SHIFT) { + VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes); + nvkm_kmap(pt->memory); + while (ptes--) { + const u64 data = (*map->dma++ >> 8) | map->type; + VMM_WO064(pt, vmm, ptei++ * 8, data); + map->type += map->ctag; + } + nvkm_done(pt->memory); + return; + } + + VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, gf100_vmm_pgt_pte); +} + +void +gf100_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gf100_vmm_pgt_pte); +} + +void +gf100_vmm_pgt_unmap(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + VMM_FO064(pt, vmm, ptei * 8, 0ULL, ptes); +} + +const struct nvkm_vmm_desc_func +gf100_vmm_pgt = { + .unmap = gf100_vmm_pgt_unmap, + .mem = gf100_vmm_pgt_mem, + .dma = gf100_vmm_pgt_dma, + .sgl = gf100_vmm_pgt_sgl, +}; + +void +gf100_vmm_pgd_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei) +{ + struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; + struct nvkm_mmu_pt *pd = pgd->pt[0]; + struct nvkm_mmu_pt *pt; + u64 data = 0; + + if ((pt = pgt->pt[0])) { + switch (nvkm_memory_target(pt->memory)) { + case NVKM_MEM_TARGET_VRAM: data |= 1ULL << 0; break; + case NVKM_MEM_TARGET_HOST: data |= 2ULL << 0; + data |= BIT_ULL(35); /* VOL */ + break; + case NVKM_MEM_TARGET_NCOH: data |= 3ULL << 0; break; + default: + WARN_ON(1); + return; + } + data |= pt->addr >> 8; + } + + if ((pt = pgt->pt[1])) { + switch (nvkm_memory_target(pt->memory)) { + case NVKM_MEM_TARGET_VRAM: data |= 1ULL << 32; break; + case NVKM_MEM_TARGET_HOST: data |= 2ULL << 32; + data |= BIT_ULL(34); /* VOL */ + break; + case NVKM_MEM_TARGET_NCOH: data |= 3ULL << 32; break; + default: + WARN_ON(1); + return; + } + data |= pt->addr << 24; + } + + nvkm_kmap(pd->memory); + VMM_WO064(pd, vmm, pdei * 8, data); + nvkm_done(pd->memory); +} + +const struct nvkm_vmm_desc_func +gf100_vmm_pgd = { + .unmap = gf100_vmm_pgt_unmap, + .pde = gf100_vmm_pgd_pde, +}; + +static const struct nvkm_vmm_desc +gf100_vmm_desc_17_12[] = { + { SPT, 15, 8, 0x1000, &gf100_vmm_pgt }, + { PGD, 13, 8, 0x1000, &gf100_vmm_pgd }, + {} +}; + +static const struct nvkm_vmm_desc +gf100_vmm_desc_17_17[] = { + { LPT, 10, 8, 0x1000, &gf100_vmm_pgt }, + { PGD, 13, 8, 0x1000, &gf100_vmm_pgd }, + {} +}; + +static const struct nvkm_vmm_desc +gf100_vmm_desc_16_12[] = { + { SPT, 14, 8, 0x1000, &gf100_vmm_pgt }, + { PGD, 14, 8, 0x1000, &gf100_vmm_pgd }, + {} +}; + +static const struct nvkm_vmm_desc +gf100_vmm_desc_16_16[] = { + { LPT, 10, 8, 0x1000, &gf100_vmm_pgt }, + { PGD, 14, 8, 0x1000, &gf100_vmm_pgd }, + {} +}; + +void +gf100_vmm_flush_(struct nvkm_vmm *vmm, int depth) +{ + struct nvkm_subdev *subdev = &vmm->mmu->subdev; + struct nvkm_device *device = subdev->device; + u32 type = depth << 24; + + type = 0x00000001; /* PAGE_ALL */ + if (atomic_read(&vmm->engref[NVKM_SUBDEV_BAR])) + type |= 0x00000004; /* HUB_ONLY */ + + mutex_lock(&subdev->mutex); + /* Looks like maybe a "free flush slots" counter, the + * faster you write to 0x100cbc to more it decreases. + */ + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100c80) & 0x00ff0000) + break; + ); + + nvkm_wr32(device, 0x100cb8, vmm->pd->pt[0]->addr >> 8); + nvkm_wr32(device, 0x100cbc, 0x80000000 | type); + + /* Wait for flush to be queued? */ + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100c80) & 0x00008000) + break; + ); + mutex_unlock(&subdev->mutex); +} + +void +gf100_vmm_flush(struct nvkm_vmm *vmm, int depth) +{ + gf100_vmm_flush_(vmm, 0); +} + +int +gf100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, + struct nvkm_vmm_map *map) +{ + const enum nvkm_memory_target target = nvkm_memory_target(map->memory); + const struct nvkm_vmm_page *page = map->page; + const bool gm20x = page->desc->func->sparse != NULL; + union { + struct gf100_vmm_map_vn vn; + struct gf100_vmm_map_v0 v0; + } *args = argv; + struct nvkm_device *device = vmm->mmu->subdev.device; + struct nvkm_memory *memory = map->memory; + u8 kind, priv, ro, vol; + int kindn, aper, ret = -ENOSYS; + const u8 *kindm; + + map->next = (1 << page->shift) >> 8; + map->type = map->ctag = 0; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + vol = !!args->v0.vol; + ro = !!args->v0.ro; + priv = !!args->v0.priv; + kind = args->v0.kind; + } else + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + vol = target == NVKM_MEM_TARGET_HOST; + ro = 0; + priv = 0; + kind = 0x00; + } else { + VMM_DEBUG(vmm, "args"); + return ret; + } + + aper = vmm->func->aper(target); + if (WARN_ON(aper < 0)) + return aper; + + kindm = vmm->mmu->func->kind(vmm->mmu, &kindn); + if (kind >= kindn || kindm[kind] == 0xff) { + VMM_DEBUG(vmm, "kind %02x", kind); + return -EINVAL; + } + + if (kindm[kind] != kind) { + u32 comp = (page->shift == 16 && !gm20x) ? 16 : 17; + u32 tags = ALIGN(nvkm_memory_size(memory), 1 << 17) >> comp; + if (aper != 0 || !(page->type & NVKM_VMM_PAGE_COMP)) { + VMM_DEBUG(vmm, "comp %d %02x", aper, page->type); + return -EINVAL; + } + + ret = nvkm_memory_tags_get(memory, device, tags, + nvkm_ltc_tags_clear, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } + + if (map->tags->mn) { + u64 tags = map->tags->mn->offset + (map->offset >> 17); + if (page->shift == 17 || !gm20x) { + map->type |= tags << 44; + map->ctag |= 1ULL << 44; + map->next |= 1ULL << 44; + } else { + map->ctag |= tags << 1 | 1; + } + } else { + kind = kindm[kind]; + } + } + + map->type |= BIT(0); + map->type |= (u64)priv << 1; + map->type |= (u64) ro << 2; + map->type |= (u64) vol << 32; + map->type |= (u64)aper << 33; + map->type |= (u64)kind << 36; + return 0; +} + +int +gf100_vmm_aper(enum nvkm_memory_target target) +{ + switch (target) { + case NVKM_MEM_TARGET_VRAM: return 0; + case NVKM_MEM_TARGET_HOST: return 2; + case NVKM_MEM_TARGET_NCOH: return 3; + default: + return -EINVAL; + } +} + +void +gf100_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + nvkm_fo64(inst, 0x0200, 0x00000000, 2); +} + +int +gf100_vmm_join_(struct nvkm_vmm *vmm, struct nvkm_memory *inst, u64 base) +{ + struct nvkm_mmu_pt *pd = vmm->pd->pt[0]; + + switch (nvkm_memory_target(pd->memory)) { + case NVKM_MEM_TARGET_VRAM: base |= 0ULL << 0; break; + case NVKM_MEM_TARGET_HOST: base |= 2ULL << 0; + base |= BIT_ULL(2) /* VOL. */; + break; + case NVKM_MEM_TARGET_NCOH: base |= 3ULL << 0; break; + default: + WARN_ON(1); + return -EINVAL; + } + base |= pd->addr; + + nvkm_kmap(inst); + nvkm_wo64(inst, 0x0200, base); + nvkm_wo64(inst, 0x0208, vmm->limit - 1); + nvkm_done(inst); + return 0; +} + +int +gf100_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + return gf100_vmm_join_(vmm, inst, 0); +} + +static const struct nvkm_vmm_func +gf100_vmm_17 = { + .join = gf100_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 17, &gf100_vmm_desc_17_17[0], NVKM_VMM_PAGE_xVxC }, + { 12, &gf100_vmm_desc_17_12[0], NVKM_VMM_PAGE_xVHx }, + {} + } +}; + +static const struct nvkm_vmm_func +gf100_vmm_16 = { + .join = gf100_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 16, &gf100_vmm_desc_16_16[0], NVKM_VMM_PAGE_xVxC }, + { 12, &gf100_vmm_desc_16_12[0], NVKM_VMM_PAGE_xVHx }, + {} + } +}; + +int +gf100_vmm_new_(const struct nvkm_vmm_func *func_16, + const struct nvkm_vmm_func *func_17, + struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + switch (mmu->subdev.device->fb->page) { + case 16: return nv04_vmm_new_(func_16, mmu, 0, addr, size, + argv, argc, key, name, pvmm); + case 17: return nv04_vmm_new_(func_17, mmu, 0, addr, size, + argv, argc, key, name, pvmm); + default: + WARN_ON(1); + return -EINVAL; + } +} + +int +gf100_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return gf100_vmm_new_(&gf100_vmm_16, &gf100_vmm_17, mmu, addr, + size, argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk104.c new file mode 100644 index 000000000000..0ebb7bccfcd2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk104.c @@ -0,0 +1,102 @@ +/* + * 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 "vmm.h" + +void +gk104_vmm_lpt_invalid(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + /* VALID_FALSE + PRIV tells the MMU to ignore corresponding SPTEs. */ + VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(1) /* PRIV. */, ptes); +} + +static const struct nvkm_vmm_desc_func +gk104_vmm_lpt = { + .invalid = gk104_vmm_lpt_invalid, + .unmap = gf100_vmm_pgt_unmap, + .mem = gf100_vmm_pgt_mem, +}; + +const struct nvkm_vmm_desc +gk104_vmm_desc_17_12[] = { + { SPT, 15, 8, 0x1000, &gf100_vmm_pgt }, + { PGD, 13, 8, 0x1000, &gf100_vmm_pgd }, + {} +}; + +const struct nvkm_vmm_desc +gk104_vmm_desc_17_17[] = { + { LPT, 10, 8, 0x1000, &gk104_vmm_lpt }, + { PGD, 13, 8, 0x1000, &gf100_vmm_pgd }, + {} +}; + +const struct nvkm_vmm_desc +gk104_vmm_desc_16_12[] = { + { SPT, 14, 8, 0x1000, &gf100_vmm_pgt }, + { PGD, 14, 8, 0x1000, &gf100_vmm_pgd }, + {} +}; + +const struct nvkm_vmm_desc +gk104_vmm_desc_16_16[] = { + { LPT, 10, 8, 0x1000, &gk104_vmm_lpt }, + { PGD, 14, 8, 0x1000, &gf100_vmm_pgd }, + {} +}; + +static const struct nvkm_vmm_func +gk104_vmm_17 = { + .join = gf100_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 17, &gk104_vmm_desc_17_17[0], NVKM_VMM_PAGE_xVxC }, + { 12, &gk104_vmm_desc_17_12[0], NVKM_VMM_PAGE_xVHx }, + {} + } +}; + +static const struct nvkm_vmm_func +gk104_vmm_16 = { + .join = gf100_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 16, &gk104_vmm_desc_16_16[0], NVKM_VMM_PAGE_xVxC }, + { 12, &gk104_vmm_desc_16_12[0], NVKM_VMM_PAGE_xVHx }, + {} + } +}; + +int +gk104_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return gf100_vmm_new_(&gk104_vmm_16, &gk104_vmm_17, mmu, addr, + size, argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk20a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk20a.c new file mode 100644 index 000000000000..8086994a0446 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgk20a.c @@ -0,0 +1,71 @@ +/* + * 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 "vmm.h" + +#include <core/memory.h> + +int +gk20a_vmm_aper(enum nvkm_memory_target target) +{ + switch (target) { + case NVKM_MEM_TARGET_NCOH: return 0; + default: + return -EINVAL; + } +} + +static const struct nvkm_vmm_func +gk20a_vmm_17 = { + .join = gf100_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 17, &gk104_vmm_desc_17_17[0], NVKM_VMM_PAGE_xxHC }, + { 12, &gk104_vmm_desc_17_12[0], NVKM_VMM_PAGE_xxHx }, + {} + } +}; + +static const struct nvkm_vmm_func +gk20a_vmm_16 = { + .join = gf100_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 16, &gk104_vmm_desc_16_16[0], NVKM_VMM_PAGE_xxHC }, + { 12, &gk104_vmm_desc_16_12[0], NVKM_VMM_PAGE_xxHx }, + {} + } +}; + +int +gk20a_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return gf100_vmm_new_(&gk20a_vmm_16, &gk20a_vmm_17, mmu, addr, + size, argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm200.c new file mode 100644 index 000000000000..a1676a4644fe --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm200.c @@ -0,0 +1,185 @@ +/* + * 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 "vmm.h" + +#include <nvif/ifb00d.h> +#include <nvif/unpack.h> + +static void +gm200_vmm_pgt_sparse(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + /* VALID_FALSE + VOL tells the MMU to treat the PTE as sparse. */ + VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(32) /* VOL. */, ptes); +} + +static const struct nvkm_vmm_desc_func +gm200_vmm_spt = { + .unmap = gf100_vmm_pgt_unmap, + .sparse = gm200_vmm_pgt_sparse, + .mem = gf100_vmm_pgt_mem, + .dma = gf100_vmm_pgt_dma, + .sgl = gf100_vmm_pgt_sgl, +}; + +static const struct nvkm_vmm_desc_func +gm200_vmm_lpt = { + .invalid = gk104_vmm_lpt_invalid, + .unmap = gf100_vmm_pgt_unmap, + .sparse = gm200_vmm_pgt_sparse, + .mem = gf100_vmm_pgt_mem, +}; + +static void +gm200_vmm_pgd_sparse(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes) +{ + /* VALID_FALSE + VOL_BIG tells the MMU to treat the PDE as sparse. */ + VMM_FO064(pt, vmm, pdei * 8, BIT_ULL(35) /* VOL_BIG. */, pdes); +} + +static const struct nvkm_vmm_desc_func +gm200_vmm_pgd = { + .unmap = gf100_vmm_pgt_unmap, + .sparse = gm200_vmm_pgd_sparse, + .pde = gf100_vmm_pgd_pde, +}; + +const struct nvkm_vmm_desc +gm200_vmm_desc_17_12[] = { + { SPT, 15, 8, 0x1000, &gm200_vmm_spt }, + { PGD, 13, 8, 0x1000, &gm200_vmm_pgd }, + {} +}; + +const struct nvkm_vmm_desc +gm200_vmm_desc_17_17[] = { + { LPT, 10, 8, 0x1000, &gm200_vmm_lpt }, + { PGD, 13, 8, 0x1000, &gm200_vmm_pgd }, + {} +}; + +const struct nvkm_vmm_desc +gm200_vmm_desc_16_12[] = { + { SPT, 14, 8, 0x1000, &gm200_vmm_spt }, + { PGD, 14, 8, 0x1000, &gm200_vmm_pgd }, + {} +}; + +const struct nvkm_vmm_desc +gm200_vmm_desc_16_16[] = { + { LPT, 10, 8, 0x1000, &gm200_vmm_lpt }, + { PGD, 14, 8, 0x1000, &gm200_vmm_pgd }, + {} +}; + +int +gm200_vmm_join_(struct nvkm_vmm *vmm, struct nvkm_memory *inst, u64 base) +{ + if (vmm->func->page[1].shift == 16) + base |= BIT_ULL(11); + return gf100_vmm_join_(vmm, inst, base); +} + +int +gm200_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + return gm200_vmm_join_(vmm, inst, 0); +} + +static const struct nvkm_vmm_func +gm200_vmm_17 = { + .join = gm200_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 27, &gm200_vmm_desc_17_17[1], NVKM_VMM_PAGE_Sxxx }, + { 17, &gm200_vmm_desc_17_17[0], NVKM_VMM_PAGE_SVxC }, + { 12, &gm200_vmm_desc_17_12[0], NVKM_VMM_PAGE_SVHx }, + {} + } +}; + +static const struct nvkm_vmm_func +gm200_vmm_16 = { + .join = gm200_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 27, &gm200_vmm_desc_16_16[1], NVKM_VMM_PAGE_Sxxx }, + { 16, &gm200_vmm_desc_16_16[0], NVKM_VMM_PAGE_SVxC }, + { 12, &gm200_vmm_desc_16_12[0], NVKM_VMM_PAGE_SVHx }, + {} + } +}; + +int +gm200_vmm_new_(const struct nvkm_vmm_func *func_16, + const struct nvkm_vmm_func *func_17, + struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + const struct nvkm_vmm_func *func; + union { + struct gm200_vmm_vn vn; + struct gm200_vmm_v0 v0; + } *args = argv; + int ret = -ENOSYS; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + switch (args->v0.bigpage) { + case 16: func = func_16; break; + case 17: func = func_17; break; + default: + return -EINVAL; + } + } else + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + func = func_17; + } else + return ret; + + return nvkm_vmm_new_(func, mmu, 0, addr, size, key, name, pvmm); +} + +int +gm200_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return gm200_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, addr, + size, argv, argc, key, name, pvmm); +} + +int +gm200_vmm_new_fixed(struct nvkm_mmu *mmu, u64 addr, u64 size, + void *argv, u32 argc, struct lock_class_key *key, + const char *name, struct nvkm_vmm **pvmm) +{ + return gf100_vmm_new_(&gm200_vmm_16, &gm200_vmm_17, mmu, addr, + size, argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm20b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm20b.c new file mode 100644 index 000000000000..64d4b6cff8dd --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgm20b.c @@ -0,0 +1,70 @@ +/* + * 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 "vmm.h" + +static const struct nvkm_vmm_func +gm20b_vmm_17 = { + .join = gm200_vmm_join, + .part = gf100_vmm_part, + .aper = gk20a_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 27, &gm200_vmm_desc_17_17[1], NVKM_VMM_PAGE_Sxxx }, + { 17, &gm200_vmm_desc_17_17[0], NVKM_VMM_PAGE_SxHC }, + { 12, &gm200_vmm_desc_17_12[0], NVKM_VMM_PAGE_SxHx }, + {} + } +}; + +static const struct nvkm_vmm_func +gm20b_vmm_16 = { + .join = gm200_vmm_join, + .part = gf100_vmm_part, + .aper = gk20a_vmm_aper, + .valid = gf100_vmm_valid, + .flush = gf100_vmm_flush, + .page = { + { 27, &gm200_vmm_desc_16_16[1], NVKM_VMM_PAGE_Sxxx }, + { 16, &gm200_vmm_desc_16_16[0], NVKM_VMM_PAGE_SxHC }, + { 12, &gm200_vmm_desc_16_12[0], NVKM_VMM_PAGE_SxHx }, + {} + } +}; + +int +gm20b_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return gm200_vmm_new_(&gm20b_vmm_16, &gm20b_vmm_17, mmu, addr, + size, argv, argc, key, name, pvmm); +} + +int +gm20b_vmm_new_fixed(struct nvkm_mmu *mmu, u64 addr, u64 size, + void *argv, u32 argc, struct lock_class_key *key, + const char *name, struct nvkm_vmm **pvmm) +{ + return gf100_vmm_new_(&gm20b_vmm_16, &gm20b_vmm_17, mmu, addr, + size, argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c new file mode 100644 index 000000000000..059fafe0e771 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp100.c @@ -0,0 +1,347 @@ +/* + * 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 "vmm.h" + +#include <subdev/fb.h> +#include <subdev/ltc.h> + +#include <nvif/ifc00d.h> +#include <nvif/unpack.h> + +static inline void +gp100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) +{ + u64 data = (addr >> 4) | map->type; + + map->type += ptes * map->ctag; + + while (ptes--) { + VMM_WO064(pt, vmm, ptei++ * 8, data); + data += map->next; + } +} + +static void +gp100_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte); +} + +static void +gp100_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + if (map->page->shift == PAGE_SHIFT) { + VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes); + nvkm_kmap(pt->memory); + while (ptes--) { + const u64 data = (*map->dma++ >> 4) | map->type; + VMM_WO064(pt, vmm, ptei++ * 8, data); + map->type += map->ctag; + } + nvkm_done(pt->memory); + return; + } + + VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte); +} + +static void +gp100_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gp100_vmm_pgt_pte); +} + +static void +gp100_vmm_pgt_sparse(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + /* VALID_FALSE + VOL tells the MMU to treat the PTE as sparse. */ + VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(3) /* VOL. */, ptes); +} + +static const struct nvkm_vmm_desc_func +gp100_vmm_desc_spt = { + .unmap = gf100_vmm_pgt_unmap, + .sparse = gp100_vmm_pgt_sparse, + .mem = gp100_vmm_pgt_mem, + .dma = gp100_vmm_pgt_dma, + .sgl = gp100_vmm_pgt_sgl, +}; + +static void +gp100_vmm_lpt_invalid(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + /* VALID_FALSE + PRIV tells the MMU to ignore corresponding SPTEs. */ + VMM_FO064(pt, vmm, ptei * 8, BIT_ULL(5) /* PRIV. */, ptes); +} + +static const struct nvkm_vmm_desc_func +gp100_vmm_desc_lpt = { + .invalid = gp100_vmm_lpt_invalid, + .unmap = gf100_vmm_pgt_unmap, + .sparse = gp100_vmm_pgt_sparse, + .mem = gp100_vmm_pgt_mem, +}; + +static inline void +gp100_vmm_pd0_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) +{ + u64 data = (addr >> 4) | map->type; + + map->type += ptes * map->ctag; + + while (ptes--) { + VMM_WO128(pt, vmm, ptei++ * 0x10, data, 0ULL); + data += map->next; + } +} + +static void +gp100_vmm_pd0_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gp100_vmm_pd0_pte); +} + +static inline bool +gp100_vmm_pde(struct nvkm_mmu_pt *pt, u64 *data) +{ + switch (nvkm_memory_target(pt->memory)) { + case NVKM_MEM_TARGET_VRAM: *data |= 1ULL << 1; break; + case NVKM_MEM_TARGET_HOST: *data |= 2ULL << 1; + *data |= BIT_ULL(3); /* VOL. */ + break; + case NVKM_MEM_TARGET_NCOH: *data |= 3ULL << 1; break; + default: + WARN_ON(1); + return false; + } + *data |= pt->addr >> 4; + return true; +} + +static void +gp100_vmm_pd0_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei) +{ + struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; + struct nvkm_mmu_pt *pd = pgd->pt[0]; + u64 data[2] = {}; + + if (pgt->pt[0] && !gp100_vmm_pde(pgt->pt[0], &data[0])) + return; + if (pgt->pt[1] && !gp100_vmm_pde(pgt->pt[1], &data[1])) + return; + + nvkm_kmap(pd->memory); + VMM_WO128(pd, vmm, pdei * 0x10, data[0], data[1]); + nvkm_done(pd->memory); +} + +static void +gp100_vmm_pd0_sparse(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes) +{ + /* VALID_FALSE + VOL_BIG tells the MMU to treat the PDE as sparse. */ + VMM_FO128(pt, vmm, pdei * 0x10, BIT_ULL(3) /* VOL_BIG. */, 0ULL, pdes); +} + +static void +gp100_vmm_pd0_unmap(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes) +{ + VMM_FO128(pt, vmm, pdei * 0x10, 0ULL, 0ULL, pdes); +} + +static const struct nvkm_vmm_desc_func +gp100_vmm_desc_pd0 = { + .unmap = gp100_vmm_pd0_unmap, + .sparse = gp100_vmm_pd0_sparse, + .pde = gp100_vmm_pd0_pde, + .mem = gp100_vmm_pd0_mem, +}; + +static void +gp100_vmm_pd1_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei) +{ + struct nvkm_vmm_pt *pgt = pgd->pde[pdei]; + struct nvkm_mmu_pt *pd = pgd->pt[0]; + u64 data = 0; + + if (!gp100_vmm_pde(pgt->pt[0], &data)) + return; + + nvkm_kmap(pd->memory); + VMM_WO064(pd, vmm, pdei * 8, data); + nvkm_done(pd->memory); +} + +static const struct nvkm_vmm_desc_func +gp100_vmm_desc_pd1 = { + .unmap = gf100_vmm_pgt_unmap, + .sparse = gp100_vmm_pgt_sparse, + .pde = gp100_vmm_pd1_pde, +}; + +const struct nvkm_vmm_desc +gp100_vmm_desc_16[] = { + { LPT, 5, 8, 0x0100, &gp100_vmm_desc_lpt }, + { PGD, 8, 16, 0x1000, &gp100_vmm_desc_pd0 }, + { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 }, + { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 }, + { PGD, 2, 8, 0x1000, &gp100_vmm_desc_pd1 }, + {} +}; + +const struct nvkm_vmm_desc +gp100_vmm_desc_12[] = { + { SPT, 9, 8, 0x1000, &gp100_vmm_desc_spt }, + { PGD, 8, 16, 0x1000, &gp100_vmm_desc_pd0 }, + { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 }, + { PGD, 9, 8, 0x1000, &gp100_vmm_desc_pd1 }, + { PGD, 2, 8, 0x1000, &gp100_vmm_desc_pd1 }, + {} +}; + +int +gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, + struct nvkm_vmm_map *map) +{ + const enum nvkm_memory_target target = nvkm_memory_target(map->memory); + const struct nvkm_vmm_page *page = map->page; + union { + struct gp100_vmm_map_vn vn; + struct gp100_vmm_map_v0 v0; + } *args = argv; + struct nvkm_device *device = vmm->mmu->subdev.device; + struct nvkm_memory *memory = map->memory; + u8 kind, priv, ro, vol; + int kindn, aper, ret = -ENOSYS; + const u8 *kindm; + + map->next = (1ULL << page->shift) >> 4; + map->type = 0; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + vol = !!args->v0.vol; + ro = !!args->v0.ro; + priv = !!args->v0.priv; + kind = args->v0.kind; + } else + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + vol = target == NVKM_MEM_TARGET_HOST; + ro = 0; + priv = 0; + kind = 0x00; + } else { + VMM_DEBUG(vmm, "args"); + return ret; + } + + aper = vmm->func->aper(target); + if (WARN_ON(aper < 0)) + return aper; + + kindm = vmm->mmu->func->kind(vmm->mmu, &kindn); + if (kind >= kindn || kindm[kind] == 0xff) { + VMM_DEBUG(vmm, "kind %02x", kind); + return -EINVAL; + } + + if (kindm[kind] != kind) { + u64 tags = nvkm_memory_size(memory) >> 16; + if (aper != 0 || !(page->type & NVKM_VMM_PAGE_COMP)) { + VMM_DEBUG(vmm, "comp %d %02x", aper, page->type); + return -EINVAL; + } + + ret = nvkm_memory_tags_get(memory, device, tags, + nvkm_ltc_tags_clear, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } + + if (map->tags->mn) { + tags = map->tags->mn->offset + (map->offset >> 16); + map->ctag |= ((1ULL << page->shift) >> 16) << 36; + map->type |= tags << 36; + map->next |= map->ctag; + } else { + kind = kindm[kind]; + } + } + + map->type |= BIT(0); + map->type |= (u64)aper << 1; + map->type |= (u64) vol << 3; + map->type |= (u64)priv << 5; + map->type |= (u64) ro << 6; + map->type |= (u64)kind << 56; + return 0; +} + +void +gp100_vmm_flush(struct nvkm_vmm *vmm, int depth) +{ + gf100_vmm_flush_(vmm, 5 /* CACHE_LEVEL_UP_TO_PDE3 */ - depth); +} + +int +gp100_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + const u64 base = BIT_ULL(10) /* VER2 */ | BIT_ULL(11); /* 64KiB */ + return gf100_vmm_join_(vmm, inst, base); +} + +static const struct nvkm_vmm_func +gp100_vmm = { + .join = gp100_vmm_join, + .part = gf100_vmm_part, + .aper = gf100_vmm_aper, + .valid = gp100_vmm_valid, + .flush = gp100_vmm_flush, + .page = { + { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, + { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx }, + { 29, &gp100_vmm_desc_16[2], NVKM_VMM_PAGE_Sxxx }, + { 21, &gp100_vmm_desc_16[1], NVKM_VMM_PAGE_SVxC }, + { 16, &gp100_vmm_desc_16[0], NVKM_VMM_PAGE_SVxC }, + { 12, &gp100_vmm_desc_12[0], NVKM_VMM_PAGE_SVHx }, + {} + } +}; + +int +gp100_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return nv04_vmm_new_(&gp100_vmm, mmu, 0, addr, size, + argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c new file mode 100644 index 000000000000..3dcc6bddb32f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmgp10b.c @@ -0,0 +1,49 @@ +/* + * 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 "vmm.h" + +static const struct nvkm_vmm_func +gp10b_vmm = { + .join = gp100_vmm_join, + .part = gf100_vmm_part, + .aper = gk20a_vmm_aper, + .valid = gp100_vmm_valid, + .flush = gp100_vmm_flush, + .page = { + { 47, &gp100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx }, + { 38, &gp100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx }, + { 29, &gp100_vmm_desc_16[2], NVKM_VMM_PAGE_Sxxx }, + { 21, &gp100_vmm_desc_16[1], NVKM_VMM_PAGE_SxHC }, + { 16, &gp100_vmm_desc_16[0], NVKM_VMM_PAGE_SxHC }, + { 12, &gp100_vmm_desc_12[0], NVKM_VMM_PAGE_SxHx }, + {} + } +}; + +int +gp10b_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return nv04_vmm_new_(&gp10b_vmm, mmu, 0, addr, size, + argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv04.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv04.c new file mode 100644 index 000000000000..0cab1ffc9f64 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv04.c @@ -0,0 +1,140 @@ +/* + * 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 "vmm.h" + +#include <nvif/if000d.h> +#include <nvif/unpack.h> + +static inline void +nv04_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) +{ + u32 data = addr | 0x00000003; /* PRESENT, RW. */ + while (ptes--) { + VMM_WO032(pt, vmm, 8 + ptei++ * 4, data); + data += 0x00001000; + } +} + +static void +nv04_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv04_vmm_pgt_pte); +} + +static void +nv04_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ +#if PAGE_SHIFT == 12 + nvkm_kmap(pt->memory); + while (ptes--) + VMM_WO032(pt, vmm, 8 + (ptei++ * 4), *map->dma++ | 0x00000003); + nvkm_done(pt->memory); +#else + VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv04_vmm_pgt_pte); +#endif +} + +static void +nv04_vmm_pgt_unmap(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + VMM_FO032(pt, vmm, 8 + (ptei * 4), 0, ptes); +} + +static const struct nvkm_vmm_desc_func +nv04_vmm_desc_pgt = { + .unmap = nv04_vmm_pgt_unmap, + .dma = nv04_vmm_pgt_dma, + .sgl = nv04_vmm_pgt_sgl, +}; + +static const struct nvkm_vmm_desc +nv04_vmm_desc_12[] = { + { PGT, 15, 4, 0x1000, &nv04_vmm_desc_pgt }, + {} +}; + +int +nv04_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, + struct nvkm_vmm_map *map) +{ + union { + struct nv04_vmm_map_vn vn; + } *args = argv; + int ret = -ENOSYS; + if ((ret = nvif_unvers(ret, &argv, &argc, args->vn))) + VMM_DEBUG(vmm, "args"); + return ret; +} + +static const struct nvkm_vmm_func +nv04_vmm = { + .valid = nv04_vmm_valid, + .page = { + { 12, &nv04_vmm_desc_12[0], NVKM_VMM_PAGE_HOST }, + {} + } +}; + +int +nv04_vmm_new_(const struct nvkm_vmm_func *func, struct nvkm_mmu *mmu, + u32 pd_header, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + union { + struct nv04_vmm_vn vn; + } *args = argv; + int ret; + + ret = nvkm_vmm_new_(func, mmu, pd_header, addr, size, key, name, pvmm); + if (ret) + return ret; + + return nvif_unvers(-ENOSYS, &argv, &argc, args->vn); +} + +int +nv04_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + struct nvkm_memory *mem; + struct nvkm_vmm *vmm; + int ret; + + ret = nv04_vmm_new_(&nv04_vmm, mmu, 8, addr, size, + argv, argc, key, name, &vmm); + *pvmm = vmm; + if (ret) + return ret; + + mem = vmm->pd->pt[0]->memory; + nvkm_kmap(mem); + nvkm_wo32(mem, 0x00000, 0x0002103d); /* PCI, RW, PT, !LN */ + nvkm_wo32(mem, 0x00004, vmm->limit - 1); + nvkm_done(mem); + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv41.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv41.c new file mode 100644 index 000000000000..b595f130e573 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv41.c @@ -0,0 +1,113 @@ +/* + * 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 "vmm.h" + +#include <subdev/timer.h> + +static void +nv41_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) +{ + u32 data = (addr >> 7) | 0x00000001; /* VALID. */ + while (ptes--) { + VMM_WO032(pt, vmm, ptei++ * 4, data); + data += 0x00000020; + } +} + +static void +nv41_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv41_vmm_pgt_pte); +} + +static void +nv41_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ +#if PAGE_SHIFT == 12 + nvkm_kmap(pt->memory); + while (ptes--) { + const u32 data = (*map->dma++ >> 7) | 0x00000001; + VMM_WO032(pt, vmm, ptei++ * 4, data); + } + nvkm_done(pt->memory); +#else + VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv41_vmm_pgt_pte); +#endif +} + +static void +nv41_vmm_pgt_unmap(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + VMM_FO032(pt, vmm, ptei * 4, 0, ptes); +} + +static const struct nvkm_vmm_desc_func +nv41_vmm_desc_pgt = { + .unmap = nv41_vmm_pgt_unmap, + .dma = nv41_vmm_pgt_dma, + .sgl = nv41_vmm_pgt_sgl, +}; + +static const struct nvkm_vmm_desc +nv41_vmm_desc_12[] = { + { PGT, 17, 4, 0x1000, &nv41_vmm_desc_pgt }, + {} +}; + +static void +nv41_vmm_flush(struct nvkm_vmm *vmm, int level) +{ + struct nvkm_subdev *subdev = &vmm->mmu->subdev; + struct nvkm_device *device = subdev->device; + + mutex_lock(&subdev->mutex); + nvkm_wr32(device, 0x100810, 0x00000022); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100810) & 0x00000020) + break; + ); + nvkm_wr32(device, 0x100810, 0x00000000); + mutex_unlock(&subdev->mutex); +} + +static const struct nvkm_vmm_func +nv41_vmm = { + .valid = nv04_vmm_valid, + .flush = nv41_vmm_flush, + .page = { + { 12, &nv41_vmm_desc_12[0], NVKM_VMM_PAGE_HOST }, + {} + } +}; + +int +nv41_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return nv04_vmm_new_(&nv41_vmm, mmu, 0, addr, size, + argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c new file mode 100644 index 000000000000..b834e4352334 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv44.c @@ -0,0 +1,230 @@ +/* + * 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 "vmm.h" + +#include <subdev/timer.h> + +static void +nv44_vmm_pgt_fill(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + dma_addr_t *list, u32 ptei, u32 ptes) +{ + u32 pteo = (ptei << 2) & ~0x0000000f; + u32 tmp[4]; + + tmp[0] = nvkm_ro32(pt->memory, pteo + 0x0); + tmp[1] = nvkm_ro32(pt->memory, pteo + 0x4); + tmp[2] = nvkm_ro32(pt->memory, pteo + 0x8); + tmp[3] = nvkm_ro32(pt->memory, pteo + 0xc); + + while (ptes--) { + u32 addr = (list ? *list++ : vmm->null) >> 12; + switch (ptei++ & 0x3) { + case 0: + tmp[0] &= ~0x07ffffff; + tmp[0] |= addr; + break; + case 1: + tmp[0] &= ~0xf8000000; + tmp[0] |= addr << 27; + tmp[1] &= ~0x003fffff; + tmp[1] |= addr >> 5; + break; + case 2: + tmp[1] &= ~0xffc00000; + tmp[1] |= addr << 22; + tmp[2] &= ~0x0001ffff; + tmp[2] |= addr >> 10; + break; + case 3: + tmp[2] &= ~0xfffe0000; + tmp[2] |= addr << 17; + tmp[3] &= ~0x00000fff; + tmp[3] |= addr >> 15; + break; + } + } + + VMM_WO032(pt, vmm, pteo + 0x0, tmp[0]); + VMM_WO032(pt, vmm, pteo + 0x4, tmp[1]); + VMM_WO032(pt, vmm, pteo + 0x8, tmp[2]); + VMM_WO032(pt, vmm, pteo + 0xc, tmp[3] | 0x40000000); +} + +static void +nv44_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) +{ + dma_addr_t tmp[4], i; + + if (ptei & 3) { + const u32 pten = min(ptes, 4 - (ptei & 3)); + for (i = 0; i < pten; i++, addr += 0x1000) + tmp[i] = addr; + nv44_vmm_pgt_fill(vmm, pt, tmp, ptei, pten); + ptei += pten; + ptes -= pten; + } + + while (ptes >= 4) { + for (i = 0; i < 4; i++, addr += 0x1000) + tmp[i] = addr >> 12; + VMM_WO032(pt, vmm, ptei++ * 4, tmp[0] >> 0 | tmp[1] << 27); + VMM_WO032(pt, vmm, ptei++ * 4, tmp[1] >> 5 | tmp[2] << 22); + VMM_WO032(pt, vmm, ptei++ * 4, tmp[2] >> 10 | tmp[3] << 17); + VMM_WO032(pt, vmm, ptei++ * 4, tmp[3] >> 15 | 0x40000000); + ptes -= 4; + } + + if (ptes) { + for (i = 0; i < ptes; i++, addr += 0x1000) + tmp[i] = addr; + nv44_vmm_pgt_fill(vmm, pt, tmp, ptei, ptes); + } +} + +static void +nv44_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv44_vmm_pgt_pte); +} + +static void +nv44_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ +#if PAGE_SHIFT == 12 + nvkm_kmap(pt->memory); + if (ptei & 3) { + const u32 pten = min(ptes, 4 - (ptei & 3)); + nv44_vmm_pgt_fill(vmm, pt, map->dma, ptei, pten); + ptei += pten; + ptes -= pten; + map->dma += pten; + } + + while (ptes >= 4) { + u32 tmp[4], i; + for (i = 0; i < 4; i++) + tmp[i] = *map->dma++ >> 12; + VMM_WO032(pt, vmm, ptei++ * 4, tmp[0] >> 0 | tmp[1] << 27); + VMM_WO032(pt, vmm, ptei++ * 4, tmp[1] >> 5 | tmp[2] << 22); + VMM_WO032(pt, vmm, ptei++ * 4, tmp[2] >> 10 | tmp[3] << 17); + VMM_WO032(pt, vmm, ptei++ * 4, tmp[3] >> 15 | 0x40000000); + ptes -= 4; + } + + if (ptes) { + nv44_vmm_pgt_fill(vmm, pt, map->dma, ptei, ptes); + map->dma += ptes; + } + nvkm_done(pt->memory); +#else + VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv44_vmm_pgt_pte); +#endif +} + +static void +nv44_vmm_pgt_unmap(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + nvkm_kmap(pt->memory); + if (ptei & 3) { + const u32 pten = min(ptes, 4 - (ptei & 3)); + nv44_vmm_pgt_fill(vmm, pt, NULL, ptei, pten); + ptei += pten; + ptes -= pten; + } + + while (ptes > 4) { + VMM_WO032(pt, vmm, ptei++ * 4, 0x00000000); + VMM_WO032(pt, vmm, ptei++ * 4, 0x00000000); + VMM_WO032(pt, vmm, ptei++ * 4, 0x00000000); + VMM_WO032(pt, vmm, ptei++ * 4, 0x00000000); + ptes -= 4; + } + + if (ptes) + nv44_vmm_pgt_fill(vmm, pt, NULL, ptei, ptes); + nvkm_done(pt->memory); +} + +static const struct nvkm_vmm_desc_func +nv44_vmm_desc_pgt = { + .unmap = nv44_vmm_pgt_unmap, + .dma = nv44_vmm_pgt_dma, + .sgl = nv44_vmm_pgt_sgl, +}; + +static const struct nvkm_vmm_desc +nv44_vmm_desc_12[] = { + { PGT, 17, 4, 0x80000, &nv44_vmm_desc_pgt }, + {} +}; + +static void +nv44_vmm_flush(struct nvkm_vmm *vmm, int level) +{ + struct nvkm_device *device = vmm->mmu->subdev.device; + nvkm_wr32(device, 0x100814, vmm->limit - 4096); + nvkm_wr32(device, 0x100808, 0x000000020); + nvkm_msec(device, 2000, + if (nvkm_rd32(device, 0x100808) & 0x00000001) + break; + ); + nvkm_wr32(device, 0x100808, 0x00000000); +} + +static const struct nvkm_vmm_func +nv44_vmm = { + .valid = nv04_vmm_valid, + .flush = nv44_vmm_flush, + .page = { + { 12, &nv44_vmm_desc_12[0], NVKM_VMM_PAGE_HOST }, + {} + } +}; + +int +nv44_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + struct nvkm_subdev *subdev = &mmu->subdev; + struct nvkm_vmm *vmm; + int ret; + + ret = nv04_vmm_new_(&nv44_vmm, mmu, 0, addr, size, + argv, argc, key, name, &vmm); + *pvmm = vmm; + if (ret) + return ret; + + vmm->nullp = dma_alloc_coherent(subdev->device->dev, 16 * 1024, + &vmm->null, GFP_KERNEL); + if (!vmm->nullp) { + nvkm_warn(subdev, "unable to allocate dummy pages\n"); + vmm->null = 0; + } + + return 0; +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c new file mode 100644 index 000000000000..863a2edd9861 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmmnv50.c @@ -0,0 +1,385 @@ +/* + * 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 "vmm.h" + +#include <subdev/fb.h> +#include <subdev/timer.h> +#include <engine/gr.h> + +#include <nvif/if500d.h> +#include <nvif/unpack.h> + +static inline void +nv50_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr) +{ + u64 next = addr | map->type, data; + u32 pten; + int log2blk; + + map->type += ptes * map->ctag; + + while (ptes) { + for (log2blk = 7; log2blk >= 0; log2blk--) { + pten = 1 << log2blk; + if (ptes >= pten && IS_ALIGNED(ptei, pten)) + break; + } + + data = next | (log2blk << 7); + next += pten * map->next; + ptes -= pten; + + while (pten--) + VMM_WO064(pt, vmm, ptei++ * 8, data); + } +} + +static void +nv50_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, nv50_vmm_pgt_pte); +} + +static void +nv50_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + if (map->page->shift == PAGE_SHIFT) { + VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes); + nvkm_kmap(pt->memory); + while (ptes--) { + const u64 data = *map->dma++ | map->type; + VMM_WO064(pt, vmm, ptei++ * 8, data); + map->type += map->ctag; + } + nvkm_done(pt->memory); + return; + } + + VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, nv50_vmm_pgt_pte); +} + +static void +nv50_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, + u32 ptei, u32 ptes, struct nvkm_vmm_map *map) +{ + VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, nv50_vmm_pgt_pte); +} + +static void +nv50_vmm_pgt_unmap(struct nvkm_vmm *vmm, + struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes) +{ + VMM_FO064(pt, vmm, ptei * 8, 0ULL, ptes); +} + +static const struct nvkm_vmm_desc_func +nv50_vmm_pgt = { + .unmap = nv50_vmm_pgt_unmap, + .mem = nv50_vmm_pgt_mem, + .dma = nv50_vmm_pgt_dma, + .sgl = nv50_vmm_pgt_sgl, +}; + +static bool +nv50_vmm_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgt, u64 *pdata) +{ + struct nvkm_mmu_pt *pt; + u64 data = 0xdeadcafe00000000ULL; + if (pgt && (pt = pgt->pt[0])) { + switch (pgt->page) { + case 16: data = 0x00000001; break; + case 12: data = 0x00000003; + switch (nvkm_memory_size(pt->memory)) { + case 0x100000: data |= 0x00000000; break; + case 0x040000: data |= 0x00000020; break; + case 0x020000: data |= 0x00000040; break; + case 0x010000: data |= 0x00000060; break; + default: + WARN_ON(1); + return false; + } + break; + default: + WARN_ON(1); + return false; + } + + switch (nvkm_memory_target(pt->memory)) { + case NVKM_MEM_TARGET_VRAM: data |= 0x00000000; break; + case NVKM_MEM_TARGET_HOST: data |= 0x00000008; break; + case NVKM_MEM_TARGET_NCOH: data |= 0x0000000c; break; + default: + WARN_ON(1); + return false; + } + + data |= pt->addr; + } + *pdata = data; + return true; +} + +static void +nv50_vmm_pgd_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei) +{ + struct nvkm_vmm_join *join; + u32 pdeo = vmm->mmu->func->vmm.pd_offset + (pdei * 8); + u64 data; + + if (!nv50_vmm_pde(vmm, pgd->pde[pdei], &data)) + return; + + list_for_each_entry(join, &vmm->join, head) { + nvkm_kmap(join->inst); + nvkm_wo64(join->inst, pdeo, data); + nvkm_done(join->inst); + } +} + +static const struct nvkm_vmm_desc_func +nv50_vmm_pgd = { + .pde = nv50_vmm_pgd_pde, +}; + +static const struct nvkm_vmm_desc +nv50_vmm_desc_12[] = { + { PGT, 17, 8, 0x1000, &nv50_vmm_pgt }, + { PGD, 11, 0, 0x0000, &nv50_vmm_pgd }, + {} +}; + +static const struct nvkm_vmm_desc +nv50_vmm_desc_16[] = { + { PGT, 13, 8, 0x1000, &nv50_vmm_pgt }, + { PGD, 11, 0, 0x0000, &nv50_vmm_pgd }, + {} +}; + +static void +nv50_vmm_flush(struct nvkm_vmm *vmm, int level) +{ + struct nvkm_subdev *subdev = &vmm->mmu->subdev; + struct nvkm_device *device = subdev->device; + int i, id; + + mutex_lock(&subdev->mutex); + for (i = 0; i < NVKM_SUBDEV_NR; i++) { + if (!atomic_read(&vmm->engref[i])) + continue; + + /* unfortunate hw bug workaround... */ + if (i == NVKM_ENGINE_GR && device->gr) { + int ret = nvkm_gr_tlb_flush(device->gr); + if (ret != -ENODEV) + continue; + } + + switch (i) { + case NVKM_ENGINE_GR : id = 0x00; break; + case NVKM_ENGINE_VP : + case NVKM_ENGINE_MSPDEC: id = 0x01; break; + case NVKM_SUBDEV_BAR : id = 0x06; break; + case NVKM_ENGINE_MSPPP : + case NVKM_ENGINE_MPEG : id = 0x08; break; + case NVKM_ENGINE_BSP : + case NVKM_ENGINE_MSVLD : id = 0x09; break; + case NVKM_ENGINE_CIPHER: + case NVKM_ENGINE_SEC : id = 0x0a; break; + case NVKM_ENGINE_CE0 : id = 0x0d; break; + default: + continue; + } + + nvkm_wr32(device, 0x100c80, (id << 16) | 1); + if (nvkm_msec(device, 2000, + if (!(nvkm_rd32(device, 0x100c80) & 0x00000001)) + break; + ) < 0) + nvkm_error(subdev, "%s mmu invalidate timeout\n", + nvkm_subdev_name[i]); + } + mutex_unlock(&subdev->mutex); +} + +static int +nv50_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc, + struct nvkm_vmm_map *map) +{ + const struct nvkm_vmm_page *page = map->page; + union { + struct nv50_vmm_map_vn vn; + struct nv50_vmm_map_v0 v0; + } *args = argv; + struct nvkm_device *device = vmm->mmu->subdev.device; + struct nvkm_ram *ram = device->fb->ram; + struct nvkm_memory *memory = map->memory; + u8 aper, kind, comp, priv, ro; + int kindn, ret = -ENOSYS; + const u8 *kindm; + + map->type = map->ctag = 0; + map->next = 1 << page->shift; + + if (!(ret = nvif_unpack(ret, &argv, &argc, args->v0, 0, 0, false))) { + ro = !!args->v0.ro; + priv = !!args->v0.priv; + kind = args->v0.kind & 0x7f; + comp = args->v0.comp & 0x03; + } else + if (!(ret = nvif_unvers(ret, &argv, &argc, args->vn))) { + ro = 0; + priv = 0; + kind = 0x00; + comp = 0; + } else { + VMM_DEBUG(vmm, "args"); + return ret; + } + + switch (nvkm_memory_target(memory)) { + case NVKM_MEM_TARGET_VRAM: + if (ram->stolen) { + map->type |= ram->stolen; + aper = 3; + } else { + aper = 0; + } + break; + case NVKM_MEM_TARGET_HOST: + aper = 2; + break; + case NVKM_MEM_TARGET_NCOH: + aper = 3; + break; + default: + WARN_ON(1); + return -EINVAL; + } + + kindm = vmm->mmu->func->kind(vmm->mmu, &kindn); + if (kind >= kindn || kindm[kind] == 0x7f) { + VMM_DEBUG(vmm, "kind %02x", kind); + return -EINVAL; + } + + if (map->mem && map->mem->type != kindm[kind]) { + VMM_DEBUG(vmm, "kind %02x bankswz: %d %d", kind, + kindm[kind], map->mem->type); + return -EINVAL; + } + + if (comp) { + u32 tags = (nvkm_memory_size(memory) >> 16) * comp; + if (aper != 0 || !(page->type & NVKM_VMM_PAGE_COMP)) { + VMM_DEBUG(vmm, "comp %d %02x", aper, page->type); + return -EINVAL; + } + + ret = nvkm_memory_tags_get(memory, device, tags, NULL, + &map->tags); + if (ret) { + VMM_DEBUG(vmm, "comp %d", ret); + return ret; + } + + if (map->tags->mn) { + u32 tags = map->tags->mn->offset + (map->offset >> 16); + map->ctag |= (u64)comp << 49; + map->type |= (u64)comp << 47; + map->type |= (u64)tags << 49; + map->next |= map->ctag; + } + } + + map->type |= BIT(0); /* Valid. */ + map->type |= (u64)ro << 3; + map->type |= (u64)aper << 4; + map->type |= (u64)priv << 6; + map->type |= (u64)kind << 40; + return 0; +} + +static void +nv50_vmm_part(struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + struct nvkm_vmm_join *join; + + list_for_each_entry(join, &vmm->join, head) { + if (join->inst == inst) { + list_del(&join->head); + kfree(join); + break; + } + } +} + +static int +nv50_vmm_join(struct nvkm_vmm *vmm, struct nvkm_memory *inst) +{ + const u32 pd_offset = vmm->mmu->func->vmm.pd_offset; + struct nvkm_vmm_join *join; + int ret = 0; + u64 data; + u32 pdei; + + if (!(join = kmalloc(sizeof(*join), GFP_KERNEL))) + return -ENOMEM; + join->inst = inst; + list_add_tail(&join->head, &vmm->join); + + nvkm_kmap(join->inst); + for (pdei = vmm->start >> 29; pdei <= (vmm->limit - 1) >> 29; pdei++) { + if (!nv50_vmm_pde(vmm, vmm->pd->pde[pdei], &data)) { + ret = -EINVAL; + break; + } + nvkm_wo64(join->inst, pd_offset + (pdei * 8), data); + } + nvkm_done(join->inst); + return ret; +} + +static const struct nvkm_vmm_func +nv50_vmm = { + .join = nv50_vmm_join, + .part = nv50_vmm_part, + .valid = nv50_vmm_valid, + .flush = nv50_vmm_flush, + .page_block = 1 << 29, + .page = { + { 16, &nv50_vmm_desc_16[0], NVKM_VMM_PAGE_xVxC }, + { 12, &nv50_vmm_desc_12[0], NVKM_VMM_PAGE_xVHx }, + {} + } +}; + +int +nv50_vmm_new(struct nvkm_mmu *mmu, u64 addr, u64 size, void *argv, u32 argc, + struct lock_class_key *key, const char *name, + struct nvkm_vmm **pvmm) +{ + return nv04_vmm_new_(&nv50_vmm, mmu, 0, addr, size, + argv, argc, key, name, pvmm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c index a4cb82495cee..b1b1f3626b96 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c @@ -87,7 +87,7 @@ nvkm_pci_fini(struct nvkm_subdev *subdev, bool suspend) if (pci->irq >= 0) { free_irq(pci->irq, pci); pci->irq = -1; - }; + } if (pci->agp.bridge) nvkm_agp_fini(pci); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c index 73ca1203281d..5e91b3f90065 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.c @@ -39,7 +39,7 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob, { struct gm200_secboot *gsb = gm200_secboot(sb); struct nvkm_subdev *subdev = &gsb->base.subdev; - struct nvkm_vma vma; + struct nvkm_vma *vma = NULL; u32 start_address; int ret; @@ -48,12 +48,16 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob, return ret; /* Map the HS firmware so the HS bootloader can see it */ - ret = nvkm_gpuobj_map(blob, gsb->vm, NV_MEM_ACCESS_RW, &vma); + ret = nvkm_vmm_get(gsb->vmm, 12, blob->size, &vma); if (ret) { nvkm_falcon_put(falcon, subdev); return ret; } + ret = nvkm_memory_map(blob, 0, gsb->vmm, vma, NULL, 0); + if (ret) + goto end; + /* Reset and set the falcon up */ ret = nvkm_falcon_reset(falcon); if (ret) @@ -61,7 +65,7 @@ gm200_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob, nvkm_falcon_bind_context(falcon, gsb->inst); /* Load the HS bootloader into the falcon's IMEM/DMEM */ - ret = sb->acr->func->load(sb->acr, falcon, blob, vma.offset); + ret = sb->acr->func->load(sb->acr, falcon, blob, vma->addr); if (ret < 0) goto end; @@ -91,7 +95,7 @@ end: nvkm_mc_intr_mask(sb->subdev.device, falcon->owner->index, true); /* We don't need the ACR firmware anymore */ - nvkm_gpuobj_unmap(&vma); + nvkm_vmm_put(gsb->vmm, &vma); nvkm_falcon_put(falcon, subdev); return ret; @@ -102,37 +106,26 @@ gm200_secboot_oneinit(struct nvkm_secboot *sb) { struct gm200_secboot *gsb = gm200_secboot(sb); struct nvkm_device *device = sb->subdev.device; - struct nvkm_vm *vm; - const u64 vm_area_len = 600 * 1024; int ret; /* Allocate instance block and VM */ - ret = nvkm_gpuobj_new(device, 0x1000, 0, true, NULL, &gsb->inst); + ret = nvkm_memory_new(device, NVKM_MEM_TARGET_INST, 0x1000, 0, true, + &gsb->inst); if (ret) return ret; - ret = nvkm_gpuobj_new(device, 0x8000, 0, true, NULL, &gsb->pgd); + ret = nvkm_vmm_new(device, 0, 600 * 1024, NULL, 0, NULL, "acr", + &gsb->vmm); if (ret) return ret; - ret = nvkm_vm_new(device, 0, vm_area_len, 0, NULL, &vm); - if (ret) - return ret; - - atomic_inc(&vm->engref[NVKM_SUBDEV_PMU]); + atomic_inc(&gsb->vmm->engref[NVKM_SUBDEV_PMU]); + gsb->vmm->debug = gsb->base.subdev.debug; - ret = nvkm_vm_ref(vm, &gsb->vm, gsb->pgd); - nvkm_vm_ref(NULL, &vm, NULL); + ret = nvkm_vmm_join(gsb->vmm, gsb->inst); if (ret) return ret; - nvkm_kmap(gsb->inst); - nvkm_wo32(gsb->inst, 0x200, lower_32_bits(gsb->pgd->addr)); - nvkm_wo32(gsb->inst, 0x204, upper_32_bits(gsb->pgd->addr)); - nvkm_wo32(gsb->inst, 0x208, lower_32_bits(vm_area_len - 1)); - nvkm_wo32(gsb->inst, 0x20c, upper_32_bits(vm_area_len - 1)); - nvkm_done(gsb->inst); - if (sb->acr->func->oneinit) { ret = sb->acr->func->oneinit(sb->acr, sb); if (ret) @@ -160,9 +153,9 @@ gm200_secboot_dtor(struct nvkm_secboot *sb) sb->acr->func->dtor(sb->acr); - nvkm_vm_ref(NULL, &gsb->vm, gsb->pgd); - nvkm_gpuobj_del(&gsb->pgd); - nvkm_gpuobj_del(&gsb->inst); + nvkm_vmm_part(gsb->vmm, gsb->inst); + nvkm_vmm_unref(&gsb->vmm); + nvkm_memory_unref(&gsb->inst); return gsb; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h index c8ab3d76bdef..62c5e162099a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gm200.h @@ -29,9 +29,8 @@ struct gm200_secboot { struct nvkm_secboot base; /* Instance block & address space used for HS FW execution */ - struct nvkm_gpuobj *inst; - struct nvkm_gpuobj *pgd; - struct nvkm_vm *vm; + struct nvkm_memory *inst; + struct nvkm_vmm *vmm; }; #define gm200_secboot(sb) container_of(sb, struct gm200_secboot, base) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c index ee989210725e..6f10b098676c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/ls_ucode_msgqueue.c @@ -183,7 +183,7 @@ acr_ls_sec2_post_run(const struct nvkm_acr *acr, const struct nvkm_secboot *sb) break; ); if (reg & BIT(4)) { - nvkm_debug(subdev, "applying workaround for start bug..."); + nvkm_debug(subdev, "applying workaround for start bug...\n"); nvkm_falcon_start(sb->boot_falcon); nvkm_msec(subdev->device, 1, if ((reg = nvkm_rd32(subdev->device, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h index 885e919a8720..d9091f029506 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h @@ -25,6 +25,7 @@ #include <subdev/secboot.h> #include <subdev/mmu.h> +struct nvkm_gpuobj; struct nvkm_secboot_func { int (*oneinit)(struct nvkm_secboot *); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild index 2bafcc1d1818..7ba56b12badd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild @@ -12,3 +12,4 @@ nvkm-y += nvkm/subdev/therm/gt215.o nvkm-y += nvkm/subdev/therm/gf119.o nvkm-y += nvkm/subdev/therm/gm107.o nvkm-y += nvkm/subdev/therm/gm200.o +nvkm-y += nvkm/subdev/therm/gp100.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index 952a7cb0a59a..f27fc6d0d4c6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -341,7 +341,8 @@ nvkm_therm_init(struct nvkm_subdev *subdev) { struct nvkm_therm *therm = nvkm_therm(subdev); - therm->func->init(therm); + if (therm->func->init) + therm->func->init(therm); if (therm->suspend >= 0) { /* restore the pwm value only when on manual or auto mode */ diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.h b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gp100.c index 1df8154d0626..9f0dea3f61dc 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gp100.c @@ -1,5 +1,5 @@ /* - * Copyright 2015 Advanced Micro Devices, Inc. + * Copyright 2017 Rhys Kidd * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -19,26 +19,38 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * + * Authors: Rhys Kidd */ -#ifndef POLARIS10_SMC_H -#define POLARIS10_SMC_H +#include "priv.h" -#include "smumgr.h" +static int +gp100_temp_get(struct nvkm_therm *therm) +{ + struct nvkm_device *device = therm->subdev.device; + struct nvkm_subdev *subdev = &therm->subdev; + u32 tsensor = nvkm_rd32(device, 0x020460); + u32 inttemp = (tsensor & 0x0001fff8); + /* device SHADOWed */ + if (tsensor & 0x40000000) + nvkm_trace(subdev, "reading temperature from SHADOWed sensor\n"); -int polaris10_populate_all_graphic_levels(struct pp_hwmgr *hwmgr); -int polaris10_populate_all_memory_levels(struct pp_hwmgr *hwmgr); -int polaris10_init_smc_table(struct pp_hwmgr *hwmgr); -int polaris10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr); -int polaris10_thermal_avfs_enable(struct pp_hwmgr *hwmgr); -int polaris10_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type); -int polaris10_update_sclk_threshold(struct pp_hwmgr *hwmgr); -uint32_t polaris10_get_offsetof(uint32_t type, uint32_t member); -uint32_t polaris10_get_mac_definition(uint32_t value); -int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr); -bool polaris10_is_dpm_running(struct pp_hwmgr *hwmgr); -int polaris10_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr, - struct amd_pp_profile *request); + /* device valid */ + if (tsensor & 0x20000000) + return (inttemp >> 8); + else + return -ENODEV; +} -#endif +static const struct nvkm_therm_func +gp100_therm = { + .temp_get = gp100_temp_get, + .program_alarms = nvkm_therm_program_alarms_polling, +}; +int +gp100_therm_new(struct nvkm_device *device, int index, + struct nvkm_therm **ptherm) +{ + return nvkm_therm_new_(&gp100_therm, device, index, ptherm); +} diff --git a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c index d9d25df6fc1b..4600d3841c25 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-hdmi.c @@ -165,11 +165,15 @@ static bool hdmic_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; + bool connected; if (gpio_is_valid(ddata->hpd_gpio)) - return gpio_get_value_cansleep(ddata->hpd_gpio); + connected = gpio_get_value_cansleep(ddata->hpd_gpio); else - return in->ops.hdmi->detect(in); + connected = in->ops.hdmi->detect(in); + if (!connected && in->ops.hdmi->lost_hotplug) + in->ops.hdmi->lost_hotplug(in); + return connected; } static int hdmic_register_hpd_cb(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c index a9e9d667c55e..e3d98d78fc40 100644 --- a/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c +++ b/drivers/gpu/drm/omapdrm/displays/encoder-tpd12s015.c @@ -51,6 +51,8 @@ static int tpd_connect(struct omap_dss_device *dssdev, dssdev->dst = dst; gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 1); + gpiod_set_value_cansleep(ddata->ls_oe_gpio, 1); + /* DC-DC converter needs at max 300us to get to 90% of 5V */ udelay(300); @@ -69,6 +71,7 @@ static void tpd_disconnect(struct omap_dss_device *dssdev, return; gpiod_set_value_cansleep(ddata->ct_cp_hpd_gpio, 0); + gpiod_set_value_cansleep(ddata->ls_oe_gpio, 0); dst->src = NULL; dssdev->dst = NULL; @@ -146,25 +149,22 @@ static int tpd_read_edid(struct omap_dss_device *dssdev, { struct panel_drv_data *ddata = to_panel_data(dssdev); struct omap_dss_device *in = ddata->in; - int r; if (!gpiod_get_value_cansleep(ddata->hpd_gpio)) return -ENODEV; - gpiod_set_value_cansleep(ddata->ls_oe_gpio, 1); - - r = in->ops.hdmi->read_edid(in, edid, len); - - gpiod_set_value_cansleep(ddata->ls_oe_gpio, 0); - - return r; + return in->ops.hdmi->read_edid(in, edid, len); } static bool tpd_detect(struct omap_dss_device *dssdev) { struct panel_drv_data *ddata = to_panel_data(dssdev); + struct omap_dss_device *in = ddata->in; + bool connected = gpiod_get_value_cansleep(ddata->hpd_gpio); - return gpiod_get_value_cansleep(ddata->hpd_gpio); + if (!connected && in->ops.hdmi->lost_hotplug) + in->ops.hdmi->lost_hotplug(in); + return connected; } static int tpd_register_hpd_cb(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/omapdrm/dss/Kconfig b/drivers/gpu/drm/omapdrm/dss/Kconfig index 8b87d5cf45fc..f24ebf7f61dd 100644 --- a/drivers/gpu/drm/omapdrm/dss/Kconfig +++ b/drivers/gpu/drm/omapdrm/dss/Kconfig @@ -65,6 +65,14 @@ config OMAP4_DSS_HDMI help HDMI support for OMAP4 based SoCs. +config OMAP4_DSS_HDMI_CEC + bool "Enable HDMI CEC support for OMAP4" + depends on OMAP4_DSS_HDMI + select CEC_CORE + default y + ---help--- + When selected the HDMI transmitter will support the CEC feature. + config OMAP5_DSS_HDMI bool "HDMI support for OMAP5" default n diff --git a/drivers/gpu/drm/omapdrm/dss/Makefile b/drivers/gpu/drm/omapdrm/dss/Makefile index 142ce5a02542..3c5644c3fc38 100644 --- a/drivers/gpu/drm/omapdrm/dss/Makefile +++ b/drivers/gpu/drm/omapdrm/dss/Makefile @@ -14,5 +14,6 @@ omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o omapdss-$(CONFIG_OMAP2_DSS_HDMI_COMMON) += hdmi_common.o hdmi_wp.o hdmi_pll.o \ hdmi_phy.o omapdss-$(CONFIG_OMAP4_DSS_HDMI) += hdmi4.o hdmi4_core.o +omapdss-$(CONFIG_OMAP4_DSS_HDMI_CEC) += hdmi4_cec.o omapdss-$(CONFIG_OMAP5_DSS_HDMI) += hdmi5.o hdmi5_core.o ccflags-$(CONFIG_OMAP2_DSS_DEBUG) += -DDEBUG diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi.h b/drivers/gpu/drm/omapdrm/dss/hdmi.h index a820b394af09..c2609c448ddc 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi.h @@ -24,6 +24,7 @@ #include <linux/platform_device.h> #include <linux/hdmi.h> #include <sound/omap-hdmi-audio.h> +#include <media/cec.h> #include "omapdss.h" #include "dss.h" @@ -264,6 +265,10 @@ struct hdmi_core_data { void __iomem *base; bool cts_swmode; bool audio_use_mclk; + + struct hdmi_wp_data *wp; + unsigned int core_pwr_cnt; + struct cec_adapter *adap; }; static inline void hdmi_write_reg(void __iomem *base_addr, const u32 idx, @@ -373,7 +378,7 @@ struct omap_hdmi { bool audio_configured; struct omap_dss_audio audio_config; - /* This lock should be taken when booleans bellow are touched. */ + /* This lock should be taken when booleans below are touched. */ spinlock_t audio_playing_lock; bool audio_playing; bool display_enabled; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index f169348da377..a598dfdeb585 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -36,9 +36,11 @@ #include <linux/of.h> #include <linux/of_graph.h> #include <sound/omap-hdmi-audio.h> +#include <media/cec.h> #include "omapdss.h" #include "hdmi4_core.h" +#include "hdmi4_cec.h" #include "dss.h" #include "hdmi.h" @@ -70,7 +72,8 @@ static void hdmi_runtime_put(void) static irqreturn_t hdmi_irq_handler(int irq, void *data) { - struct hdmi_wp_data *wp = data; + struct omap_hdmi *hdmi = data; + struct hdmi_wp_data *wp = &hdmi->wp; u32 irqstatus; irqstatus = hdmi_wp_get_irqstatus(wp); @@ -95,6 +98,13 @@ static irqreturn_t hdmi_irq_handler(int irq, void *data) } else if (irqstatus & HDMI_IRQ_LINK_DISCONNECT) { hdmi_wp_set_phy_pwr(wp, HDMI_PHYPWRCMD_LDOON); } + if (irqstatus & HDMI_IRQ_CORE) { + u32 intr4 = hdmi_read_reg(hdmi->core.base, HDMI_CORE_SYS_INTR4); + + hdmi_write_reg(hdmi->core.base, HDMI_CORE_SYS_INTR4, intr4); + if (intr4 & 8) + hdmi4_cec_irq(&hdmi->core); + } return IRQ_HANDLED; } @@ -123,14 +133,19 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev) { int r; + if (hdmi.core.core_pwr_cnt++) + return 0; + r = regulator_enable(hdmi.vdda_reg); if (r) - return r; + goto err_reg_enable; r = hdmi_runtime_get(); if (r) goto err_runtime_get; + hdmi4_core_powerdown_disable(&hdmi.core); + /* Make selection of HDMI in DSS */ dss_select_hdmi_venc_clk_source(DSS_HDMI_M_PCLK); @@ -140,12 +155,17 @@ static int hdmi_power_on_core(struct omap_dss_device *dssdev) err_runtime_get: regulator_disable(hdmi.vdda_reg); +err_reg_enable: + hdmi.core.core_pwr_cnt--; return r; } static void hdmi_power_off_core(struct omap_dss_device *dssdev) { + if (--hdmi.core.core_pwr_cnt) + return; + hdmi.core_enabled = false; hdmi_runtime_put(); @@ -166,8 +186,8 @@ static int hdmi_power_on_full(struct omap_dss_device *dssdev) return r; /* disable and clear irqs */ - hdmi_wp_clear_irqenable(wp, 0xffffffff); - hdmi_wp_set_irqstatus(wp, 0xffffffff); + hdmi_wp_clear_irqenable(wp, ~HDMI_IRQ_CORE); + hdmi_wp_set_irqstatus(wp, ~HDMI_IRQ_CORE); vm = &hdmi.cfg.vm; @@ -242,7 +262,7 @@ static void hdmi_power_off_full(struct omap_dss_device *dssdev) { enum omap_channel channel = dssdev->dispc_channel; - hdmi_wp_clear_irqenable(&hdmi.wp, 0xffffffff); + hdmi_wp_clear_irqenable(&hdmi.wp, ~HDMI_IRQ_CORE); hdmi_wp_video_stop(&hdmi.wp); @@ -393,11 +413,11 @@ static void hdmi_display_disable(struct omap_dss_device *dssdev) mutex_unlock(&hdmi.lock); } -static int hdmi_core_enable(struct omap_dss_device *dssdev) +int hdmi4_core_enable(struct omap_dss_device *dssdev) { int r = 0; - DSSDBG("ENTER omapdss_hdmi_core_enable\n"); + DSSDBG("ENTER omapdss_hdmi4_core_enable\n"); mutex_lock(&hdmi.lock); @@ -415,9 +435,9 @@ err0: return r; } -static void hdmi_core_disable(struct omap_dss_device *dssdev) +void hdmi4_core_disable(struct omap_dss_device *dssdev) { - DSSDBG("Enter omapdss_hdmi_core_disable\n"); + DSSDBG("Enter omapdss_hdmi4_core_disable\n"); mutex_lock(&hdmi.lock); @@ -475,19 +495,28 @@ static int hdmi_read_edid(struct omap_dss_device *dssdev, need_enable = hdmi.core_enabled == false; if (need_enable) { - r = hdmi_core_enable(dssdev); + r = hdmi4_core_enable(dssdev); if (r) return r; } r = read_edid(edid, len); - + if (r >= 256) + hdmi4_cec_set_phys_addr(&hdmi.core, + cec_get_edid_phys_addr(edid, r, NULL)); + else + hdmi4_cec_set_phys_addr(&hdmi.core, CEC_PHYS_ADDR_INVALID); if (need_enable) - hdmi_core_disable(dssdev); + hdmi4_core_disable(dssdev); return r; } +static void hdmi_lost_hotplug(struct omap_dss_device *dssdev) +{ + hdmi4_cec_set_phys_addr(&hdmi.core, CEC_PHYS_ADDR_INVALID); +} + static int hdmi_set_infoframe(struct omap_dss_device *dssdev, const struct hdmi_avi_infoframe *avi) { @@ -514,6 +543,7 @@ static const struct omapdss_hdmi_ops hdmi_ops = { .get_timings = hdmi_display_get_timings, .read_edid = hdmi_read_edid, + .lost_hotplug = hdmi_lost_hotplug, .set_infoframe = hdmi_set_infoframe, .set_hdmi_mode = hdmi_set_hdmi_mode, }; @@ -715,6 +745,10 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data) if (r) goto err; + r = hdmi4_cec_init(pdev, &hdmi.core, &hdmi.wp); + if (r) + goto err; + irq = platform_get_irq(pdev, 0); if (irq < 0) { DSSERR("platform_get_irq failed\n"); @@ -724,7 +758,7 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data) r = devm_request_threaded_irq(&pdev->dev, irq, NULL, hdmi_irq_handler, - IRQF_ONESHOT, "OMAP HDMI", &hdmi.wp); + IRQF_ONESHOT, "OMAP HDMI", &hdmi); if (r) { DSSERR("HDMI IRQ request failed\n"); goto err; @@ -759,6 +793,8 @@ static void hdmi4_unbind(struct device *dev, struct device *master, void *data) hdmi_uninit_output(pdev); + hdmi4_cec_uninit(&hdmi.core); + hdmi_pll_uninit(&hdmi.pll); pm_runtime_disable(&pdev->dev); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c new file mode 100644 index 000000000000..d86873f2abe6 --- /dev/null +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.c @@ -0,0 +1,381 @@ +/* + * HDMI CEC + * + * Based on the CEC code from hdmi_ti_4xxx_ip.c from Android. + * + * Copyright (C) 2010-2011 Texas Instruments Incorporated - http://www.ti.com/ + * Authors: Yong Zhi + * Mythri pk <mythripk@ti.com> + * + * Heavily modified to use the linux CEC framework: + * + * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION 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 <linux/kernel.h> +#include <linux/err.h> +#include <linux/io.h> +#include <linux/platform_device.h> +#include <linux/slab.h> + +#include "dss.h" +#include "hdmi.h" +#include "hdmi4_core.h" +#include "hdmi4_cec.h" + +/* HDMI CEC */ +#define HDMI_CEC_DEV_ID 0x900 +#define HDMI_CEC_SPEC 0x904 + +/* Not really a debug register, more a low-level control register */ +#define HDMI_CEC_DBG_3 0x91C +#define HDMI_CEC_TX_INIT 0x920 +#define HDMI_CEC_TX_DEST 0x924 +#define HDMI_CEC_SETUP 0x938 +#define HDMI_CEC_TX_COMMAND 0x93C +#define HDMI_CEC_TX_OPERAND 0x940 +#define HDMI_CEC_TRANSMIT_DATA 0x97C +#define HDMI_CEC_CA_7_0 0x988 +#define HDMI_CEC_CA_15_8 0x98C +#define HDMI_CEC_INT_STATUS_0 0x998 +#define HDMI_CEC_INT_STATUS_1 0x99C +#define HDMI_CEC_INT_ENABLE_0 0x990 +#define HDMI_CEC_INT_ENABLE_1 0x994 +#define HDMI_CEC_RX_CONTROL 0x9B0 +#define HDMI_CEC_RX_COUNT 0x9B4 +#define HDMI_CEC_RX_CMD_HEADER 0x9B8 +#define HDMI_CEC_RX_COMMAND 0x9BC +#define HDMI_CEC_RX_OPERAND 0x9C0 + +#define HDMI_CEC_TX_FIFO_INT_MASK 0x64 +#define HDMI_CEC_RETRANSMIT_CNT_INT_MASK 0x2 + +#define HDMI_CORE_CEC_RETRY 200 + +static void hdmi_cec_received_msg(struct hdmi_core_data *core) +{ + u32 cnt = hdmi_read_reg(core->base, HDMI_CEC_RX_COUNT) & 0xff; + + /* While there are CEC frames in the FIFO */ + while (cnt & 0x70) { + /* and the frame doesn't have an error */ + if (!(cnt & 0x80)) { + struct cec_msg msg = {}; + unsigned int i; + + /* then read the message */ + msg.len = cnt & 0xf; + msg.msg[0] = hdmi_read_reg(core->base, + HDMI_CEC_RX_CMD_HEADER); + msg.msg[1] = hdmi_read_reg(core->base, + HDMI_CEC_RX_COMMAND); + for (i = 0; i < msg.len; i++) { + unsigned int reg = HDMI_CEC_RX_OPERAND + i * 4; + + msg.msg[2 + i] = + hdmi_read_reg(core->base, reg); + } + msg.len += 2; + cec_received_msg(core->adap, &msg); + } + /* Clear the current frame from the FIFO */ + hdmi_write_reg(core->base, HDMI_CEC_RX_CONTROL, 1); + /* Wait until the current frame is cleared */ + while (hdmi_read_reg(core->base, HDMI_CEC_RX_CONTROL) & 1) + udelay(1); + /* + * Re-read the count register and loop to see if there are + * more messages in the FIFO. + */ + cnt = hdmi_read_reg(core->base, HDMI_CEC_RX_COUNT) & 0xff; + } +} + +static void hdmi_cec_transmit_fifo_empty(struct hdmi_core_data *core, u32 stat1) +{ + if (stat1 & 2) { + u32 dbg3 = hdmi_read_reg(core->base, HDMI_CEC_DBG_3); + + cec_transmit_done(core->adap, + CEC_TX_STATUS_NACK | + CEC_TX_STATUS_MAX_RETRIES, + 0, (dbg3 >> 4) & 7, 0, 0); + } else if (stat1 & 1) { + cec_transmit_done(core->adap, + CEC_TX_STATUS_ARB_LOST | + CEC_TX_STATUS_MAX_RETRIES, + 0, 0, 0, 0); + } else if (stat1 == 0) { + cec_transmit_done(core->adap, CEC_TX_STATUS_OK, + 0, 0, 0, 0); + } +} + +void hdmi4_cec_irq(struct hdmi_core_data *core) +{ + u32 stat0 = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_0); + u32 stat1 = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1); + + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0, stat0); + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, stat1); + + if (stat0 & 0x40) + REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7); + else if (stat0 & 0x24) + hdmi_cec_transmit_fifo_empty(core, stat1); + if (stat1 & 2) { + u32 dbg3 = hdmi_read_reg(core->base, HDMI_CEC_DBG_3); + + cec_transmit_done(core->adap, + CEC_TX_STATUS_NACK | + CEC_TX_STATUS_MAX_RETRIES, + 0, (dbg3 >> 4) & 7, 0, 0); + } else if (stat1 & 1) { + cec_transmit_done(core->adap, + CEC_TX_STATUS_ARB_LOST | + CEC_TX_STATUS_MAX_RETRIES, + 0, 0, 0, 0); + } + if (stat0 & 0x02) + hdmi_cec_received_msg(core); + if (stat1 & 0x3) + REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7); +} + +static bool hdmi_cec_clear_tx_fifo(struct cec_adapter *adap) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + int retry = HDMI_CORE_CEC_RETRY; + int temp; + + REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, 0x1, 7, 7); + while (retry) { + temp = hdmi_read_reg(core->base, HDMI_CEC_DBG_3); + if (FLD_GET(temp, 7, 7) == 0) + break; + retry--; + } + return retry != 0; +} + +static bool hdmi_cec_clear_rx_fifo(struct cec_adapter *adap) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + int retry = HDMI_CORE_CEC_RETRY; + int temp; + + hdmi_write_reg(core->base, HDMI_CEC_RX_CONTROL, 0x3); + retry = HDMI_CORE_CEC_RETRY; + while (retry) { + temp = hdmi_read_reg(core->base, HDMI_CEC_RX_CONTROL); + if (FLD_GET(temp, 1, 0) == 0) + break; + retry--; + } + return retry != 0; +} + +static int hdmi_cec_adap_enable(struct cec_adapter *adap, bool enable) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + int temp, err; + + if (!enable) { + hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_0, 0); + hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_1, 0); + REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0, 3, 3); + hdmi_wp_clear_irqenable(core->wp, HDMI_IRQ_CORE); + hdmi_wp_set_irqstatus(core->wp, HDMI_IRQ_CORE); + hdmi4_core_disable(NULL); + return 0; + } + err = hdmi4_core_enable(NULL); + if (err) + return err; + + /* Clear TX FIFO */ + if (!hdmi_cec_clear_tx_fifo(adap)) { + pr_err("cec-%s: could not clear TX FIFO\n", adap->name); + return -EIO; + } + + /* Clear RX FIFO */ + if (!hdmi_cec_clear_rx_fifo(adap)) { + pr_err("cec-%s: could not clear RX FIFO\n", adap->name); + return -EIO; + } + + /* Clear CEC interrupts */ + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, + hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1)); + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0, + hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_0)); + + /* Enable HDMI core interrupts */ + hdmi_wp_set_irqenable(core->wp, HDMI_IRQ_CORE); + /* Unmask CEC interrupt */ + REG_FLD_MOD(core->base, HDMI_CORE_SYS_INTR_UNMASK4, 0x1, 3, 3); + /* + * Enable CEC interrupts: + * Transmit Buffer Full/Empty Change event + * Transmitter FIFO Empty event + * Receiver FIFO Not Empty event + */ + hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_0, 0x26); + /* + * Enable CEC interrupts: + * RX FIFO Overrun Error event + * Short Pulse Detected event + * Frame Retransmit Count Exceeded event + * Start Bit Irregularity event + */ + hdmi_write_reg(core->base, HDMI_CEC_INT_ENABLE_1, 0x0f); + + /* cec calibration enable (self clearing) */ + hdmi_write_reg(core->base, HDMI_CEC_SETUP, 0x03); + msleep(20); + hdmi_write_reg(core->base, HDMI_CEC_SETUP, 0x04); + + temp = hdmi_read_reg(core->base, HDMI_CEC_SETUP); + if (FLD_GET(temp, 4, 4) != 0) { + temp = FLD_MOD(temp, 0, 4, 4); + hdmi_write_reg(core->base, HDMI_CEC_SETUP, temp); + + /* + * If we enabled CEC in middle of a CEC message on the bus, + * we could have start bit irregularity and/or short + * pulse event. Clear them now. + */ + temp = hdmi_read_reg(core->base, HDMI_CEC_INT_STATUS_1); + temp = FLD_MOD(0x0, 0x5, 2, 0); + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, temp); + } + return 0; +} + +static int hdmi_cec_adap_log_addr(struct cec_adapter *adap, u8 log_addr) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + u32 v; + + if (log_addr == CEC_LOG_ADDR_INVALID) { + hdmi_write_reg(core->base, HDMI_CEC_CA_7_0, 0); + hdmi_write_reg(core->base, HDMI_CEC_CA_15_8, 0); + return 0; + } + if (log_addr <= 7) { + v = hdmi_read_reg(core->base, HDMI_CEC_CA_7_0); + v |= 1 << log_addr; + hdmi_write_reg(core->base, HDMI_CEC_CA_7_0, v); + } else { + v = hdmi_read_reg(core->base, HDMI_CEC_CA_15_8); + v |= 1 << (log_addr - 8); + hdmi_write_reg(core->base, HDMI_CEC_CA_15_8, v); + } + return 0; +} + +static int hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, + u32 signal_free_time, struct cec_msg *msg) +{ + struct hdmi_core_data *core = cec_get_drvdata(adap); + int temp; + u32 i; + + /* Clear TX FIFO */ + if (!hdmi_cec_clear_tx_fifo(adap)) { + pr_err("cec-%s: could not clear TX FIFO for transmit\n", + adap->name); + return -EIO; + } + + /* Clear TX interrupts */ + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_0, + HDMI_CEC_TX_FIFO_INT_MASK); + + hdmi_write_reg(core->base, HDMI_CEC_INT_STATUS_1, + HDMI_CEC_RETRANSMIT_CNT_INT_MASK); + + /* Set the retry count */ + REG_FLD_MOD(core->base, HDMI_CEC_DBG_3, attempts - 1, 6, 4); + + /* Set the initiator addresses */ + hdmi_write_reg(core->base, HDMI_CEC_TX_INIT, cec_msg_initiator(msg)); + + /* Set destination id */ + temp = cec_msg_destination(msg); + if (msg->len == 1) + temp |= 0x80; + hdmi_write_reg(core->base, HDMI_CEC_TX_DEST, temp); + if (msg->len == 1) + return 0; + + /* Setup command and arguments for the command */ + hdmi_write_reg(core->base, HDMI_CEC_TX_COMMAND, msg->msg[1]); + + for (i = 0; i < msg->len - 2; i++) + hdmi_write_reg(core->base, HDMI_CEC_TX_OPERAND + i * 4, + msg->msg[2 + i]); + + /* Operand count */ + hdmi_write_reg(core->base, HDMI_CEC_TRANSMIT_DATA, + (msg->len - 2) | 0x10); + return 0; +} + +static const struct cec_adap_ops hdmi_cec_adap_ops = { + .adap_enable = hdmi_cec_adap_enable, + .adap_log_addr = hdmi_cec_adap_log_addr, + .adap_transmit = hdmi_cec_adap_transmit, +}; + +void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa) +{ + cec_s_phys_addr(core->adap, pa, false); +} + +int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core, + struct hdmi_wp_data *wp) +{ + const u32 caps = CEC_CAP_TRANSMIT | CEC_CAP_LOG_ADDRS | + CEC_CAP_PASSTHROUGH | CEC_CAP_RC; + unsigned int ret; + + core->adap = cec_allocate_adapter(&hdmi_cec_adap_ops, core, + "omap4", caps, CEC_MAX_LOG_ADDRS); + ret = PTR_ERR_OR_ZERO(core->adap); + if (ret < 0) + return ret; + core->wp = wp; + + /* + * Initialize CEC clock divider: CEC needs 2MHz clock hence + * set the devider to 24 to get 48/24=2MHz clock + */ + REG_FLD_MOD(core->wp->base, HDMI_WP_CLK, 0x18, 5, 0); + + ret = cec_register_adapter(core->adap, &pdev->dev); + if (ret < 0) { + cec_delete_adapter(core->adap); + return ret; + } + return 0; +} + +void hdmi4_cec_uninit(struct hdmi_core_data *core) +{ + cec_unregister_adapter(core->adap); +} diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h new file mode 100644 index 000000000000..0292337c97cc --- /dev/null +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_cec.h @@ -0,0 +1,55 @@ +/* + * HDMI header definition for OMAP4 HDMI CEC IP + * + * Copyright 2016-2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved. + * + * This program is free software; you may redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _HDMI4_CEC_H_ +#define _HDMI4_CEC_H_ + +struct hdmi_core_data; +struct hdmi_wp_data; +struct platform_device; + +/* HDMI CEC funcs */ +#ifdef CONFIG_OMAP4_DSS_HDMI_CEC +void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa); +void hdmi4_cec_irq(struct hdmi_core_data *core); +int hdmi4_cec_init(struct platform_device *pdev, struct hdmi_core_data *core, + struct hdmi_wp_data *wp); +void hdmi4_cec_uninit(struct hdmi_core_data *core); +#else +static inline void hdmi4_cec_set_phys_addr(struct hdmi_core_data *core, u16 pa) +{ +} + +static inline void hdmi4_cec_irq(struct hdmi_core_data *core) +{ +} + +static inline int hdmi4_cec_init(struct platform_device *pdev, + struct hdmi_core_data *core, + struct hdmi_wp_data *wp) +{ + return 0; +} + +static inline void hdmi4_cec_uninit(struct hdmi_core_data *core) +{ +} +#endif + +#endif diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c index 365cf07daa01..62e451162d96 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.c @@ -208,9 +208,9 @@ static void hdmi_core_init(struct hdmi_core_video_config *video_cfg) video_cfg->tclk_sel_clkmult = HDMI_FPLL10IDCK; } -static void hdmi_core_powerdown_disable(struct hdmi_core_data *core) +void hdmi4_core_powerdown_disable(struct hdmi_core_data *core) { - DSSDBG("Enter hdmi_core_powerdown_disable\n"); + DSSDBG("Enter hdmi4_core_powerdown_disable\n"); REG_FLD_MOD(core->base, HDMI_CORE_SYS_SYS_CTRL1, 0x1, 0, 0); } @@ -335,9 +335,6 @@ void hdmi4_configure(struct hdmi_core_data *core, */ hdmi_core_swreset_assert(core); - /* power down off */ - hdmi_core_powerdown_disable(core); - v_core_cfg.pkt_mode = HDMI_PACKETMODE24BITPERPIXEL; v_core_cfg.hdmi_dvi = cfg->hdmi_dvi_mode; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h index a069f96ec6f6..b6ab579e44d2 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4_core.h @@ -266,6 +266,10 @@ void hdmi4_configure(struct hdmi_core_data *core, struct hdmi_wp_data *wp, void hdmi4_core_dump(struct hdmi_core_data *core, struct seq_file *s); int hdmi4_core_init(struct platform_device *pdev, struct hdmi_core_data *core); +int hdmi4_core_enable(struct omap_dss_device *dssdev); +void hdmi4_core_disable(struct omap_dss_device *dssdev); +void hdmi4_core_powerdown_disable(struct hdmi_core_data *core); + int hdmi4_audio_start(struct hdmi_core_data *core, struct hdmi_wp_data *wp); void hdmi4_audio_stop(struct hdmi_core_data *core, struct hdmi_wp_data *wp); int hdmi4_audio_config(struct hdmi_core_data *core, struct hdmi_wp_data *wp, diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 47a331670963..990422b35784 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -395,6 +395,7 @@ struct omapdss_hdmi_ops { struct videomode *vm); int (*read_edid)(struct omap_dss_device *dssdev, u8 *buf, int len); + void (*lost_hotplug)(struct omap_dss_device *dssdev); bool (*detect)(struct omap_dss_device *dssdev); int (*register_hpd_cb)(struct omap_dss_device *dssdev, diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index 74fc9362ecf9..c0fb52c6d4ca 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -219,7 +219,7 @@ int qxl_garbage_collect(struct qxl_device *qdev) union qxl_release_info *info; while (qxl_ring_pop(qdev->release_ring, &id)) { - QXL_INFO(qdev, "popped %lld\n", id); + DRM_DEBUG_DRIVER("popped %lld\n", id); while (id) { release = qxl_release_from_id_locked(qdev, id); if (release == NULL) @@ -229,8 +229,8 @@ int qxl_garbage_collect(struct qxl_device *qdev) next_id = info->next; qxl_release_unmap(qdev, release, info); - QXL_INFO(qdev, "popped %lld, next %lld\n", id, - next_id); + DRM_DEBUG_DRIVER("popped %lld, next %lld\n", id, + next_id); switch (release->type) { case QXL_RELEASE_DRAWABLE: @@ -248,7 +248,7 @@ int qxl_garbage_collect(struct qxl_device *qdev) } } - QXL_INFO(qdev, "%s: %d\n", __func__, i); + DRM_DEBUG_DRIVER("%d\n", i); return i; } @@ -381,17 +381,19 @@ void qxl_io_create_primary(struct qxl_device *qdev, { struct qxl_surface_create *create; - QXL_INFO(qdev, "%s: qdev %p, ram_header %p\n", __func__, qdev, - qdev->ram_header); + DRM_DEBUG_DRIVER("qdev %p, ram_header %p\n", qdev, qdev->ram_header); create = &qdev->ram_header->create_surface; create->format = bo->surf.format; create->width = bo->surf.width; create->height = bo->surf.height; create->stride = bo->surf.stride; - create->mem = qxl_bo_physical_address(qdev, bo, offset); + if (bo->shadow) { + create->mem = qxl_bo_physical_address(qdev, bo->shadow, offset); + } else { + create->mem = qxl_bo_physical_address(qdev, bo, offset); + } - QXL_INFO(qdev, "%s: mem = %llx, from %p\n", __func__, create->mem, - bo->kptr); + DRM_DEBUG_DRIVER("mem = %llx, from %p\n", create->mem, bo->kptr); create->flags = QXL_SURF_FLAG_KEEP_DATA; create->type = QXL_SURF_TYPE_PRIMARY; @@ -401,7 +403,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id) { - QXL_INFO(qdev, "qxl_memslot_add %d\n", id); + DRM_DEBUG_DRIVER("qxl_memslot_add %d\n", id); wait_for_io_cmd(qdev, id, QXL_IO_MEMSLOT_ADD_ASYNC); } diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index afbf50d0c08f..4756b3c9bf2c 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -305,7 +305,9 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = { void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb) { struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb); + struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj); + WARN_ON(bo->shadow); drm_gem_object_unreference_unlocked(qxl_fb->obj); drm_framebuffer_cleanup(fb); kfree(qxl_fb); @@ -508,6 +510,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, .x2 = qfb->base.width, .y2 = qfb->base.height }; + bool same_shadow = false; if (old_state->fb) { qfb_old = to_qxl_framebuffer(old_state->fb); @@ -519,15 +522,23 @@ static void qxl_primary_atomic_update(struct drm_plane *plane, if (bo == bo_old) return; + if (bo_old && bo_old->shadow && bo->shadow && + bo_old->shadow == bo->shadow) { + same_shadow = true; + } + if (bo_old && bo_old->is_primary) { - qxl_io_destroy_primary(qdev); + if (!same_shadow) + qxl_io_destroy_primary(qdev); bo_old->is_primary = false; } if (!bo->is_primary) { - qxl_io_create_primary(qdev, 0, bo); + if (!same_shadow) + qxl_io_create_primary(qdev, 0, bo); bo->is_primary = true; } + qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1); } @@ -679,8 +690,9 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane, static int qxl_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { + struct qxl_device *qdev = plane->dev->dev_private; struct drm_gem_object *obj; - struct qxl_bo *user_bo; + struct qxl_bo *user_bo, *old_bo = NULL; int ret; if (!new_state->fb) @@ -689,6 +701,32 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane, obj = to_qxl_framebuffer(new_state->fb)->obj; user_bo = gem_to_qxl_bo(obj); + if (plane->type == DRM_PLANE_TYPE_PRIMARY && + user_bo->is_dumb && !user_bo->shadow) { + if (plane->state->fb) { + obj = to_qxl_framebuffer(plane->state->fb)->obj; + old_bo = gem_to_qxl_bo(obj); + } + if (old_bo && old_bo->shadow && + user_bo->gem_base.size == old_bo->gem_base.size && + plane->state->crtc == new_state->crtc && + plane->state->crtc_w == new_state->crtc_w && + plane->state->crtc_h == new_state->crtc_h && + plane->state->src_x == new_state->src_x && + plane->state->src_y == new_state->src_y && + plane->state->src_w == new_state->src_w && + plane->state->src_h == new_state->src_h && + plane->state->rotation == new_state->rotation && + plane->state->zpos == new_state->zpos) { + drm_gem_object_get(&old_bo->shadow->gem_base); + user_bo->shadow = old_bo->shadow; + } else { + qxl_bo_create(qdev, user_bo->gem_base.size, + true, true, QXL_GEM_DOMAIN_VRAM, NULL, + &user_bo->shadow); + } + } + ret = qxl_bo_pin(user_bo, QXL_GEM_DOMAIN_CPU, NULL); if (ret) return ret; @@ -713,6 +751,11 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane, obj = to_qxl_framebuffer(old_state->fb)->obj; user_bo = gem_to_qxl_bo(obj); qxl_bo_unpin(user_bo); + + if (user_bo->shadow && !user_bo->is_primary) { + drm_gem_object_put_unlocked(&user_bo->shadow->gem_base); + user_bo->shadow = NULL; + } } static const uint32_t qxl_cursor_plane_formats[] = { diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 3397a1907336..08752c0ffb35 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -62,33 +62,9 @@ #define QXL_DEBUGFS_MAX_COMPONENTS 32 -extern int qxl_log_level; extern int qxl_num_crtc; extern int qxl_max_ioctls; -enum { - QXL_INFO_LEVEL = 1, - QXL_DEBUG_LEVEL = 2, -}; - -#define QXL_INFO(qdev, fmt, ...) do { \ - if (qxl_log_level >= QXL_INFO_LEVEL) { \ - qxl_io_log(qdev, fmt, __VA_ARGS__); \ - } \ - } while (0) -#define QXL_DEBUG(qdev, fmt, ...) do { \ - if (qxl_log_level >= QXL_DEBUG_LEVEL) { \ - qxl_io_log(qdev, fmt, __VA_ARGS__); \ - } \ - } while (0) -#define QXL_INFO_ONCE(qdev, fmt, ...) do { \ - static int done; \ - if (!done) { \ - done = 1; \ - QXL_INFO(qdev, fmt, __VA_ARGS__); \ - } \ - } while (0) - #define DRM_FILE_OFFSET 0x100000000ULL #define DRM_FILE_PAGE_OFFSET (DRM_FILE_OFFSET >> PAGE_SHIFT) @@ -113,6 +89,8 @@ struct qxl_bo { /* Constant after initialization */ struct drm_gem_object gem_base; bool is_primary; /* is this now a primary surface */ + bool is_dumb; + struct qxl_bo *shadow; bool hw_surf_alloc; struct qxl_surface surf; uint32_t surface_id; @@ -351,7 +329,7 @@ int qxl_check_idle(struct qxl_ring *ring); static inline void * qxl_fb_virtual_address(struct qxl_device *qdev, unsigned long physical) { - QXL_INFO(qdev, "not implemented (%lu)\n", physical); + DRM_DEBUG_DRIVER("not implemented (%lu)\n", physical); return 0; } diff --git a/drivers/gpu/drm/qxl/qxl_dumb.c b/drivers/gpu/drm/qxl/qxl_dumb.c index 5e65d5d2d937..11085ab01374 100644 --- a/drivers/gpu/drm/qxl/qxl_dumb.c +++ b/drivers/gpu/drm/qxl/qxl_dumb.c @@ -63,6 +63,7 @@ int qxl_mode_dumb_create(struct drm_file *file_priv, &handle); if (r) return r; + qobj->is_dumb = true; args->pitch = pitch; args->handle = handle; return 0; diff --git a/drivers/gpu/drm/qxl/qxl_fb.c b/drivers/gpu/drm/qxl/qxl_fb.c index 844c4a31ca13..23af3e352673 100644 --- a/drivers/gpu/drm/qxl/qxl_fb.c +++ b/drivers/gpu/drm/qxl/qxl_fb.c @@ -240,18 +240,15 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev, return ret; qbo = gem_to_qxl_bo(gobj); - QXL_INFO(qdev, "%s: %dx%d %d\n", __func__, mode_cmd.width, - mode_cmd.height, mode_cmd.pitches[0]); + DRM_DEBUG_DRIVER("%dx%d %d\n", mode_cmd.width, + mode_cmd.height, mode_cmd.pitches[0]); shadow = vmalloc(mode_cmd.pitches[0] * mode_cmd.height); /* TODO: what's the usual response to memory allocation errors? */ BUG_ON(!shadow); - QXL_INFO(qdev, - "surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n", - qxl_bo_gpu_offset(qbo), - qxl_bo_mmap_offset(qbo), - qbo->kptr, - shadow); + DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n", + qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo), + qbo->kptr, shadow); size = mode_cmd.pitches[0] * mode_cmd.height; info = drm_fb_helper_alloc_fbi(&qfbdev->helper); diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index e6ec845b5be0..a6da6fa6ad58 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -154,7 +154,7 @@ qxl_release_alloc(struct qxl_device *qdev, int type, return handle; } *ret = release; - QXL_INFO(qdev, "allocated release %d\n", handle); + DRM_DEBUG_DRIVER("allocated release %d\n", handle); release->id = handle; return handle; } @@ -179,8 +179,7 @@ void qxl_release_free(struct qxl_device *qdev, struct qxl_release *release) { - QXL_INFO(qdev, "release %d, type %d\n", release->id, - release->type); + DRM_DEBUG_DRIVER("release %d, type %d\n", release->id, release->type); if (release->surface_release_id) qxl_surface_id_dealloc(qdev, release->surface_release_id); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 0f50c0b25a58..586ecd6e0e45 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -133,8 +133,8 @@ int qxl_mmap(struct file *filp, struct vm_area_struct *vma) "filp->private_data->minor->dev->dev_private == NULL\n"); return -EINVAL; } - QXL_INFO(qdev, "%s: filp->private_data = 0x%p, vma->vm_pgoff = %lx\n", - __func__, filp->private_data, vma->vm_pgoff); + DRM_DEBUG_DRIVER("filp->private_data = 0x%p, vma->vm_pgoff = %lx\n", + filp->private_data, vma->vm_pgoff); r = ttm_bo_mmap(filp, vma, &qdev->mman.bdev); if (unlikely(r != 0)) diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index be16c6390216..cf3e5985e3e7 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -102,8 +102,7 @@ radeon-y += \ radeon-y += \ radeon_vce.o \ vce_v1_0.o \ - vce_v2_0.o \ - radeon_kfd.o + vce_v2_0.o radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o radeon-$(CONFIG_ACPI) += radeon_acpi.o diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index 432cb46f6a34..3e798593e042 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -45,34 +45,32 @@ static char *pre_emph_names[] = { /***** radeon AUX functions *****/ -/* Atom needs data in little endian format - * so swap as appropriate when copying data to - * or from atom. Note that atom operates on - * dw units. +/* Atom needs data in little endian format so swap as appropriate when copying + * data to or from atom. Note that atom operates on dw units. + * + * Use to_le=true when sending data to atom and provide at least + * ALIGN(num_bytes,4) bytes in the dst buffer. + * + * Use to_le=false when receiving data from atom and provide ALIGN(num_bytes,4) + * byes in the src buffer. */ void radeon_atom_copy_swap(u8 *dst, u8 *src, u8 num_bytes, bool to_le) { #ifdef __BIG_ENDIAN - u8 src_tmp[20], dst_tmp[20]; /* used for byteswapping */ - u32 *dst32, *src32; + u32 src_tmp[5], dst_tmp[5]; int i; + u8 align_num_bytes = ALIGN(num_bytes, 4); - memcpy(src_tmp, src, num_bytes); - src32 = (u32 *)src_tmp; - dst32 = (u32 *)dst_tmp; if (to_le) { - for (i = 0; i < ((num_bytes + 3) / 4); i++) - dst32[i] = cpu_to_le32(src32[i]); - memcpy(dst, dst_tmp, num_bytes); + memcpy(src_tmp, src, num_bytes); + for (i = 0; i < align_num_bytes / 4; i++) + dst_tmp[i] = cpu_to_le32(src_tmp[i]); + memcpy(dst, dst_tmp, align_num_bytes); } else { - u8 dws = num_bytes & ~3; - for (i = 0; i < ((num_bytes + 3) / 4); i++) - dst32[i] = le32_to_cpu(src32[i]); - memcpy(dst, dst_tmp, dws); - if (num_bytes % 4) { - for (i = 0; i < (num_bytes % 4); i++) - dst[dws+i] = dst_tmp[dws+i]; - } + memcpy(src_tmp, src, align_num_bytes); + for (i = 0; i < align_num_bytes / 4; i++) + dst_tmp[i] = le32_to_cpu(src_tmp[i]); + memcpy(dst, dst_tmp, num_bytes); } #else memcpy(dst, src, num_bytes); @@ -304,10 +302,10 @@ static int convert_bpc_to_bpp(int bpc) /***** radeon specific DP functions *****/ -int radeon_dp_get_dp_link_config(struct drm_connector *connector, - const u8 dpcd[DP_DPCD_SIZE], - unsigned pix_clock, - unsigned *dp_lanes, unsigned *dp_rate) +static int radeon_dp_get_dp_link_config(struct drm_connector *connector, + const u8 dpcd[DP_DPCD_SIZE], + unsigned pix_clock, + unsigned *dp_lanes, unsigned *dp_rate) { int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); static const unsigned link_rates[3] = { 162000, 270000, 540000 }; diff --git a/drivers/gpu/drm/radeon/ci_dpm.c b/drivers/gpu/drm/radeon/ci_dpm.c index c97fbb2ab48b..7e1b04dc5593 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.c +++ b/drivers/gpu/drm/radeon/ci_dpm.c @@ -184,6 +184,7 @@ static int ci_set_overdrive_target_tdp(struct radeon_device *rdev, u32 target_tdp); static int ci_update_uvd_dpm(struct radeon_device *rdev, bool gate); +static PPSMC_Result ci_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg); static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev, PPSMC_Msg msg, u32 parameter); @@ -1651,6 +1652,27 @@ static int ci_notify_hw_of_power_source(struct radeon_device *rdev, } #endif +static PPSMC_Result ci_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg) +{ + u32 tmp; + int i; + + if (!ci_is_smc_running(rdev)) + return PPSMC_Result_Failed; + + WREG32(SMC_MESSAGE_0, msg); + + for (i = 0; i < rdev->usec_timeout; i++) { + tmp = RREG32(SMC_RESP_0); + if (tmp != 0) + break; + udelay(1); + } + tmp = RREG32(SMC_RESP_0); + + return (PPSMC_Result)tmp; +} + static PPSMC_Result ci_send_msg_to_smc_with_parameter(struct radeon_device *rdev, PPSMC_Msg msg, u32 parameter) { diff --git a/drivers/gpu/drm/radeon/ci_dpm.h b/drivers/gpu/drm/radeon/ci_dpm.h index 723220ffbea2..dff2a63df38f 100644 --- a/drivers/gpu/drm/radeon/ci_dpm.h +++ b/drivers/gpu/drm/radeon/ci_dpm.h @@ -330,7 +330,6 @@ int ci_program_jump_on_start(struct radeon_device *rdev); void ci_stop_smc_clock(struct radeon_device *rdev); void ci_start_smc_clock(struct radeon_device *rdev); bool ci_is_smc_running(struct radeon_device *rdev); -PPSMC_Result ci_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg); PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev); int ci_load_smc_ucode(struct radeon_device *rdev, u32 limit); int ci_read_smc_sram_dword(struct radeon_device *rdev, diff --git a/drivers/gpu/drm/radeon/ci_smc.c b/drivers/gpu/drm/radeon/ci_smc.c index 3356a21d97ec..371121913756 100644 --- a/drivers/gpu/drm/radeon/ci_smc.c +++ b/drivers/gpu/drm/radeon/ci_smc.c @@ -163,27 +163,6 @@ bool ci_is_smc_running(struct radeon_device *rdev) return false; } -PPSMC_Result ci_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg) -{ - u32 tmp; - int i; - - if (!ci_is_smc_running(rdev)) - return PPSMC_Result_Failed; - - WREG32(SMC_MESSAGE_0, msg); - - for (i = 0; i < rdev->usec_timeout; i++) { - tmp = RREG32(SMC_RESP_0); - if (tmp != 0) - break; - udelay(1); - } - tmp = RREG32(SMC_RESP_0); - - return (PPSMC_Result)tmp; -} - #if 0 PPSMC_Result ci_wait_for_smc_inactive(struct radeon_device *rdev) { diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 3cb6c55b268d..898f9a078830 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -33,7 +33,6 @@ #include "cik_blit_shaders.h" #include "radeon_ucode.h" #include "clearstate_ci.h" -#include "radeon_kfd.h" #define SH_MEM_CONFIG_GFX_DEFAULT \ ALIGNMENT_MODE(SH_MEM_ALIGNMENT_MODE_UNALIGNED) @@ -5684,10 +5683,9 @@ int cik_vm_init(struct radeon_device *rdev) /* * number of VMs * VMID 0 is reserved for System - * radeon graphics/compute will use VMIDs 1-7 - * amdkfd will use VMIDs 8-15 + * radeon graphics/compute will use VMIDs 1-15 */ - rdev->vm_manager.nvm = RADEON_NUM_OF_VMIDS; + rdev->vm_manager.nvm = 16; /* base offset of vram pages */ if (rdev->flags & RADEON_IS_IGP) { u64 tmp = RREG32(MC_VM_FB_OFFSET); @@ -7589,9 +7587,6 @@ restart_ih: /* wptr/rptr are in bytes! */ ring_index = rptr / 4; - radeon_kfd_interrupt(rdev, - (const void *) &rdev->ih.ring[ring_index]); - src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff; src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff; ring_id = le32_to_cpu(rdev->ih.ring[ring_index + 2]) & 0xff; @@ -8486,10 +8481,6 @@ static int cik_startup(struct radeon_device *rdev) if (r) return r; - r = radeon_kfd_resume(rdev); - if (r) - return r; - return 0; } @@ -8538,7 +8529,6 @@ int cik_resume(struct radeon_device *rdev) */ int cik_suspend(struct radeon_device *rdev) { - radeon_kfd_suspend(rdev); radeon_pm_suspend(rdev); radeon_audio_fini(rdev); radeon_vm_manager_fini(rdev); diff --git a/drivers/gpu/drm/radeon/cikd.h b/drivers/gpu/drm/radeon/cikd.h index e21015475ed5..cda16fcd43bb 100644 --- a/drivers/gpu/drm/radeon/cikd.h +++ b/drivers/gpu/drm/radeon/cikd.h @@ -30,8 +30,6 @@ #define CIK_RB_BITMAP_WIDTH_PER_SH 2 #define HAWAII_RB_BITMAP_WIDTH_PER_SH 4 -#define RADEON_NUM_OF_VMIDS 8 - /* DIDT IND registers */ #define DIDT_SQ_CTRL0 0x0 # define DIDT_CTRL_EN (1 << 0) diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c31e660e35db..7d39ed63e5be 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -1456,7 +1456,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p) header = radeon_get_ib_value(p, h_idx); crtc_id = radeon_get_ib_value(p, h_idx + 5); reg = R100_CP_PACKET0_GET_REG(header); - crtc = drm_crtc_find(p->rdev->ddev, crtc_id); + crtc = drm_crtc_find(p->rdev->ddev, p->filp, crtc_id); if (!crtc) { DRM_ERROR("cannot find crtc %d\n", crtc_id); return -ENOENT; diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 97fd58e97043..c96b31950ca7 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -887,7 +887,7 @@ int r600_cs_common_vline_parse(struct radeon_cs_parser *p, crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1); reg = R600_CP_PACKET0_GET_REG(header); - crtc = drm_crtc_find(p->rdev->ddev, crtc_id); + crtc = drm_crtc_find(p->rdev->ddev, p->filp, crtc_id); if (!crtc) { DRM_ERROR("cannot find crtc %d\n", crtc_id); return -ENOENT; diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 8cbaeec090c9..a8e546569858 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -2456,9 +2456,6 @@ struct radeon_device { u64 vram_pin_size; u64 gart_pin_size; - /* amdkfd interface */ - struct kfd_dev *kfd; - struct mutex mn_lock; DECLARE_HASHTABLE(mn_hash, 7); }; diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c index 9e45127329d7..5012f5e47a1e 100644 --- a/drivers/gpu/drm/radeon/radeon_connectors.c +++ b/drivers/gpu/drm/radeon/radeon_connectors.c @@ -263,7 +263,7 @@ radeon_connector_update_scratch_regs(struct drm_connector *connector, enum drm_c if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -290,7 +290,7 @@ static struct drm_encoder *radeon_find_encoder(struct drm_connector *connector, if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -403,7 +403,7 @@ static struct drm_encoder *radeon_best_single_encoder(struct drm_connector *conn int enc_id = connector->encoder_ids[0]; /* pick the encoder ids */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } @@ -1367,7 +1367,7 @@ radeon_dvi_detect(struct drm_connector *connector, bool force) if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -1453,7 +1453,7 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -1472,7 +1472,7 @@ static struct drm_encoder *radeon_dvi_encoder(struct drm_connector *connector) /* then check use digitial */ /* pick the first one */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } @@ -1619,7 +1619,7 @@ u16 radeon_connector_encoder_get_dp_bridge_encoder_id(struct drm_connector *conn if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; @@ -1648,7 +1648,7 @@ static bool radeon_connector_encoder_is_hbr2(struct drm_connector *connector) if (connector->encoder_ids[i] == 0) break; - encoder = drm_encoder_find(connector->dev, connector->encoder_ids[i]); + encoder = drm_encoder_find(connector->dev, NULL, connector->encoder_ids[i]); if (!encoder) continue; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index f4becad0a78c..31dd04f6baa1 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -43,7 +43,6 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_crtc_helper.h> -#include "radeon_kfd.h" /* * KMS wrapper. @@ -338,14 +337,6 @@ static int radeon_pci_probe(struct pci_dev *pdev, { int ret; - /* - * Initialize amdkfd before starting radeon. If it was not loaded yet, - * defer radeon probing - */ - ret = radeon_kfd_init(); - if (ret == -EPROBE_DEFER) - return ret; - if (vga_switcheroo_client_probe_defer(pdev)) return -EPROBE_DEFER; @@ -645,7 +636,6 @@ static int __init radeon_init(void) static void __exit radeon_exit(void) { - radeon_kfd_fini(); pci_unregister_driver(pdriver); radeon_unregister_atpx_handler(); } diff --git a/drivers/gpu/drm/radeon/radeon_kfd.c b/drivers/gpu/drm/radeon/radeon_kfd.c deleted file mode 100644 index a2ac8ac0930d..000000000000 --- a/drivers/gpu/drm/radeon/radeon_kfd.c +++ /dev/null @@ -1,901 +0,0 @@ -/* - * Copyright 2014 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION 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 <linux/module.h> -#include <linux/fdtable.h> -#include <linux/uaccess.h> -#include <drm/drmP.h> -#include "radeon.h" -#include "cikd.h" -#include "cik_reg.h" -#include "radeon_kfd.h" -#include "radeon_ucode.h" -#include <linux/firmware.h> -#include "cik_structs.h" - -#define CIK_PIPE_PER_MEC (4) - -static const uint32_t watchRegs[MAX_WATCH_ADDRESSES * ADDRESS_WATCH_REG_MAX] = { - TCP_WATCH0_ADDR_H, TCP_WATCH0_ADDR_L, TCP_WATCH0_CNTL, - TCP_WATCH1_ADDR_H, TCP_WATCH1_ADDR_L, TCP_WATCH1_CNTL, - TCP_WATCH2_ADDR_H, TCP_WATCH2_ADDR_L, TCP_WATCH2_CNTL, - TCP_WATCH3_ADDR_H, TCP_WATCH3_ADDR_L, TCP_WATCH3_CNTL -}; - -struct kgd_mem { - struct radeon_bo *bo; - uint64_t gpu_addr; - void *cpu_ptr; -}; - - -static int alloc_gtt_mem(struct kgd_dev *kgd, size_t size, - void **mem_obj, uint64_t *gpu_addr, - void **cpu_ptr); - -static void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj); - -static uint64_t get_vmem_size(struct kgd_dev *kgd); -static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd); - -static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd); - -static int alloc_pasid(unsigned int bits); -static void free_pasid(unsigned int pasid); - -static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type); - -/* - * Register access functions - */ - -static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid, - uint32_t sh_mem_config, uint32_t sh_mem_ape1_base, - uint32_t sh_mem_ape1_limit, uint32_t sh_mem_bases); - -static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid, - unsigned int vmid); - -static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, - uint32_t hpd_size, uint64_t hpd_gpu_addr); -static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id); -static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, - uint32_t queue_id, uint32_t __user *wptr, - uint32_t wptr_shift, uint32_t wptr_mask, - struct mm_struct *mm); -static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd); -static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address, - uint32_t pipe_id, uint32_t queue_id); - -static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t reset_type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id); -static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd); -static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd, - unsigned int timeout); -static int kgd_address_watch_disable(struct kgd_dev *kgd); -static int kgd_address_watch_execute(struct kgd_dev *kgd, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo); -static int kgd_wave_control_execute(struct kgd_dev *kgd, - uint32_t gfx_index_val, - uint32_t sq_cmd); -static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd, - unsigned int watch_point_id, - unsigned int reg_offset); - -static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd, uint8_t vmid); -static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd, - uint8_t vmid); -static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid); - -static const struct kfd2kgd_calls kfd2kgd = { - .init_gtt_mem_allocation = alloc_gtt_mem, - .free_gtt_mem = free_gtt_mem, - .get_vmem_size = get_vmem_size, - .get_gpu_clock_counter = get_gpu_clock_counter, - .get_max_engine_clock_in_mhz = get_max_engine_clock_in_mhz, - .alloc_pasid = alloc_pasid, - .free_pasid = free_pasid, - .program_sh_mem_settings = kgd_program_sh_mem_settings, - .set_pasid_vmid_mapping = kgd_set_pasid_vmid_mapping, - .init_pipeline = kgd_init_pipeline, - .init_interrupts = kgd_init_interrupts, - .hqd_load = kgd_hqd_load, - .hqd_sdma_load = kgd_hqd_sdma_load, - .hqd_is_occupied = kgd_hqd_is_occupied, - .hqd_sdma_is_occupied = kgd_hqd_sdma_is_occupied, - .hqd_destroy = kgd_hqd_destroy, - .hqd_sdma_destroy = kgd_hqd_sdma_destroy, - .address_watch_disable = kgd_address_watch_disable, - .address_watch_execute = kgd_address_watch_execute, - .wave_control_execute = kgd_wave_control_execute, - .address_watch_get_offset = kgd_address_watch_get_offset, - .get_atc_vmid_pasid_mapping_pasid = get_atc_vmid_pasid_mapping_pasid, - .get_atc_vmid_pasid_mapping_valid = get_atc_vmid_pasid_mapping_valid, - .write_vmid_invalidate_request = write_vmid_invalidate_request, - .get_fw_version = get_fw_version -}; - -static const struct kgd2kfd_calls *kgd2kfd; - -int radeon_kfd_init(void) -{ - int ret; - -#if defined(CONFIG_HSA_AMD_MODULE) - int (*kgd2kfd_init_p)(unsigned, const struct kgd2kfd_calls**); - - kgd2kfd_init_p = symbol_request(kgd2kfd_init); - - if (kgd2kfd_init_p == NULL) - return -ENOENT; - - ret = kgd2kfd_init_p(KFD_INTERFACE_VERSION, &kgd2kfd); - if (ret) { - symbol_put(kgd2kfd_init); - kgd2kfd = NULL; - } - -#elif defined(CONFIG_HSA_AMD) - ret = kgd2kfd_init(KFD_INTERFACE_VERSION, &kgd2kfd); - if (ret) - kgd2kfd = NULL; - -#else - ret = -ENOENT; -#endif - - return ret; -} - -void radeon_kfd_fini(void) -{ - if (kgd2kfd) { - kgd2kfd->exit(); - symbol_put(kgd2kfd_init); - } -} - -void radeon_kfd_device_probe(struct radeon_device *rdev) -{ - if (kgd2kfd) - rdev->kfd = kgd2kfd->probe((struct kgd_dev *)rdev, - rdev->pdev, &kfd2kgd); -} - -void radeon_kfd_device_init(struct radeon_device *rdev) -{ - int i, queue, pipe, mec; - - if (rdev->kfd) { - struct kgd2kfd_shared_resources gpu_resources = { - .compute_vmid_bitmap = 0xFF00, - .num_pipe_per_mec = 4, - .num_queue_per_pipe = 8 - }; - - bitmap_zero(gpu_resources.queue_bitmap, KGD_MAX_QUEUES); - - for (i = 0; i < KGD_MAX_QUEUES; ++i) { - queue = i % gpu_resources.num_queue_per_pipe; - pipe = (i / gpu_resources.num_queue_per_pipe) - % gpu_resources.num_pipe_per_mec; - mec = (i / gpu_resources.num_queue_per_pipe) - / gpu_resources.num_pipe_per_mec; - - if (mec == 0 && pipe > 0) - set_bit(i, gpu_resources.queue_bitmap); - } - - radeon_doorbell_get_kfd_info(rdev, - &gpu_resources.doorbell_physical_address, - &gpu_resources.doorbell_aperture_size, - &gpu_resources.doorbell_start_offset); - - kgd2kfd->device_init(rdev->kfd, &gpu_resources); - } -} - -void radeon_kfd_device_fini(struct radeon_device *rdev) -{ - if (rdev->kfd) { - kgd2kfd->device_exit(rdev->kfd); - rdev->kfd = NULL; - } -} - -void radeon_kfd_interrupt(struct radeon_device *rdev, const void *ih_ring_entry) -{ - if (rdev->kfd) - kgd2kfd->interrupt(rdev->kfd, ih_ring_entry); -} - -void radeon_kfd_suspend(struct radeon_device *rdev) -{ - if (rdev->kfd) - kgd2kfd->suspend(rdev->kfd); -} - -int radeon_kfd_resume(struct radeon_device *rdev) -{ - int r = 0; - - if (rdev->kfd) - r = kgd2kfd->resume(rdev->kfd); - - return r; -} - -static int alloc_gtt_mem(struct kgd_dev *kgd, size_t size, - void **mem_obj, uint64_t *gpu_addr, - void **cpu_ptr) -{ - struct radeon_device *rdev = (struct radeon_device *)kgd; - struct kgd_mem **mem = (struct kgd_mem **) mem_obj; - int r; - - BUG_ON(kgd == NULL); - BUG_ON(gpu_addr == NULL); - BUG_ON(cpu_ptr == NULL); - - *mem = kmalloc(sizeof(struct kgd_mem), GFP_KERNEL); - if ((*mem) == NULL) - return -ENOMEM; - - r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT, - RADEON_GEM_GTT_WC, NULL, NULL, &(*mem)->bo); - if (r) { - dev_err(rdev->dev, - "failed to allocate BO for amdkfd (%d)\n", r); - return r; - } - - /* map the buffer */ - r = radeon_bo_reserve((*mem)->bo, true); - if (r) { - dev_err(rdev->dev, "(%d) failed to reserve bo for amdkfd\n", r); - goto allocate_mem_reserve_bo_failed; - } - - r = radeon_bo_pin((*mem)->bo, RADEON_GEM_DOMAIN_GTT, - &(*mem)->gpu_addr); - if (r) { - dev_err(rdev->dev, "(%d) failed to pin bo for amdkfd\n", r); - goto allocate_mem_pin_bo_failed; - } - *gpu_addr = (*mem)->gpu_addr; - - r = radeon_bo_kmap((*mem)->bo, &(*mem)->cpu_ptr); - if (r) { - dev_err(rdev->dev, - "(%d) failed to map bo to kernel for amdkfd\n", r); - goto allocate_mem_kmap_bo_failed; - } - *cpu_ptr = (*mem)->cpu_ptr; - - radeon_bo_unreserve((*mem)->bo); - - return 0; - -allocate_mem_kmap_bo_failed: - radeon_bo_unpin((*mem)->bo); -allocate_mem_pin_bo_failed: - radeon_bo_unreserve((*mem)->bo); -allocate_mem_reserve_bo_failed: - radeon_bo_unref(&(*mem)->bo); - - return r; -} - -static void free_gtt_mem(struct kgd_dev *kgd, void *mem_obj) -{ - struct kgd_mem *mem = (struct kgd_mem *) mem_obj; - - BUG_ON(mem == NULL); - - radeon_bo_reserve(mem->bo, true); - radeon_bo_kunmap(mem->bo); - radeon_bo_unpin(mem->bo); - radeon_bo_unreserve(mem->bo); - radeon_bo_unref(&(mem->bo)); - kfree(mem); -} - -static uint64_t get_vmem_size(struct kgd_dev *kgd) -{ - struct radeon_device *rdev = (struct radeon_device *)kgd; - - BUG_ON(kgd == NULL); - - return rdev->mc.real_vram_size; -} - -static uint64_t get_gpu_clock_counter(struct kgd_dev *kgd) -{ - struct radeon_device *rdev = (struct radeon_device *)kgd; - - return rdev->asic->get_gpu_clock_counter(rdev); -} - -static uint32_t get_max_engine_clock_in_mhz(struct kgd_dev *kgd) -{ - struct radeon_device *rdev = (struct radeon_device *)kgd; - - /* The sclk is in quantas of 10kHz */ - return rdev->pm.dpm.dyn_state.max_clock_voltage_on_ac.sclk / 100; -} - -/* - * PASID manager - */ -static DEFINE_IDA(pasid_ida); - -int alloc_pasid(unsigned int bits) -{ - int pasid = -EINVAL; - - for (bits = min(bits, 31U); bits > 0; bits--) { - pasid = ida_simple_get(&pasid_ida, - 1U << (bits - 1), 1U << bits, - GFP_KERNEL); - if (pasid != -ENOSPC) - break; - } - - return pasid; -} - -void free_pasid(unsigned int pasid) -{ - ida_simple_remove(&pasid_ida, pasid); -} - -static inline struct radeon_device *get_radeon_device(struct kgd_dev *kgd) -{ - return (struct radeon_device *)kgd; -} - -static void write_register(struct kgd_dev *kgd, uint32_t offset, uint32_t value) -{ - struct radeon_device *rdev = get_radeon_device(kgd); - - writel(value, (void __iomem *)(rdev->rmmio + offset)); -} - -static uint32_t read_register(struct kgd_dev *kgd, uint32_t offset) -{ - struct radeon_device *rdev = get_radeon_device(kgd); - - return readl((void __iomem *)(rdev->rmmio + offset)); -} - -static void lock_srbm(struct kgd_dev *kgd, uint32_t mec, uint32_t pipe, - uint32_t queue, uint32_t vmid) -{ - struct radeon_device *rdev = get_radeon_device(kgd); - uint32_t value = PIPEID(pipe) | MEID(mec) | VMID(vmid) | QUEUEID(queue); - - mutex_lock(&rdev->srbm_mutex); - write_register(kgd, SRBM_GFX_CNTL, value); -} - -static void unlock_srbm(struct kgd_dev *kgd) -{ - struct radeon_device *rdev = get_radeon_device(kgd); - - write_register(kgd, SRBM_GFX_CNTL, 0); - mutex_unlock(&rdev->srbm_mutex); -} - -static void acquire_queue(struct kgd_dev *kgd, uint32_t pipe_id, - uint32_t queue_id) -{ - uint32_t mec = (++pipe_id / CIK_PIPE_PER_MEC) + 1; - uint32_t pipe = (pipe_id % CIK_PIPE_PER_MEC); - - lock_srbm(kgd, mec, pipe, queue_id, 0); -} - -static void release_queue(struct kgd_dev *kgd) -{ - unlock_srbm(kgd); -} - -static void kgd_program_sh_mem_settings(struct kgd_dev *kgd, uint32_t vmid, - uint32_t sh_mem_config, - uint32_t sh_mem_ape1_base, - uint32_t sh_mem_ape1_limit, - uint32_t sh_mem_bases) -{ - lock_srbm(kgd, 0, 0, 0, vmid); - - write_register(kgd, SH_MEM_CONFIG, sh_mem_config); - write_register(kgd, SH_MEM_APE1_BASE, sh_mem_ape1_base); - write_register(kgd, SH_MEM_APE1_LIMIT, sh_mem_ape1_limit); - write_register(kgd, SH_MEM_BASES, sh_mem_bases); - - unlock_srbm(kgd); -} - -static int kgd_set_pasid_vmid_mapping(struct kgd_dev *kgd, unsigned int pasid, - unsigned int vmid) -{ - /* - * We have to assume that there is no outstanding mapping. - * The ATC_VMID_PASID_MAPPING_UPDATE_STATUS bit could be 0 - * because a mapping is in progress or because a mapping finished and - * the SW cleared it. - * So the protocol is to always wait & clear. - */ - uint32_t pasid_mapping = (pasid == 0) ? 0 : (uint32_t)pasid | - ATC_VMID_PASID_MAPPING_VALID_MASK; - - write_register(kgd, ATC_VMID0_PASID_MAPPING + vmid*sizeof(uint32_t), - pasid_mapping); - - while (!(read_register(kgd, ATC_VMID_PASID_MAPPING_UPDATE_STATUS) & - (1U << vmid))) - cpu_relax(); - write_register(kgd, ATC_VMID_PASID_MAPPING_UPDATE_STATUS, 1U << vmid); - - /* Mapping vmid to pasid also for IH block */ - write_register(kgd, IH_VMID_0_LUT + vmid * sizeof(uint32_t), - pasid_mapping); - - return 0; -} - -static int kgd_init_pipeline(struct kgd_dev *kgd, uint32_t pipe_id, - uint32_t hpd_size, uint64_t hpd_gpu_addr) -{ - /* nothing to do here */ - return 0; -} - -static int kgd_init_interrupts(struct kgd_dev *kgd, uint32_t pipe_id) -{ - uint32_t mec; - uint32_t pipe; - - mec = (pipe_id / CIK_PIPE_PER_MEC) + 1; - pipe = (pipe_id % CIK_PIPE_PER_MEC); - - lock_srbm(kgd, mec, pipe, 0, 0); - - write_register(kgd, CPC_INT_CNTL, - TIME_STAMP_INT_ENABLE | OPCODE_ERROR_INT_ENABLE); - - unlock_srbm(kgd); - - return 0; -} - -static inline uint32_t get_sdma_base_addr(struct cik_sdma_rlc_registers *m) -{ - uint32_t retval; - - retval = m->sdma_engine_id * SDMA1_REGISTER_OFFSET + - m->sdma_queue_id * KFD_CIK_SDMA_QUEUE_OFFSET; - - pr_debug("kfd: sdma base address: 0x%x\n", retval); - - return retval; -} - -static inline struct cik_mqd *get_mqd(void *mqd) -{ - return (struct cik_mqd *)mqd; -} - -static inline struct cik_sdma_rlc_registers *get_sdma_mqd(void *mqd) -{ - return (struct cik_sdma_rlc_registers *)mqd; -} - -static int kgd_hqd_load(struct kgd_dev *kgd, void *mqd, uint32_t pipe_id, - uint32_t queue_id, uint32_t __user *wptr, - uint32_t wptr_shift, uint32_t wptr_mask, - struct mm_struct *mm) -{ - uint32_t wptr_shadow, is_wptr_shadow_valid; - struct cik_mqd *m; - - m = get_mqd(mqd); - - is_wptr_shadow_valid = !get_user(wptr_shadow, wptr); - - acquire_queue(kgd, pipe_id, queue_id); - write_register(kgd, CP_MQD_BASE_ADDR, m->cp_mqd_base_addr_lo); - write_register(kgd, CP_MQD_BASE_ADDR_HI, m->cp_mqd_base_addr_hi); - write_register(kgd, CP_MQD_CONTROL, m->cp_mqd_control); - - write_register(kgd, CP_HQD_PQ_BASE, m->cp_hqd_pq_base_lo); - write_register(kgd, CP_HQD_PQ_BASE_HI, m->cp_hqd_pq_base_hi); - write_register(kgd, CP_HQD_PQ_CONTROL, m->cp_hqd_pq_control); - - write_register(kgd, CP_HQD_IB_CONTROL, m->cp_hqd_ib_control); - write_register(kgd, CP_HQD_IB_BASE_ADDR, m->cp_hqd_ib_base_addr_lo); - write_register(kgd, CP_HQD_IB_BASE_ADDR_HI, m->cp_hqd_ib_base_addr_hi); - - write_register(kgd, CP_HQD_IB_RPTR, m->cp_hqd_ib_rptr); - - write_register(kgd, CP_HQD_PERSISTENT_STATE, - m->cp_hqd_persistent_state); - write_register(kgd, CP_HQD_SEMA_CMD, m->cp_hqd_sema_cmd); - write_register(kgd, CP_HQD_MSG_TYPE, m->cp_hqd_msg_type); - - write_register(kgd, CP_HQD_ATOMIC0_PREOP_LO, - m->cp_hqd_atomic0_preop_lo); - - write_register(kgd, CP_HQD_ATOMIC0_PREOP_HI, - m->cp_hqd_atomic0_preop_hi); - - write_register(kgd, CP_HQD_ATOMIC1_PREOP_LO, - m->cp_hqd_atomic1_preop_lo); - - write_register(kgd, CP_HQD_ATOMIC1_PREOP_HI, - m->cp_hqd_atomic1_preop_hi); - - write_register(kgd, CP_HQD_PQ_RPTR_REPORT_ADDR, - m->cp_hqd_pq_rptr_report_addr_lo); - - write_register(kgd, CP_HQD_PQ_RPTR_REPORT_ADDR_HI, - m->cp_hqd_pq_rptr_report_addr_hi); - - write_register(kgd, CP_HQD_PQ_RPTR, m->cp_hqd_pq_rptr); - - write_register(kgd, CP_HQD_PQ_WPTR_POLL_ADDR, - m->cp_hqd_pq_wptr_poll_addr_lo); - - write_register(kgd, CP_HQD_PQ_WPTR_POLL_ADDR_HI, - m->cp_hqd_pq_wptr_poll_addr_hi); - - write_register(kgd, CP_HQD_PQ_DOORBELL_CONTROL, - m->cp_hqd_pq_doorbell_control); - - write_register(kgd, CP_HQD_VMID, m->cp_hqd_vmid); - - write_register(kgd, CP_HQD_QUANTUM, m->cp_hqd_quantum); - - write_register(kgd, CP_HQD_PIPE_PRIORITY, m->cp_hqd_pipe_priority); - write_register(kgd, CP_HQD_QUEUE_PRIORITY, m->cp_hqd_queue_priority); - - write_register(kgd, CP_HQD_IQ_RPTR, m->cp_hqd_iq_rptr); - - if (is_wptr_shadow_valid) - write_register(kgd, CP_HQD_PQ_WPTR, wptr_shadow); - - write_register(kgd, CP_HQD_ACTIVE, m->cp_hqd_active); - release_queue(kgd); - - return 0; -} - -static int kgd_hqd_sdma_load(struct kgd_dev *kgd, void *mqd) -{ - struct cik_sdma_rlc_registers *m; - uint32_t sdma_base_addr; - - m = get_sdma_mqd(mqd); - sdma_base_addr = get_sdma_base_addr(m); - - write_register(kgd, - sdma_base_addr + SDMA0_RLC0_VIRTUAL_ADDR, - m->sdma_rlc_virtual_addr); - - write_register(kgd, - sdma_base_addr + SDMA0_RLC0_RB_BASE, - m->sdma_rlc_rb_base); - - write_register(kgd, - sdma_base_addr + SDMA0_RLC0_RB_BASE_HI, - m->sdma_rlc_rb_base_hi); - - write_register(kgd, - sdma_base_addr + SDMA0_RLC0_RB_RPTR_ADDR_LO, - m->sdma_rlc_rb_rptr_addr_lo); - - write_register(kgd, - sdma_base_addr + SDMA0_RLC0_RB_RPTR_ADDR_HI, - m->sdma_rlc_rb_rptr_addr_hi); - - write_register(kgd, - sdma_base_addr + SDMA0_RLC0_DOORBELL, - m->sdma_rlc_doorbell); - - write_register(kgd, - sdma_base_addr + SDMA0_RLC0_RB_CNTL, - m->sdma_rlc_rb_cntl); - - return 0; -} - -static bool kgd_hqd_is_occupied(struct kgd_dev *kgd, uint64_t queue_address, - uint32_t pipe_id, uint32_t queue_id) -{ - uint32_t act; - bool retval = false; - uint32_t low, high; - - acquire_queue(kgd, pipe_id, queue_id); - act = read_register(kgd, CP_HQD_ACTIVE); - if (act) { - low = lower_32_bits(queue_address >> 8); - high = upper_32_bits(queue_address >> 8); - - if (low == read_register(kgd, CP_HQD_PQ_BASE) && - high == read_register(kgd, CP_HQD_PQ_BASE_HI)) - retval = true; - } - release_queue(kgd); - return retval; -} - -static bool kgd_hqd_sdma_is_occupied(struct kgd_dev *kgd, void *mqd) -{ - struct cik_sdma_rlc_registers *m; - uint32_t sdma_base_addr; - uint32_t sdma_rlc_rb_cntl; - - m = get_sdma_mqd(mqd); - sdma_base_addr = get_sdma_base_addr(m); - - sdma_rlc_rb_cntl = read_register(kgd, - sdma_base_addr + SDMA0_RLC0_RB_CNTL); - - if (sdma_rlc_rb_cntl & SDMA_RB_ENABLE) - return true; - - return false; -} - -static int kgd_hqd_destroy(struct kgd_dev *kgd, void *mqd, uint32_t reset_type, - unsigned int timeout, uint32_t pipe_id, - uint32_t queue_id) -{ - uint32_t temp; - - acquire_queue(kgd, pipe_id, queue_id); - write_register(kgd, CP_HQD_PQ_DOORBELL_CONTROL, 0); - - write_register(kgd, CP_HQD_DEQUEUE_REQUEST, reset_type); - - while (true) { - temp = read_register(kgd, CP_HQD_ACTIVE); - if (temp & 0x1) - break; - if (timeout == 0) { - pr_err("kfd: cp queue preemption time out (%dms)\n", - temp); - release_queue(kgd); - return -ETIME; - } - msleep(20); - timeout -= 20; - } - - release_queue(kgd); - return 0; -} - -static int kgd_hqd_sdma_destroy(struct kgd_dev *kgd, void *mqd, - unsigned int timeout) -{ - struct cik_sdma_rlc_registers *m; - uint32_t sdma_base_addr; - uint32_t temp; - - m = get_sdma_mqd(mqd); - sdma_base_addr = get_sdma_base_addr(m); - - temp = read_register(kgd, sdma_base_addr + SDMA0_RLC0_RB_CNTL); - temp = temp & ~SDMA_RB_ENABLE; - write_register(kgd, sdma_base_addr + SDMA0_RLC0_RB_CNTL, temp); - - while (true) { - temp = read_register(kgd, sdma_base_addr + - SDMA0_RLC0_CONTEXT_STATUS); - if (temp & SDMA_RLC_IDLE) - break; - if (timeout == 0) - return -ETIME; - msleep(20); - timeout -= 20; - } - - write_register(kgd, sdma_base_addr + SDMA0_RLC0_DOORBELL, 0); - write_register(kgd, sdma_base_addr + SDMA0_RLC0_RB_RPTR, 0); - write_register(kgd, sdma_base_addr + SDMA0_RLC0_RB_WPTR, 0); - write_register(kgd, sdma_base_addr + SDMA0_RLC0_RB_BASE, 0); - - return 0; -} - -static int kgd_address_watch_disable(struct kgd_dev *kgd) -{ - union TCP_WATCH_CNTL_BITS cntl; - unsigned int i; - - cntl.u32All = 0; - - cntl.bitfields.valid = 0; - cntl.bitfields.mask = ADDRESS_WATCH_REG_CNTL_DEFAULT_MASK; - cntl.bitfields.atc = 1; - - /* Turning off this address until we set all the registers */ - for (i = 0; i < MAX_WATCH_ADDRESSES; i++) - write_register(kgd, - watchRegs[i * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_CNTL], - cntl.u32All); - - return 0; -} - -static int kgd_address_watch_execute(struct kgd_dev *kgd, - unsigned int watch_point_id, - uint32_t cntl_val, - uint32_t addr_hi, - uint32_t addr_lo) -{ - union TCP_WATCH_CNTL_BITS cntl; - - cntl.u32All = cntl_val; - - /* Turning off this watch point until we set all the registers */ - cntl.bitfields.valid = 0; - write_register(kgd, - watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_CNTL], - cntl.u32All); - - write_register(kgd, - watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_ADDR_HI], - addr_hi); - - write_register(kgd, - watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_ADDR_LO], - addr_lo); - - /* Enable the watch point */ - cntl.bitfields.valid = 1; - - write_register(kgd, - watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + - ADDRESS_WATCH_REG_CNTL], - cntl.u32All); - - return 0; -} - -static int kgd_wave_control_execute(struct kgd_dev *kgd, - uint32_t gfx_index_val, - uint32_t sq_cmd) -{ - struct radeon_device *rdev = get_radeon_device(kgd); - uint32_t data; - - mutex_lock(&rdev->grbm_idx_mutex); - - write_register(kgd, GRBM_GFX_INDEX, gfx_index_val); - write_register(kgd, SQ_CMD, sq_cmd); - - /* Restore the GRBM_GFX_INDEX register */ - - data = INSTANCE_BROADCAST_WRITES | SH_BROADCAST_WRITES | - SE_BROADCAST_WRITES; - - write_register(kgd, GRBM_GFX_INDEX, data); - - mutex_unlock(&rdev->grbm_idx_mutex); - - return 0; -} - -static uint32_t kgd_address_watch_get_offset(struct kgd_dev *kgd, - unsigned int watch_point_id, - unsigned int reg_offset) -{ - return watchRegs[watch_point_id * ADDRESS_WATCH_REG_MAX + reg_offset] - / 4; -} - -static bool get_atc_vmid_pasid_mapping_valid(struct kgd_dev *kgd, uint8_t vmid) -{ - uint32_t reg; - struct radeon_device *rdev = (struct radeon_device *) kgd; - - reg = RREG32(ATC_VMID0_PASID_MAPPING + vmid*4); - return reg & ATC_VMID_PASID_MAPPING_VALID_MASK; -} - -static uint16_t get_atc_vmid_pasid_mapping_pasid(struct kgd_dev *kgd, - uint8_t vmid) -{ - uint32_t reg; - struct radeon_device *rdev = (struct radeon_device *) kgd; - - reg = RREG32(ATC_VMID0_PASID_MAPPING + vmid*4); - return reg & ATC_VMID_PASID_MAPPING_PASID_MASK; -} - -static void write_vmid_invalidate_request(struct kgd_dev *kgd, uint8_t vmid) -{ - struct radeon_device *rdev = (struct radeon_device *) kgd; - - return WREG32(VM_INVALIDATE_REQUEST, 1 << vmid); -} - -static uint16_t get_fw_version(struct kgd_dev *kgd, enum kgd_engine_type type) -{ - struct radeon_device *rdev = (struct radeon_device *) kgd; - const union radeon_firmware_header *hdr; - - BUG_ON(kgd == NULL || rdev->mec_fw == NULL); - - switch (type) { - case KGD_ENGINE_PFP: - hdr = (const union radeon_firmware_header *) rdev->pfp_fw->data; - break; - - case KGD_ENGINE_ME: - hdr = (const union radeon_firmware_header *) rdev->me_fw->data; - break; - - case KGD_ENGINE_CE: - hdr = (const union radeon_firmware_header *) rdev->ce_fw->data; - break; - - case KGD_ENGINE_MEC1: - hdr = (const union radeon_firmware_header *) rdev->mec_fw->data; - break; - - case KGD_ENGINE_MEC2: - hdr = (const union radeon_firmware_header *) - rdev->mec2_fw->data; - break; - - case KGD_ENGINE_RLC: - hdr = (const union radeon_firmware_header *) rdev->rlc_fw->data; - break; - - case KGD_ENGINE_SDMA1: - case KGD_ENGINE_SDMA2: - hdr = (const union radeon_firmware_header *) - rdev->sdma_fw->data; - break; - - default: - return 0; - } - - if (hdr == NULL) - return 0; - - /* Only 12 bit in use*/ - return hdr->common.ucode_version; -} diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index dfee8f7d94ae..cde037f213d7 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -34,8 +34,6 @@ #include <linux/slab.h> #include <linux/pm_runtime.h> -#include "radeon_kfd.h" - #if defined(CONFIG_VGA_SWITCHEROO) bool radeon_has_atpx(void); #else @@ -68,8 +66,6 @@ void radeon_driver_unload_kms(struct drm_device *dev) pm_runtime_forbid(dev->dev); } - radeon_kfd_device_fini(rdev); - radeon_acpi_fini(rdev); radeon_modeset_fini(rdev); @@ -174,9 +170,6 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) "Error during ACPI methods call\n"); } - radeon_kfd_device_probe(rdev); - radeon_kfd_device_init(rdev); - if (radeon_is_px(dev)) { pm_runtime_use_autosuspend(dev->dev); pm_runtime_set_autosuspend_delay(dev->dev, 5000); diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index da44ac234f64..ca0a7ed28c9b 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -762,10 +762,6 @@ extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector); extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder, struct drm_connector *connector); -extern int radeon_dp_get_dp_link_config(struct drm_connector *connector, - const u8 *dpcd, - unsigned pix_clock, - unsigned *dp_lanes, unsigned *dp_rate); extern void radeon_dp_set_rx_power_state(struct drm_connector *connector, u8 power_state); extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector); diff --git a/drivers/gpu/drm/rockchip/Kconfig b/drivers/gpu/drm/rockchip/Kconfig index 3c70c6224bd2..0ccc76217ee4 100644 --- a/drivers/gpu/drm/rockchip/Kconfig +++ b/drivers/gpu/drm/rockchip/Kconfig @@ -60,7 +60,7 @@ config ROCKCHIP_INNO_HDMI config ROCKCHIP_LVDS bool "Rockchip LVDS support" depends on DRM_ROCKCHIP - depends on PINCTRL + depends on PINCTRL && OF help Choose this option to enable support for Rockchip LVDS controllers. Rockchip rk3288 SoC has LVDS TX Controller can be used, and it diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 39944c0f1c0b..1262120a3834 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -72,7 +72,7 @@ struct rockchip_dp_device { struct reset_control *rst; struct work_struct psr_work; - spinlock_t psr_lock; + struct mutex psr_lock; unsigned int psr_state; const struct rockchip_dp_chip_data *data; @@ -83,21 +83,20 @@ struct rockchip_dp_device { static void analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled) { struct rockchip_dp_device *dp = to_dp(encoder); - unsigned long flags; if (!analogix_dp_psr_supported(dp->dev)) return; DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); - spin_lock_irqsave(&dp->psr_lock, flags); + mutex_lock(&dp->psr_lock); if (enabled) dp->psr_state = EDP_VSC_PSR_STATE_ACTIVE; else dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; schedule_work(&dp->psr_work); - spin_unlock_irqrestore(&dp->psr_lock, flags); + mutex_unlock(&dp->psr_lock); } static void analogix_dp_psr_work(struct work_struct *work) @@ -105,7 +104,6 @@ static void analogix_dp_psr_work(struct work_struct *work) struct rockchip_dp_device *dp = container_of(work, typeof(*dp), psr_work); int ret; - unsigned long flags; ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, PSR_WAIT_LINE_FLAG_TIMEOUT_MS); @@ -114,12 +112,12 @@ static void analogix_dp_psr_work(struct work_struct *work) return; } - spin_lock_irqsave(&dp->psr_lock, flags); + mutex_lock(&dp->psr_lock); if (dp->psr_state == EDP_VSC_PSR_STATE_ACTIVE) analogix_dp_enable_psr(dp->dev); else analogix_dp_disable_psr(dp->dev); - spin_unlock_irqrestore(&dp->psr_lock, flags); + mutex_unlock(&dp->psr_lock); } static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) @@ -363,7 +361,7 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, dp->plat_data.power_off = rockchip_dp_powerdown; dp->plat_data.get_modes = rockchip_dp_get_modes; - spin_lock_init(&dp->psr_lock); + mutex_init(&dp->psr_lock); dp->psr_state = ~EDP_VSC_PSR_STATE_ACTIVE; INIT_WORK(&dp->psr_work, analogix_dp_psr_work); diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index dc58ab140151..cf54847a8bd1 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig @@ -9,6 +9,7 @@ config DRM_TEGRA select DRM_PANEL select TEGRA_HOST1X select IOMMU_IOVA if IOMMU_SUPPORT + select CEC_CORE if CEC_NOTIFIER help Choose this option if you have an NVIDIA Tegra SoC. diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 91919d52b207..fc70351b9017 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/debugfs.h> #include <linux/iommu.h> +#include <linux/of_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> @@ -23,16 +24,6 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_plane_helper.h> -struct tegra_dc_soc_info { - bool supports_border_color; - bool supports_interlacing; - bool supports_cursor; - bool supports_block_linear; - unsigned int pitch_align; - bool has_powergate; - bool broken_reset; -}; - struct tegra_plane { struct drm_plane base; unsigned int index; @@ -559,14 +550,21 @@ static int tegra_plane_atomic_check(struct drm_plane *plane, return 0; } -static void tegra_dc_disable_window(struct tegra_dc *dc, int index) +static void tegra_plane_atomic_disable(struct drm_plane *plane, + struct drm_plane_state *old_state) { + struct tegra_dc *dc = to_tegra_dc(old_state->crtc); + struct tegra_plane *p = to_tegra_plane(plane); unsigned long flags; u32 value; + /* rien ne va plus */ + if (!old_state || !old_state->crtc) + return; + spin_lock_irqsave(&dc->lock, flags); - value = WINDOW_A_SELECT << index; + value = WINDOW_A_SELECT << p->index; tegra_dc_writel(dc, value, DC_CMD_DISPLAY_WINDOW_HEADER); value = tegra_dc_readl(dc, DC_WIN_WIN_OPTIONS); @@ -591,7 +589,7 @@ static void tegra_plane_atomic_update(struct drm_plane *plane, return; if (!plane->state->visible) - return tegra_dc_disable_window(dc, p->index); + return tegra_plane_atomic_disable(plane, old_state); memset(&window, 0, sizeof(window)); window.src.x = plane->state->src.x1 >> 16; @@ -627,25 +625,10 @@ static void tegra_plane_atomic_update(struct drm_plane *plane, tegra_dc_setup_window(dc, p->index, &window); } -static void tegra_plane_atomic_disable(struct drm_plane *plane, - struct drm_plane_state *old_state) -{ - struct tegra_plane *p = to_tegra_plane(plane); - struct tegra_dc *dc; - - /* rien ne va plus */ - if (!old_state || !old_state->crtc) - return; - - dc = to_tegra_dc(old_state->crtc); - - tegra_dc_disable_window(dc, p->index); -} - -static const struct drm_plane_helper_funcs tegra_primary_plane_helper_funcs = { +static const struct drm_plane_helper_funcs tegra_plane_helper_funcs = { .atomic_check = tegra_plane_atomic_check, - .atomic_update = tegra_plane_atomic_update, .atomic_disable = tegra_plane_atomic_disable, + .atomic_update = tegra_plane_atomic_update, }; static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm, @@ -685,7 +668,7 @@ static struct drm_plane *tegra_dc_primary_plane_create(struct drm_device *drm, return ERR_PTR(err); } - drm_plane_helper_add(&plane->base, &tegra_primary_plane_helper_funcs); + drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); return &plane->base; } @@ -880,12 +863,6 @@ static const uint32_t tegra_overlay_plane_formats[] = { DRM_FORMAT_YUV422, }; -static const struct drm_plane_helper_funcs tegra_overlay_plane_helper_funcs = { - .atomic_check = tegra_plane_atomic_check, - .atomic_update = tegra_plane_atomic_update, - .atomic_disable = tegra_plane_atomic_disable, -}; - static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, struct tegra_dc *dc, unsigned int index) @@ -913,7 +890,7 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm, return ERR_PTR(err); } - drm_plane_helper_add(&plane->base, &tegra_overlay_plane_helper_funcs); + drm_plane_helper_add(&plane->base, &tegra_plane_helper_funcs); return &plane->base; } @@ -1161,6 +1138,11 @@ static void tegra_dc_commit_state(struct tegra_dc *dc, value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1; tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); + + err = clk_set_rate(dc->clk, state->pclk); + if (err < 0) + dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n", + dc->clk, state->pclk, err); } static void tegra_dc_stop(struct tegra_dc *dc) @@ -1756,7 +1738,7 @@ static int tegra_dc_init(struct host1x_client *client) struct drm_plane *cursor = NULL; int err; - dc->syncpt = host1x_syncpt_request(dc->dev, flags); + dc->syncpt = host1x_syncpt_request(client, flags); if (!dc->syncpt) dev_warn(dc->dev, "failed to allocate syncpoint\n"); @@ -1985,7 +1967,6 @@ static int tegra_dc_parse_dt(struct tegra_dc *dc) static int tegra_dc_probe(struct platform_device *pdev) { - const struct of_device_id *id; struct resource *regs; struct tegra_dc *dc; int err; @@ -1994,14 +1975,11 @@ static int tegra_dc_probe(struct platform_device *pdev) if (!dc) return -ENOMEM; - id = of_match_node(tegra_dc_of_match, pdev->dev.of_node); - if (!id) - return -ENODEV; + dc->soc = of_device_get_match_data(&pdev->dev); spin_lock_init(&dc->lock); INIT_LIST_HEAD(&dc->list); dc->dev = &pdev->dev; - dc->soc = id->data; err = tegra_dc_parse_dt(dc); if (err < 0) @@ -2019,8 +1997,22 @@ static int tegra_dc_probe(struct platform_device *pdev) return PTR_ERR(dc->rst); } - if (!dc->soc->broken_reset) - reset_control_assert(dc->rst); + /* assert reset and disable clock */ + if (!dc->soc->broken_reset) { + err = clk_prepare_enable(dc->clk); + if (err < 0) + return err; + + usleep_range(2000, 4000); + + err = reset_control_assert(dc->rst); + if (err < 0) + return err; + + usleep_range(2000, 4000); + + clk_disable_unprepare(dc->clk); + } if (dc->soc->has_powergate) { if (dc->pipe == 0) diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 4a268635749b..cb100b6e3282 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h @@ -10,6 +10,126 @@ #ifndef TEGRA_DC_H #define TEGRA_DC_H 1 +#include <linux/host1x.h> + +#include <drm/drm_crtc.h> + +#include "drm.h" + +struct tegra_output; + +struct tegra_dc_stats { + unsigned long frames; + unsigned long vblank; + unsigned long underflow; + unsigned long overflow; +}; + +struct tegra_dc_soc_info { + bool supports_border_color; + bool supports_interlacing; + bool supports_cursor; + bool supports_block_linear; + unsigned int pitch_align; + bool has_powergate; + bool broken_reset; +}; + +struct tegra_dc { + struct host1x_client client; + struct host1x_syncpt *syncpt; + struct device *dev; + spinlock_t lock; + + struct drm_crtc base; + unsigned int powergate; + int pipe; + + struct clk *clk; + struct reset_control *rst; + void __iomem *regs; + int irq; + + struct tegra_output *rgb; + + struct tegra_dc_stats stats; + struct list_head list; + + struct drm_info_list *debugfs_files; + struct drm_minor *minor; + struct dentry *debugfs; + + /* page-flip handling */ + struct drm_pending_vblank_event *event; + + const struct tegra_dc_soc_info *soc; + + struct iommu_domain *domain; +}; + +static inline struct tegra_dc * +host1x_client_to_dc(struct host1x_client *client) +{ + return container_of(client, struct tegra_dc, client); +} + +static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc) +{ + return crtc ? container_of(crtc, struct tegra_dc, base) : NULL; +} + +static inline void tegra_dc_writel(struct tegra_dc *dc, u32 value, + unsigned int offset) +{ + trace_dc_writel(dc->dev, offset, value); + writel(value, dc->regs + (offset << 2)); +} + +static inline u32 tegra_dc_readl(struct tegra_dc *dc, unsigned int offset) +{ + u32 value = readl(dc->regs + (offset << 2)); + + trace_dc_readl(dc->dev, offset, value); + + return value; +} + +struct tegra_dc_window { + struct { + unsigned int x; + unsigned int y; + unsigned int w; + unsigned int h; + } src; + struct { + unsigned int x; + unsigned int y; + unsigned int w; + unsigned int h; + } dst; + unsigned int bits_per_pixel; + unsigned int stride[2]; + unsigned long base[3]; + bool bottom_up; + + struct tegra_bo_tiling tiling; + u32 format; + u32 swap; +}; + +/* from dc.c */ +void tegra_dc_commit(struct tegra_dc *dc); +int tegra_dc_state_setup_clock(struct tegra_dc *dc, + struct drm_crtc_state *crtc_state, + struct clk *clk, unsigned long pclk, + unsigned int div); + +/* from rgb.c */ +int tegra_dc_rgb_probe(struct tegra_dc *dc); +int tegra_dc_rgb_remove(struct tegra_dc *dc); +int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc); +int tegra_dc_rgb_exit(struct tegra_dc *dc); + #define DC_CMD_GENERAL_INCR_SYNCPT 0x000 #define DC_CMD_GENERAL_INCR_SYNCPT_CNTRL 0x001 #define SYNCPT_CNTRL_NO_STALL (1 << 8) diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index 597d563d636a..943bdf88c4a2 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -386,12 +386,10 @@ int tegra_drm_submit(struct tegra_drm_context *context, unsigned int num_cmdbufs = args->num_cmdbufs; unsigned int num_relocs = args->num_relocs; unsigned int num_waitchks = args->num_waitchks; - struct drm_tegra_cmdbuf __user *cmdbufs = - (void __user *)(uintptr_t)args->cmdbufs; - struct drm_tegra_reloc __user *relocs = - (void __user *)(uintptr_t)args->relocs; - struct drm_tegra_waitchk __user *waitchks = - (void __user *)(uintptr_t)args->waitchks; + struct drm_tegra_cmdbuf __user *user_cmdbufs; + struct drm_tegra_reloc __user *user_relocs; + struct drm_tegra_waitchk __user *user_waitchks; + struct drm_tegra_syncpt __user *user_syncpt; struct drm_tegra_syncpt syncpt; struct host1x *host1x = dev_get_drvdata(drm->dev->parent); struct drm_gem_object **refs; @@ -400,6 +398,11 @@ int tegra_drm_submit(struct tegra_drm_context *context, unsigned int num_refs; int err; + user_cmdbufs = u64_to_user_ptr(args->cmdbufs); + user_relocs = u64_to_user_ptr(args->relocs); + user_waitchks = u64_to_user_ptr(args->waitchks); + user_syncpt = u64_to_user_ptr(args->syncpts); + /* We don't yet support other than one syncpt_incr struct per submit */ if (args->num_syncpts != 1) return -EINVAL; @@ -440,7 +443,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, struct tegra_bo *obj; u64 offset; - if (copy_from_user(&cmdbuf, cmdbufs, sizeof(cmdbuf))) { + if (copy_from_user(&cmdbuf, user_cmdbufs, sizeof(cmdbuf))) { err = -EFAULT; goto fail; } @@ -476,7 +479,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, host1x_job_add_gather(job, bo, cmdbuf.words, cmdbuf.offset); num_cmdbufs--; - cmdbufs++; + user_cmdbufs++; } /* copy and resolve relocations from submit */ @@ -485,7 +488,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, struct tegra_bo *obj; err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs], - &relocs[num_relocs], drm, + &user_relocs[num_relocs], drm, file); if (err < 0) goto fail; @@ -519,9 +522,8 @@ int tegra_drm_submit(struct tegra_drm_context *context, struct host1x_waitchk *wait = &job->waitchk[num_waitchks]; struct tegra_bo *obj; - err = host1x_waitchk_copy_from_user(wait, - &waitchks[num_waitchks], - file); + err = host1x_waitchk_copy_from_user( + wait, &user_waitchks[num_waitchks], file); if (err < 0) goto fail; @@ -539,8 +541,7 @@ int tegra_drm_submit(struct tegra_drm_context *context, } } - if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts, - sizeof(syncpt))) { + if (copy_from_user(&syncpt, user_syncpt, sizeof(syncpt))) { err = -EFAULT; goto fail; } @@ -1317,6 +1318,7 @@ static const struct of_device_id host1x_drm_subdevs[] = { { .compatible = "nvidia,tegra210-sor", }, { .compatible = "nvidia,tegra210-sor1", }, { .compatible = "nvidia,tegra210-vic", }, + { .compatible = "nvidia,tegra186-vic", }, { /* sentinel */ } }; diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 063f5d397526..ddae331ad8b6 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -119,104 +119,7 @@ void *tegra_drm_alloc(struct tegra_drm *tegra, size_t size, dma_addr_t *iova); void tegra_drm_free(struct tegra_drm *tegra, size_t size, void *virt, dma_addr_t iova); -struct tegra_dc_soc_info; -struct tegra_output; - -struct tegra_dc_stats { - unsigned long frames; - unsigned long vblank; - unsigned long underflow; - unsigned long overflow; -}; - -struct tegra_dc { - struct host1x_client client; - struct host1x_syncpt *syncpt; - struct device *dev; - spinlock_t lock; - - struct drm_crtc base; - unsigned int powergate; - int pipe; - - struct clk *clk; - struct reset_control *rst; - void __iomem *regs; - int irq; - - struct tegra_output *rgb; - - struct tegra_dc_stats stats; - struct list_head list; - - struct drm_info_list *debugfs_files; - struct drm_minor *minor; - struct dentry *debugfs; - - /* page-flip handling */ - struct drm_pending_vblank_event *event; - - const struct tegra_dc_soc_info *soc; - - struct iommu_domain *domain; -}; - -static inline struct tegra_dc * -host1x_client_to_dc(struct host1x_client *client) -{ - return container_of(client, struct tegra_dc, client); -} - -static inline struct tegra_dc *to_tegra_dc(struct drm_crtc *crtc) -{ - return crtc ? container_of(crtc, struct tegra_dc, base) : NULL; -} - -static inline void tegra_dc_writel(struct tegra_dc *dc, u32 value, - unsigned int offset) -{ - trace_dc_writel(dc->dev, offset, value); - writel(value, dc->regs + (offset << 2)); -} - -static inline u32 tegra_dc_readl(struct tegra_dc *dc, unsigned int offset) -{ - u32 value = readl(dc->regs + (offset << 2)); - - trace_dc_readl(dc->dev, offset, value); - - return value; -} - -struct tegra_dc_window { - struct { - unsigned int x; - unsigned int y; - unsigned int w; - unsigned int h; - } src; - struct { - unsigned int x; - unsigned int y; - unsigned int w; - unsigned int h; - } dst; - unsigned int bits_per_pixel; - unsigned int stride[2]; - unsigned long base[3]; - bool bottom_up; - - struct tegra_bo_tiling tiling; - u32 format; - u32 swap; -}; - -/* from dc.c */ -void tegra_dc_commit(struct tegra_dc *dc); -int tegra_dc_state_setup_clock(struct tegra_dc *dc, - struct drm_crtc_state *crtc_state, - struct clk *clk, unsigned long pclk, - unsigned int div); +struct cec_notifier; struct tegra_output { struct device_node *of_node; @@ -225,6 +128,7 @@ struct tegra_output { struct drm_panel *panel; struct i2c_adapter *ddc; const struct edid *edid; + struct cec_notifier *notifier; unsigned int hpd_irq; int hpd_gpio; enum of_gpio_flags hpd_gpio_flags; @@ -243,12 +147,6 @@ static inline struct tegra_output *connector_to_output(struct drm_connector *c) return container_of(c, struct tegra_output, connector); } -/* from rgb.c */ -int tegra_dc_rgb_probe(struct tegra_dc *dc); -int tegra_dc_rgb_remove(struct tegra_dc *dc); -int tegra_dc_rgb_init(struct drm_device *drm, struct tegra_dc *dc); -int tegra_dc_rgb_exit(struct tegra_dc *dc); - /* from output.c */ int tegra_output_probe(struct tegra_output *output); void tegra_output_remove(struct tegra_output *output); diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c index 6ea070da7718..9a8ea93016a9 100644 --- a/drivers/gpu/drm/tegra/gr2d.c +++ b/drivers/gpu/drm/tegra/gr2d.c @@ -36,7 +36,7 @@ static int gr2d_init(struct host1x_client *client) if (!gr2d->channel) return -ENOMEM; - client->syncpts[0] = host1x_syncpt_request(client->dev, flags); + client->syncpts[0] = host1x_syncpt_request(client, flags); if (!client->syncpts[0]) { host1x_channel_put(gr2d->channel); return -ENOMEM; diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c index cee2ab645cde..28c4ef63065b 100644 --- a/drivers/gpu/drm/tegra/gr3d.c +++ b/drivers/gpu/drm/tegra/gr3d.c @@ -46,7 +46,7 @@ static int gr3d_init(struct host1x_client *client) if (!gr3d->channel) return -ENOMEM; - client->syncpts[0] = host1x_syncpt_request(client->dev, flags); + client->syncpts[0] = host1x_syncpt_request(client, flags); if (!client->syncpts[0]) { host1x_channel_put(gr3d->channel); return -ENOMEM; diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c index 5b9d83b71943..6434b3d3d1ba 100644 --- a/drivers/gpu/drm/tegra/hdmi.c +++ b/drivers/gpu/drm/tegra/hdmi.c @@ -11,6 +11,7 @@ #include <linux/debugfs.h> #include <linux/gpio.h> #include <linux/hdmi.h> +#include <linux/of_device.h> #include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> #include <linux/reset.h> @@ -21,6 +22,8 @@ #include <sound/hda_verbs.h> +#include <media/cec-notifier.h> + #include "hdmi.h" #include "drm.h" #include "dc.h" @@ -1663,20 +1666,15 @@ static irqreturn_t tegra_hdmi_irq(int irq, void *data) static int tegra_hdmi_probe(struct platform_device *pdev) { - const struct of_device_id *match; struct tegra_hdmi *hdmi; struct resource *regs; int err; - match = of_match_node(tegra_hdmi_of_match, pdev->dev.of_node); - if (!match) - return -ENODEV; - hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL); if (!hdmi) return -ENOMEM; - hdmi->config = match->data; + hdmi->config = of_device_get_match_data(&pdev->dev); hdmi->dev = &pdev->dev; hdmi->audio_source = AUTO; @@ -1725,6 +1723,10 @@ static int tegra_hdmi_probe(struct platform_device *pdev) return PTR_ERR(hdmi->vdd); } + hdmi->output.notifier = cec_notifier_get(&pdev->dev); + if (hdmi->output.notifier == NULL) + return -ENOMEM; + hdmi->output.dev = &pdev->dev; err = tegra_output_probe(&hdmi->output); @@ -1783,6 +1785,9 @@ static int tegra_hdmi_remove(struct platform_device *pdev) tegra_output_remove(&hdmi->output); + if (hdmi->output.notifier) + cec_notifier_put(hdmi->output.notifier); + return 0; } diff --git a/drivers/gpu/drm/tegra/output.c b/drivers/gpu/drm/tegra/output.c index 1480f6aaffe4..24f8a3b712b4 100644 --- a/drivers/gpu/drm/tegra/output.c +++ b/drivers/gpu/drm/tegra/output.c @@ -11,6 +11,8 @@ #include <drm/drm_panel.h> #include "drm.h" +#include <media/cec-notifier.h> + int tegra_output_connector_get_modes(struct drm_connector *connector) { struct tegra_output *output = connector_to_output(connector); @@ -32,6 +34,7 @@ int tegra_output_connector_get_modes(struct drm_connector *connector) else if (output->ddc) edid = drm_get_edid(connector, output->ddc); + cec_notifier_set_phys_addr_from_edid(output->notifier, edid); drm_mode_connector_update_edid_property(connector, edid); if (edid) { @@ -67,6 +70,9 @@ tegra_output_connector_detect(struct drm_connector *connector, bool force) status = connector_status_connected; } + if (status != connector_status_connected) + cec_notifier_phys_addr_invalidate(output->notifier); + return status; } diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index 7ab1d1dc7cd7..4bcacd3f4861 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -2536,20 +2536,17 @@ MODULE_DEVICE_TABLE(of, tegra_sor_of_match); static int tegra_sor_probe(struct platform_device *pdev) { - const struct of_device_id *match; struct device_node *np; struct tegra_sor *sor; struct resource *regs; int err; - match = of_match_device(tegra_sor_of_match, &pdev->dev); - sor = devm_kzalloc(&pdev->dev, sizeof(*sor), GFP_KERNEL); if (!sor) return -ENOMEM; + sor->soc = of_device_get_match_data(&pdev->dev); sor->output.dev = sor->dev = &pdev->dev; - sor->soc = match->data; sor->settings = devm_kmemdup(&pdev->dev, sor->soc->settings, sor->soc->num_settings * diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c index 2448229fa653..18024183aa2b 100644 --- a/drivers/gpu/drm/tegra/vic.c +++ b/drivers/gpu/drm/tegra/vic.c @@ -167,7 +167,7 @@ static int vic_init(struct host1x_client *client) goto detach_device; } - client->syncpts[0] = host1x_syncpt_request(client->dev, 0); + client->syncpts[0] = host1x_syncpt_request(client, 0); if (!client->syncpts[0]) { err = -ENOMEM; goto free_channel; @@ -270,29 +270,33 @@ static const struct vic_config vic_t210_config = { .firmware = NVIDIA_TEGRA_210_VIC_FIRMWARE, }; +#define NVIDIA_TEGRA_186_VIC_FIRMWARE "nvidia/tegra186/vic04_ucode.bin" + +static const struct vic_config vic_t186_config = { + .firmware = NVIDIA_TEGRA_186_VIC_FIRMWARE, +}; + static const struct of_device_id vic_match[] = { { .compatible = "nvidia,tegra124-vic", .data = &vic_t124_config }, { .compatible = "nvidia,tegra210-vic", .data = &vic_t210_config }, + { .compatible = "nvidia,tegra186-vic", .data = &vic_t186_config }, { }, }; static int vic_probe(struct platform_device *pdev) { - struct vic_config *vic_config = NULL; struct device *dev = &pdev->dev; struct host1x_syncpt **syncpts; struct resource *regs; - const struct of_device_id *match; struct vic *vic; int err; - match = of_match_device(vic_match, dev); - vic_config = (struct vic_config *)match->data; - vic = devm_kzalloc(dev, sizeof(*vic), GFP_KERNEL); if (!vic) return -ENOMEM; + vic->config = of_device_get_match_data(dev); + syncpts = devm_kzalloc(dev, sizeof(*syncpts), GFP_KERNEL); if (!syncpts) return -ENOMEM; @@ -321,7 +325,7 @@ static int vic_probe(struct platform_device *pdev) if (err < 0) return err; - err = falcon_read_firmware(&vic->falcon, vic_config->firmware); + err = falcon_read_firmware(&vic->falcon, vic->config->firmware); if (err < 0) goto exit_falcon; @@ -334,7 +338,6 @@ static int vic_probe(struct platform_device *pdev) vic->client.base.syncpts = syncpts; vic->client.base.num_syncpts = 1; vic->dev = dev; - vic->config = vic_config; INIT_LIST_HEAD(&vic->client.list); vic->client.ops = &vic_ops; @@ -405,3 +408,6 @@ MODULE_FIRMWARE(NVIDIA_TEGRA_124_VIC_FIRMWARE); #if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC) MODULE_FIRMWARE(NVIDIA_TEGRA_210_VIC_FIRMWARE); #endif +#if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) +MODULE_FIRMWARE(NVIDIA_TEGRA_186_VIC_FIRMWARE); +#endif diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index d2589f310437..6ef4d1a1e3a9 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -24,6 +24,7 @@ #include <linux/completion.h> #include <linux/dma-mapping.h> #include <linux/of_graph.h> +#include <linux/math64.h> #include "tilcdc_drv.h" #include "tilcdc_regs.h" @@ -48,6 +49,7 @@ struct tilcdc_crtc { unsigned int lcd_fck_rate; ktime_t last_vblank; + unsigned int hvtotal_us; struct drm_framebuffer *curr_fb; struct drm_framebuffer *next_fb; @@ -292,6 +294,12 @@ static void tilcdc_crtc_set_clk(struct drm_crtc *crtc) LCDC_V2_CORE_CLK_EN); } +uint tilcdc_mode_hvtotal(const struct drm_display_mode *mode) +{ + return (uint) div_u64(1000llu * mode->htotal * mode->vtotal, + mode->clock); +} + static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); @@ -459,6 +467,9 @@ static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) drm_framebuffer_get(fb); crtc->hwmode = crtc->state->adjusted_mode; + + tilcdc_crtc->hvtotal_us = + tilcdc_mode_hvtotal(&crtc->hwmode); } static void tilcdc_crtc_enable(struct drm_crtc *crtc) @@ -467,7 +478,6 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc) struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); unsigned long flags; - WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); mutex_lock(&tilcdc_crtc->enable_lock); if (tilcdc_crtc->enabled || tilcdc_crtc->shutdown) { mutex_unlock(&tilcdc_crtc->enable_lock); @@ -564,7 +574,6 @@ static void tilcdc_crtc_off(struct drm_crtc *crtc, bool shutdown) static void tilcdc_crtc_disable(struct drm_crtc *crtc) { - WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); tilcdc_crtc_off(crtc, false); } @@ -608,9 +617,7 @@ static void tilcdc_crtc_destroy(struct drm_crtc *crtc) struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct tilcdc_drm_private *priv = crtc->dev->dev_private; - drm_modeset_lock(&crtc->mutex, NULL); - tilcdc_crtc_disable(crtc); - drm_modeset_unlock(&crtc->mutex); + tilcdc_crtc_shutdown(crtc); flush_workqueue(priv->wq); @@ -626,8 +633,6 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc, struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); struct drm_device *dev = crtc->dev; - WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); - if (tilcdc_crtc->event) { dev_err(dev->dev, "already pending page flip!\n"); return -EBUSY; @@ -648,7 +653,7 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc, spin_lock_irqsave(&tilcdc_crtc->irq_lock, flags); next_vblank = ktime_add_us(tilcdc_crtc->last_vblank, - 1000000 / crtc->hwmode.vrefresh); + tilcdc_crtc->hvtotal_us); tdiff = ktime_to_us(ktime_sub(next_vblank, ktime_get())); if (tdiff < TILCDC_VBLANK_SAFETY_THRESHOLD_US) @@ -728,11 +733,39 @@ static void tilcdc_crtc_disable_vblank(struct drm_crtc *crtc) { } +static void tilcdc_crtc_reset(struct drm_crtc *crtc) +{ + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + struct drm_device *dev = crtc->dev; + int ret; + + drm_atomic_helper_crtc_reset(crtc); + + /* Turn the raster off if it for some reason is on. */ + pm_runtime_get_sync(dev->dev); + if (tilcdc_read(dev, LCDC_RASTER_CTRL_REG) & LCDC_RASTER_ENABLE) { + /* Enable DMA Frame Done Interrupt */ + tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_FRAME_DONE); + tilcdc_clear_irqstatus(dev, 0xffffffff); + + tilcdc_crtc->frame_done = false; + tilcdc_clear(dev, LCDC_RASTER_CTRL_REG, LCDC_RASTER_ENABLE); + + ret = wait_event_timeout(tilcdc_crtc->frame_done_wq, + tilcdc_crtc->frame_done, + msecs_to_jiffies(500)); + if (ret == 0) + dev_err(dev->dev, "%s: timeout waiting for framedone\n", + __func__); + } + pm_runtime_put_sync(dev->dev); +} + static const struct drm_crtc_funcs tilcdc_crtc_funcs = { .destroy = tilcdc_crtc_destroy, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, - .reset = drm_atomic_helper_crtc_reset, + .reset = tilcdc_crtc_reset, .atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state, .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, .enable_vblank = tilcdc_crtc_enable_vblank, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 1813a3623ce6..8eebb5f826a6 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -418,7 +418,7 @@ static int panel_remove(struct platform_device *pdev) return 0; } -static struct of_device_id panel_of_match[] = { +static const struct of_device_id panel_of_match[] = { { .compatible = "ti,tilcdc,panel", }, { }, }; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index 623a9140493c..482299a6f3b0 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -163,7 +163,6 @@ static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) return NULL; } - of_node_set_flag(overlay, OF_DETACHED); ret = of_resolve_phandles(overlay); if (ret) { pr_err("%s: Failed to resolve phandles: %d\n", __func__, ret); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 1e2dfb1b1d6b..7e3643462a08 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -289,8 +289,6 @@ static const struct tilcdc_module_ops tfp410_module_ops = { * Device: */ -static struct of_device_id tfp410_of_match[]; - static int tfp410_probe(struct platform_device *pdev) { struct device_node *node = pdev->dev.of_node; @@ -375,7 +373,7 @@ static int tfp410_remove(struct platform_device *pdev) return 0; } -static struct of_device_id tfp410_of_match[] = { +static const struct of_device_id tfp410_of_match[] = { { .compatible = "ti,tilcdc,tfp410", }, { }, }; diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index d79607a1187c..c088703777e2 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -150,8 +150,7 @@ static void ttm_bo_release_list(struct kref *list_kref) ttm_tt_destroy(bo->ttm); atomic_dec(&bo->glob->bo_count); dma_fence_put(bo->moving); - if (bo->resv == &bo->ttm_resv) - reservation_object_fini(&bo->ttm_resv); + reservation_object_fini(&bo->ttm_resv); mutex_destroy(&bo->wu_mutex); if (bo->destroy) bo->destroy(bo); @@ -402,14 +401,11 @@ static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo) if (bo->resv == &bo->ttm_resv) return 0; - reservation_object_init(&bo->ttm_resv); BUG_ON(!reservation_object_trylock(&bo->ttm_resv)); r = reservation_object_copy_fences(&bo->ttm_resv, bo->resv); - if (r) { + if (r) reservation_object_unlock(&bo->ttm_resv); - reservation_object_fini(&bo->ttm_resv); - } return r; } @@ -459,6 +455,7 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) spin_unlock(&glob->lru_lock); if (bo->resv != &bo->ttm_resv) reservation_object_unlock(&bo->ttm_resv); + ttm_bo_cleanup_memtype_use(bo); return; } @@ -557,8 +554,6 @@ static int ttm_bo_cleanup_refs_and_unlock(struct ttm_buffer_object *bo, } ttm_bo_del_from_lru(bo); - if (!list_empty(&bo->ddestroy) && (bo->resv != &bo->ttm_resv)) - reservation_object_fini(&bo->ttm_resv); list_del_init(&bo->ddestroy); kref_put(&bo->list_kref, ttm_bo_ref_bug); @@ -1207,8 +1202,8 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, lockdep_assert_held(&bo->resv->lock.base); } else { bo->resv = &bo->ttm_resv; - reservation_object_init(&bo->ttm_resv); } + reservation_object_init(&bo->ttm_resv); atomic_inc(&bo->glob->bo_count); drm_vma_node_reset(&bo->vma_node); bo->priority = 0; diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 78cb99be7146..e7a519f1849b 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -474,6 +474,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, INIT_LIST_HEAD(&fbo->lru); INIT_LIST_HEAD(&fbo->swap); INIT_LIST_HEAD(&fbo->io_reserve_lru); + mutex_init(&fbo->wu_mutex); fbo->moving = NULL; drm_vma_node_reset(&fbo->vma_node); atomic_set(&fbo->cpu_writers, 0); diff --git a/drivers/gpu/drm/ttm/ttm_memory.c b/drivers/gpu/drm/ttm/ttm_memory.c index 29855be96be0..e96374990398 100644 --- a/drivers/gpu/drm/ttm/ttm_memory.c +++ b/drivers/gpu/drm/ttm/ttm_memory.c @@ -546,8 +546,7 @@ int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory, EXPORT_SYMBOL(ttm_mem_global_alloc); int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, - struct page *page, - bool no_wait, bool interruptible) + struct page *page, uint64_t size) { struct ttm_mem_zone *zone = NULL; @@ -564,11 +563,11 @@ int ttm_mem_global_alloc_page(struct ttm_mem_global *glob, if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL) zone = glob->zone_kernel; #endif - return ttm_mem_global_alloc_zone(glob, zone, PAGE_SIZE, no_wait, - interruptible); + return ttm_mem_global_alloc_zone(glob, zone, size, false, false); } -void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page) +void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page, + uint64_t size) { struct ttm_mem_zone *zone = NULL; @@ -579,10 +578,9 @@ void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page) if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL) zone = glob->zone_kernel; #endif - ttm_mem_global_free_zone(glob, zone, PAGE_SIZE); + ttm_mem_global_free_zone(glob, zone, size); } - size_t ttm_round_pot(size_t size) { if ((size & (size - 1)) == 0) diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc.c b/drivers/gpu/drm/ttm/ttm_page_alloc.c index 052e1f102113..316f831ad5f0 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc.c @@ -95,7 +95,7 @@ struct ttm_pool_opts { unsigned small; }; -#define NUM_POOLS 4 +#define NUM_POOLS 6 /** * struct ttm_pool_manager - Holds memory pools for fst allocation @@ -122,6 +122,8 @@ struct ttm_pool_manager { struct ttm_page_pool uc_pool; struct ttm_page_pool wc_pool_dma32; struct ttm_page_pool uc_pool_dma32; + struct ttm_page_pool wc_pool_huge; + struct ttm_page_pool uc_pool_huge; } ; }; }; @@ -256,8 +258,8 @@ static int set_pages_array_uc(struct page **pages, int addrinarray) /** * Select the right pool or requested caching state and ttm flags. */ -static struct ttm_page_pool *ttm_get_pool(int flags, - enum ttm_caching_state cstate) +static struct ttm_page_pool *ttm_get_pool(int flags, bool huge, + enum ttm_caching_state cstate) { int pool_index; @@ -269,9 +271,15 @@ static struct ttm_page_pool *ttm_get_pool(int flags, else pool_index = 0x1; - if (flags & TTM_PAGE_FLAG_DMA32) + if (flags & TTM_PAGE_FLAG_DMA32) { + if (huge) + return NULL; pool_index |= 0x2; + } else if (huge) { + pool_index |= 0x4; + } + return &_manager->pools[pool_index]; } @@ -321,7 +329,7 @@ static int ttm_page_pool_free(struct ttm_page_pool *pool, unsigned nr_free, pages_to_free = kmalloc(npages_to_free * sizeof(struct page *), GFP_KERNEL); if (!pages_to_free) { - pr_err("Failed to allocate memory for pool free operation\n"); + pr_debug("Failed to allocate memory for pool free operation\n"); return 0; } @@ -494,12 +502,14 @@ static void ttm_handle_caching_state_failure(struct list_head *pages, * pages returned in pages array. */ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, - int ttm_flags, enum ttm_caching_state cstate, unsigned count) + int ttm_flags, enum ttm_caching_state cstate, + unsigned count, unsigned order) { struct page **caching_array; struct page *p; int r = 0; - unsigned i, cpages; + unsigned i, j, cpages; + unsigned npages = 1 << order; unsigned max_cpages = min(count, (unsigned)(PAGE_SIZE/sizeof(struct page *))); @@ -507,15 +517,15 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL); if (!caching_array) { - pr_err("Unable to allocate table for new pages\n"); + pr_debug("Unable to allocate table for new pages\n"); return -ENOMEM; } for (i = 0, cpages = 0; i < count; ++i) { - p = alloc_page(gfp_flags); + p = alloc_pages(gfp_flags, order); if (!p) { - pr_err("Unable to get page %u\n", i); + pr_debug("Unable to get page %u\n", i); /* store already allocated pages in the pool after * setting the caching state */ @@ -531,14 +541,18 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, goto out; } + list_add(&p->lru, pages); + #ifdef CONFIG_HIGHMEM /* gfp flags of highmem page should never be dma32 so we * we should be fine in such case */ - if (!PageHighMem(p)) + if (PageHighMem(p)) + continue; + #endif - { - caching_array[cpages++] = p; + for (j = 0; j < npages; ++j) { + caching_array[cpages++] = p++; if (cpages == max_cpages) { r = ttm_set_pages_caching(caching_array, @@ -552,8 +566,6 @@ static int ttm_alloc_new_pages(struct list_head *pages, gfp_t gfp_flags, cpages = 0; } } - - list_add(&p->lru, pages); } if (cpages) { @@ -573,9 +585,9 @@ out: * Fill the given pool if there aren't enough pages and the requested number of * pages is small. */ -static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, - int ttm_flags, enum ttm_caching_state cstate, unsigned count, - unsigned long *irq_flags) +static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, int ttm_flags, + enum ttm_caching_state cstate, + unsigned count, unsigned long *irq_flags) { struct page *p; int r; @@ -605,7 +617,7 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, INIT_LIST_HEAD(&new_pages); r = ttm_alloc_new_pages(&new_pages, pool->gfp_flags, ttm_flags, - cstate, alloc_size); + cstate, alloc_size, 0); spin_lock_irqsave(&pool->lock, *irq_flags); if (!r) { @@ -613,7 +625,7 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, ++pool->nrefills; pool->npages += alloc_size; } else { - pr_err("Failed to fill pool (%p)\n", pool); + pr_debug("Failed to fill pool (%p)\n", pool); /* If we have any pages left put them to the pool. */ list_for_each_entry(p, &new_pages, lru) { ++cpages; @@ -627,22 +639,25 @@ static void ttm_page_pool_fill_locked(struct ttm_page_pool *pool, } /** - * Cut 'count' number of pages from the pool and put them on the return list. + * Allocate pages from the pool and put them on the return list. * - * @return count of pages still required to fulfill the request. + * @return zero for success or negative error code. */ -static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool, - struct list_head *pages, - int ttm_flags, - enum ttm_caching_state cstate, - unsigned count) +static int ttm_page_pool_get_pages(struct ttm_page_pool *pool, + struct list_head *pages, + int ttm_flags, + enum ttm_caching_state cstate, + unsigned count, unsigned order) { unsigned long irq_flags; struct list_head *p; unsigned i; + int r = 0; spin_lock_irqsave(&pool->lock, irq_flags); - ttm_page_pool_fill_locked(pool, ttm_flags, cstate, count, &irq_flags); + if (!order) + ttm_page_pool_fill_locked(pool, ttm_flags, cstate, count, + &irq_flags); if (count >= pool->npages) { /* take all pages from the pool */ @@ -672,32 +687,126 @@ static unsigned ttm_page_pool_get_pages(struct ttm_page_pool *pool, count = 0; out: spin_unlock_irqrestore(&pool->lock, irq_flags); - return count; + + /* clear the pages coming from the pool if requested */ + if (ttm_flags & TTM_PAGE_FLAG_ZERO_ALLOC) { + struct page *page; + + list_for_each_entry(page, pages, lru) { + if (PageHighMem(page)) + clear_highpage(page); + else + clear_page(page_address(page)); + } + } + + /* If pool didn't have enough pages allocate new one. */ + if (count) { + gfp_t gfp_flags = pool->gfp_flags; + + /* set zero flag for page allocation if required */ + if (ttm_flags & TTM_PAGE_FLAG_ZERO_ALLOC) + gfp_flags |= __GFP_ZERO; + + /* ttm_alloc_new_pages doesn't reference pool so we can run + * multiple requests in parallel. + **/ + r = ttm_alloc_new_pages(pages, gfp_flags, ttm_flags, cstate, + count, order); + } + + return r; } /* Put all pages in pages list to correct pool to wait for reuse */ static void ttm_put_pages(struct page **pages, unsigned npages, int flags, enum ttm_caching_state cstate) { + struct ttm_page_pool *pool = ttm_get_pool(flags, false, cstate); +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + struct ttm_page_pool *huge = ttm_get_pool(flags, true, cstate); +#endif unsigned long irq_flags; - struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); unsigned i; if (pool == NULL) { /* No pool for this memory type so free the pages */ - for (i = 0; i < npages; i++) { - if (pages[i]) { - if (page_count(pages[i]) != 1) - pr_err("Erroneous page count. Leaking pages.\n"); - __free_page(pages[i]); - pages[i] = NULL; + i = 0; + while (i < npages) { +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + struct page *p = pages[i]; +#endif + unsigned order = 0, j; + + if (!pages[i]) { + ++i; + continue; + } + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + for (j = 0; j < HPAGE_PMD_NR; ++j) + if (p++ != pages[i + j]) + break; + + if (j == HPAGE_PMD_NR) + order = HPAGE_PMD_ORDER; +#endif + + if (page_count(pages[i]) != 1) + pr_err("Erroneous page count. Leaking pages.\n"); + __free_pages(pages[i], order); + + j = 1 << order; + while (j) { + pages[i++] = NULL; + --j; } } return; } + i = 0; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (huge) { + unsigned max_size, n2free; + + spin_lock_irqsave(&huge->lock, irq_flags); + while (i < npages) { + struct page *p = pages[i]; + unsigned j; + + if (!p) + break; + + for (j = 0; j < HPAGE_PMD_NR; ++j) + if (p++ != pages[i + j]) + break; + + if (j != HPAGE_PMD_NR) + break; + + list_add_tail(&pages[i]->lru, &huge->list); + + for (j = 0; j < HPAGE_PMD_NR; ++j) + pages[i++] = NULL; + huge->npages++; + } + + /* Check that we don't go over the pool limit */ + max_size = _manager->options.max_size; + max_size /= HPAGE_PMD_NR; + if (huge->npages > max_size) + n2free = huge->npages - max_size; + else + n2free = 0; + spin_unlock_irqrestore(&huge->lock, irq_flags); + if (n2free) + ttm_page_pool_free(huge, n2free, false); + } +#endif + spin_lock_irqsave(&pool->lock, irq_flags); - for (i = 0; i < npages; i++) { + while (i < npages) { if (pages[i]) { if (page_count(pages[i]) != 1) pr_err("Erroneous page count. Leaking pages.\n"); @@ -705,6 +814,7 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags, pages[i] = NULL; pool->npages++; } + ++i; } /* Check that we don't go over the pool limit */ npages = 0; @@ -727,75 +837,96 @@ static void ttm_put_pages(struct page **pages, unsigned npages, int flags, static int ttm_get_pages(struct page **pages, unsigned npages, int flags, enum ttm_caching_state cstate) { - struct ttm_page_pool *pool = ttm_get_pool(flags, cstate); + struct ttm_page_pool *pool = ttm_get_pool(flags, false, cstate); +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + struct ttm_page_pool *huge = ttm_get_pool(flags, true, cstate); +#endif struct list_head plist; struct page *p = NULL; - gfp_t gfp_flags = GFP_USER; unsigned count; int r; - /* set zero flag for page allocation if required */ - if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) - gfp_flags |= __GFP_ZERO; - /* No pool for cached pages */ if (pool == NULL) { + gfp_t gfp_flags = GFP_USER; + unsigned i; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + unsigned j; +#endif + + /* set zero flag for page allocation if required */ + if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) + gfp_flags |= __GFP_ZERO; + if (flags & TTM_PAGE_FLAG_DMA32) gfp_flags |= GFP_DMA32; else gfp_flags |= GFP_HIGHUSER; - for (r = 0; r < npages; ++r) { + i = 0; +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + while (npages >= HPAGE_PMD_NR) { + gfp_t huge_flags = gfp_flags; + + huge_flags |= GFP_TRANSHUGE; + huge_flags &= ~__GFP_MOVABLE; + huge_flags &= ~__GFP_COMP; + p = alloc_pages(huge_flags, HPAGE_PMD_ORDER); + if (!p) + break; + + for (j = 0; j < HPAGE_PMD_NR; ++j) + pages[i++] = p++; + + npages -= HPAGE_PMD_NR; + } +#endif + + while (npages) { p = alloc_page(gfp_flags); if (!p) { - - pr_err("Unable to allocate page\n"); + pr_debug("Unable to allocate page\n"); return -ENOMEM; } - pages[r] = p; + pages[i++] = p; + --npages; } return 0; } - /* combine zero flag to pool flags */ - gfp_flags |= pool->gfp_flags; - - /* First we take pages from the pool */ - INIT_LIST_HEAD(&plist); - npages = ttm_page_pool_get_pages(pool, &plist, flags, cstate, npages); count = 0; - list_for_each_entry(p, &plist, lru) { - pages[count++] = p; - } - /* clear the pages coming from the pool if requested */ - if (flags & TTM_PAGE_FLAG_ZERO_ALLOC) { +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (huge && npages >= HPAGE_PMD_NR) { + INIT_LIST_HEAD(&plist); + ttm_page_pool_get_pages(huge, &plist, flags, cstate, + npages / HPAGE_PMD_NR, + HPAGE_PMD_ORDER); + list_for_each_entry(p, &plist, lru) { - if (PageHighMem(p)) - clear_highpage(p); - else - clear_page(page_address(p)); + unsigned j; + + for (j = 0; j < HPAGE_PMD_NR; ++j) + pages[count++] = &p[j]; } } +#endif - /* If pool didn't have enough pages allocate new one. */ - if (npages > 0) { - /* ttm_alloc_new_pages doesn't reference pool so we can run - * multiple requests in parallel. - **/ - INIT_LIST_HEAD(&plist); - r = ttm_alloc_new_pages(&plist, gfp_flags, flags, cstate, npages); - list_for_each_entry(p, &plist, lru) { - pages[count++] = p; - } - if (r) { - /* If there is any pages in the list put them back to - * the pool. */ - pr_err("Failed to allocate extra pages for large request\n"); - ttm_put_pages(pages, count, flags, cstate); - return r; - } + INIT_LIST_HEAD(&plist); + r = ttm_page_pool_get_pages(pool, &plist, flags, cstate, + npages - count, 0); + + list_for_each_entry(p, &plist, lru) + pages[count++] = p; + + if (r) { + /* If there is any pages in the list put them back to + * the pool. + */ + pr_debug("Failed to allocate extra pages for large request\n"); + ttm_put_pages(pages, count, flags, cstate); + return r; } return 0; @@ -832,6 +963,14 @@ int ttm_page_alloc_init(struct ttm_mem_global *glob, unsigned max_pages) ttm_page_pool_init_locked(&_manager->uc_pool_dma32, GFP_USER | GFP_DMA32, "uc dma"); + ttm_page_pool_init_locked(&_manager->wc_pool_huge, + GFP_TRANSHUGE & ~(__GFP_MOVABLE | __GFP_COMP), + "wc huge"); + + ttm_page_pool_init_locked(&_manager->uc_pool_huge, + GFP_TRANSHUGE & ~(__GFP_MOVABLE | __GFP_COMP) + , "uc huge"); + _manager->options.max_size = max_pages; _manager->options.small = SMALL_ALLOCATION; _manager->options.alloc_size = NUM_PAGES_TO_ALLOC; @@ -873,17 +1012,16 @@ int ttm_pool_populate(struct ttm_tt *ttm) if (ttm->state != tt_unpopulated) return 0; - for (i = 0; i < ttm->num_pages; ++i) { - ret = ttm_get_pages(&ttm->pages[i], 1, - ttm->page_flags, - ttm->caching_state); - if (ret != 0) { - ttm_pool_unpopulate(ttm); - return -ENOMEM; - } + ret = ttm_get_pages(ttm->pages, ttm->num_pages, ttm->page_flags, + ttm->caching_state); + if (unlikely(ret != 0)) { + ttm_pool_unpopulate(ttm); + return ret; + } + for (i = 0; i < ttm->num_pages; ++i) { ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i], - false, false); + PAGE_SIZE); if (unlikely(ret != 0)) { ttm_pool_unpopulate(ttm); return -ENOMEM; @@ -908,14 +1046,14 @@ void ttm_pool_unpopulate(struct ttm_tt *ttm) unsigned i; for (i = 0; i < ttm->num_pages; ++i) { - if (ttm->pages[i]) { - ttm_mem_global_free_page(ttm->glob->mem_glob, - ttm->pages[i]); - ttm_put_pages(&ttm->pages[i], 1, - ttm->page_flags, - ttm->caching_state); - } + if (!ttm->pages[i]) + continue; + + ttm_mem_global_free_page(ttm->glob->mem_glob, ttm->pages[i], + PAGE_SIZE); } + ttm_put_pages(ttm->pages, ttm->num_pages, ttm->page_flags, + ttm->caching_state); ttm->state = tt_unpopulated; } EXPORT_SYMBOL(ttm_pool_unpopulate); @@ -923,16 +1061,26 @@ EXPORT_SYMBOL(ttm_pool_unpopulate); #if defined(CONFIG_SWIOTLB) || defined(CONFIG_INTEL_IOMMU) int ttm_populate_and_map_pages(struct device *dev, struct ttm_dma_tt *tt) { - unsigned i; + unsigned i, j; int r; r = ttm_pool_populate(&tt->ttm); if (r) return r; - for (i = 0; i < tt->ttm.num_pages; i++) { + for (i = 0; i < tt->ttm.num_pages; ++i) { + struct page *p = tt->ttm.pages[i]; + size_t num_pages = 1; + + for (j = i + 1; j < tt->ttm.num_pages; ++j) { + if (++p != tt->ttm.pages[j]) + break; + + ++num_pages; + } + tt->dma_address[i] = dma_map_page(dev, tt->ttm.pages[i], - 0, PAGE_SIZE, + 0, num_pages * PAGE_SIZE, DMA_BIDIRECTIONAL); if (dma_mapping_error(dev, tt->dma_address[i])) { while (i--) { @@ -943,6 +1091,11 @@ int ttm_populate_and_map_pages(struct device *dev, struct ttm_dma_tt *tt) ttm_pool_unpopulate(&tt->ttm); return -EFAULT; } + + for (j = 1; j < num_pages; ++j) { + tt->dma_address[i + 1] = tt->dma_address[i] + PAGE_SIZE; + ++i; + } } return 0; } @@ -950,13 +1103,28 @@ EXPORT_SYMBOL(ttm_populate_and_map_pages); void ttm_unmap_and_unpopulate_pages(struct device *dev, struct ttm_dma_tt *tt) { - unsigned i; - - for (i = 0; i < tt->ttm.num_pages; i++) { - if (tt->dma_address[i]) { - dma_unmap_page(dev, tt->dma_address[i], - PAGE_SIZE, DMA_BIDIRECTIONAL); + unsigned i, j; + + for (i = 0; i < tt->ttm.num_pages;) { + struct page *p = tt->ttm.pages[i]; + size_t num_pages = 1; + + if (!tt->dma_address[i] || !tt->ttm.pages[i]) { + ++i; + continue; } + + for (j = i + 1; j < tt->ttm.num_pages; ++j) { + if (++p != tt->ttm.pages[j]) + break; + + ++num_pages; + } + + dma_unmap_page(dev, tt->dma_address[i], num_pages * PAGE_SIZE, + DMA_BIDIRECTIONAL); + + i += num_pages; } ttm_pool_unpopulate(&tt->ttm); } @@ -972,12 +1140,12 @@ int ttm_page_alloc_debugfs(struct seq_file *m, void *data) seq_printf(m, "No pool allocator running.\n"); return 0; } - seq_printf(m, "%6s %12s %13s %8s\n", + seq_printf(m, "%7s %12s %13s %8s\n", h[0], h[1], h[2], h[3]); for (i = 0; i < NUM_POOLS; ++i) { p = &_manager->pools[i]; - seq_printf(m, "%6s %12ld %13ld %8d\n", + seq_printf(m, "%7s %12ld %13ld %8d\n", p->name, p->nrefills, p->nfrees, p->npages); } diff --git a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c index 06bc14b55e66..6b2627fe9bc1 100644 --- a/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c +++ b/drivers/gpu/drm/ttm/ttm_page_alloc_dma.c @@ -60,21 +60,25 @@ #define NUM_PAGES_TO_ALLOC (PAGE_SIZE/sizeof(struct page *)) #define SMALL_ALLOCATION 4 #define FREE_ALL_PAGES (~0U) +#define VADDR_FLAG_HUGE_POOL 1UL enum pool_type { IS_UNDEFINED = 0, IS_WC = 1 << 1, IS_UC = 1 << 2, IS_CACHED = 1 << 3, - IS_DMA32 = 1 << 4 + IS_DMA32 = 1 << 4, + IS_HUGE = 1 << 5 }; /* - * The pool structure. There are usually six pools: + * The pool structure. There are up to nine pools: * - generic (not restricted to DMA32): * - write combined, uncached, cached. * - dma32 (up to 2^32 - so up 4GB): * - write combined, uncached, cached. + * - huge (not restricted to DMA32): + * - write combined, uncached, cached. * for each 'struct device'. The 'cached' is for pages that are actively used. * The other ones can be shrunk by the shrinker API if neccessary. * @pools: The 'struct device->dma_pools' link. @@ -114,13 +118,14 @@ struct dma_pool { * The accounting page keeping track of the allocated page along with * the DMA address. * @page_list: The link to the 'page_list' in 'struct dma_pool'. - * @vaddr: The virtual address of the page + * @vaddr: The virtual address of the page and a flag if the page belongs to a + * huge pool * @dma: The bus address of the page. If the page is not allocated * via the DMA API, it will be -1. */ struct dma_page { struct list_head page_list; - void *vaddr; + unsigned long vaddr; struct page *p; dma_addr_t dma; }; @@ -319,7 +324,8 @@ static int ttm_set_pages_caching(struct dma_pool *pool, static void __ttm_dma_free_page(struct dma_pool *pool, struct dma_page *d_page) { dma_addr_t dma = d_page->dma; - dma_free_coherent(pool->dev, pool->size, d_page->vaddr, dma); + d_page->vaddr &= ~VADDR_FLAG_HUGE_POOL; + dma_free_coherent(pool->dev, pool->size, (void *)d_page->vaddr, dma); kfree(d_page); d_page = NULL; @@ -327,19 +333,22 @@ static void __ttm_dma_free_page(struct dma_pool *pool, struct dma_page *d_page) static struct dma_page *__ttm_dma_alloc_page(struct dma_pool *pool) { struct dma_page *d_page; + void *vaddr; d_page = kmalloc(sizeof(struct dma_page), GFP_KERNEL); if (!d_page) return NULL; - d_page->vaddr = dma_alloc_coherent(pool->dev, pool->size, - &d_page->dma, - pool->gfp_flags); - if (d_page->vaddr) { - if (is_vmalloc_addr(d_page->vaddr)) - d_page->p = vmalloc_to_page(d_page->vaddr); + vaddr = dma_alloc_coherent(pool->dev, pool->size, &d_page->dma, + pool->gfp_flags); + if (vaddr) { + if (is_vmalloc_addr(vaddr)) + d_page->p = vmalloc_to_page(vaddr); else - d_page->p = virt_to_page(d_page->vaddr); + d_page->p = virt_to_page(vaddr); + d_page->vaddr = (unsigned long)vaddr; + if (pool->type & IS_HUGE) + d_page->vaddr |= VADDR_FLAG_HUGE_POOL; } else { kfree(d_page); d_page = NULL; @@ -371,11 +380,40 @@ static void ttm_pool_update_free_locked(struct dma_pool *pool, } /* set memory back to wb and free the pages. */ +static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) +{ + struct page *page = d_page->p; + unsigned i, num_pages; + int ret; + + /* Don't set WB on WB page pool. */ + if (!(pool->type & IS_CACHED)) { + num_pages = pool->size / PAGE_SIZE; + for (i = 0; i < num_pages; ++i, ++page) { + ret = set_pages_array_wb(&page, 1); + if (ret) { + pr_err("%s: Failed to set %d pages to wb!\n", + pool->dev_name, 1); + } + } + } + + list_del(&d_page->page_list); + __ttm_dma_free_page(pool, d_page); +} + static void ttm_dma_pages_put(struct dma_pool *pool, struct list_head *d_pages, struct page *pages[], unsigned npages) { struct dma_page *d_page, *tmp; + if (pool->type & IS_HUGE) { + list_for_each_entry_safe(d_page, tmp, d_pages, page_list) + ttm_dma_page_put(pool, d_page); + + return; + } + /* Don't set WB on WB page pool. */ if (npages && !(pool->type & IS_CACHED) && set_pages_array_wb(pages, npages)) @@ -388,17 +426,6 @@ static void ttm_dma_pages_put(struct dma_pool *pool, struct list_head *d_pages, } } -static void ttm_dma_page_put(struct dma_pool *pool, struct dma_page *d_page) -{ - /* Don't set WB on WB page pool. */ - if (!(pool->type & IS_CACHED) && set_pages_array_wb(&d_page->p, 1)) - pr_err("%s: Failed to set %d pages to wb!\n", - pool->dev_name, 1); - - list_del(&d_page->page_list); - __ttm_dma_free_page(pool, d_page); -} - /* * Free pages from pool. * @@ -436,7 +463,7 @@ static unsigned ttm_dma_page_pool_free(struct dma_pool *pool, unsigned nr_free, GFP_KERNEL); if (!pages_to_free) { - pr_err("%s: Failed to allocate memory for pool free operation\n", + pr_debug("%s: Failed to allocate memory for pool free operation\n", pool->dev_name); return 0; } @@ -567,8 +594,8 @@ static int ttm_dma_pool_match(struct device *dev, void *res, void *match_data) static struct dma_pool *ttm_dma_pool_init(struct device *dev, gfp_t flags, enum pool_type type) { - char *n[] = {"wc", "uc", "cached", " dma32", "unknown",}; - enum pool_type t[] = {IS_WC, IS_UC, IS_CACHED, IS_DMA32, IS_UNDEFINED}; + const char *n[] = {"wc", "uc", "cached", " dma32", "huge"}; + enum pool_type t[] = {IS_WC, IS_UC, IS_CACHED, IS_DMA32, IS_HUGE}; struct device_pools *sec_pool = NULL; struct dma_pool *pool = NULL, **ptr; unsigned i; @@ -605,11 +632,18 @@ static struct dma_pool *ttm_dma_pool_init(struct device *dev, gfp_t flags, pool->npages_free = pool->npages_in_use = 0; pool->nfrees = 0; pool->gfp_flags = flags; - pool->size = PAGE_SIZE; + if (type & IS_HUGE) +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + pool->size = HPAGE_PMD_SIZE; +#else + BUG(); +#endif + else + pool->size = PAGE_SIZE; pool->type = type; pool->nrefills = 0; p = pool->name; - for (i = 0; i < 5; i++) { + for (i = 0; i < ARRAY_SIZE(t); i++) { if (type & t[i]) { p += snprintf(p, sizeof(pool->name) - (p - pool->name), "%s", n[i]); @@ -713,7 +747,7 @@ static int ttm_dma_pool_alloc_new_pages(struct dma_pool *pool, struct dma_page *dma_p; struct page *p; int r = 0; - unsigned i, cpages; + unsigned i, j, npages, cpages; unsigned max_cpages = min(count, (unsigned)(PAGE_SIZE/sizeof(struct page *))); @@ -721,7 +755,7 @@ static int ttm_dma_pool_alloc_new_pages(struct dma_pool *pool, caching_array = kmalloc(max_cpages*sizeof(struct page *), GFP_KERNEL); if (!caching_array) { - pr_err("%s: Unable to allocate table for new pages\n", + pr_debug("%s: Unable to allocate table for new pages\n", pool->dev_name); return -ENOMEM; } @@ -734,8 +768,8 @@ static int ttm_dma_pool_alloc_new_pages(struct dma_pool *pool, for (i = 0, cpages = 0; i < count; ++i) { dma_p = __ttm_dma_alloc_page(pool); if (!dma_p) { - pr_err("%s: Unable to get page %u\n", - pool->dev_name, i); + pr_debug("%s: Unable to get page %u\n", + pool->dev_name, i); /* store already allocated pages in the pool after * setting the caching state */ @@ -751,28 +785,32 @@ static int ttm_dma_pool_alloc_new_pages(struct dma_pool *pool, goto out; } p = dma_p->p; + list_add(&dma_p->page_list, d_pages); + #ifdef CONFIG_HIGHMEM /* gfp flags of highmem page should never be dma32 so we * we should be fine in such case */ - if (!PageHighMem(p)) + if (PageHighMem(p)) + continue; #endif - { - caching_array[cpages++] = p; + + npages = pool->size / PAGE_SIZE; + for (j = 0; j < npages; ++j) { + caching_array[cpages++] = p + j; if (cpages == max_cpages) { /* Note: Cannot hold the spinlock */ r = ttm_set_pages_caching(pool, caching_array, - cpages); + cpages); if (r) { ttm_dma_handle_caching_state_failure( - pool, d_pages, caching_array, - cpages); + pool, d_pages, caching_array, + cpages); goto out; } cpages = 0; } } - list_add(&dma_p->page_list, d_pages); } if (cpages) { @@ -817,8 +855,8 @@ static int ttm_dma_page_pool_fill_locked(struct dma_pool *pool, struct dma_page *d_page; unsigned cpages = 0; - pr_err("%s: Failed to fill %s pool (r:%d)!\n", - pool->dev_name, pool->name, r); + pr_debug("%s: Failed to fill %s pool (r:%d)!\n", + pool->dev_name, pool->name, r); list_for_each_entry(d_page, &d_pages, page_list) { cpages++; @@ -860,6 +898,27 @@ static int ttm_dma_pool_get_pages(struct dma_pool *pool, return r; } +static gfp_t ttm_dma_pool_gfp_flags(struct ttm_dma_tt *ttm_dma, bool huge) +{ + struct ttm_tt *ttm = &ttm_dma->ttm; + gfp_t gfp_flags; + + if (ttm->page_flags & TTM_PAGE_FLAG_DMA32) + gfp_flags = GFP_USER | GFP_DMA32; + else + gfp_flags = GFP_HIGHUSER; + if (ttm->page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) + gfp_flags |= __GFP_ZERO; + + if (huge) { + gfp_flags |= GFP_TRANSHUGE; + gfp_flags &= ~__GFP_MOVABLE; + gfp_flags &= ~__GFP_COMP; + } + + return gfp_flags; +} + /* * On success pages list will hold count number of correctly * cached pages. On failure will hold the negative return value (-ENOMEM, etc). @@ -868,6 +927,7 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev) { struct ttm_tt *ttm = &ttm_dma->ttm; struct ttm_mem_global *mem_glob = ttm->glob->mem_glob; + unsigned long num_pages = ttm->num_pages; struct dma_pool *pool; enum pool_type type; unsigned i; @@ -876,26 +936,61 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev) if (ttm->state != tt_unpopulated) return 0; + INIT_LIST_HEAD(&ttm_dma->pages_list); + i = 0; + type = ttm_to_type(ttm->page_flags, ttm->caching_state); - pool = ttm_dma_find_pool(dev, type); + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + if (ttm->page_flags & TTM_PAGE_FLAG_DMA32) + goto skip_huge; + + pool = ttm_dma_find_pool(dev, type | IS_HUGE); if (!pool) { - gfp_t gfp_flags; + gfp_t gfp_flags = ttm_dma_pool_gfp_flags(ttm_dma, true); - if (ttm->page_flags & TTM_PAGE_FLAG_DMA32) - gfp_flags = GFP_USER | GFP_DMA32; - else - gfp_flags = GFP_HIGHUSER; - if (ttm->page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) - gfp_flags |= __GFP_ZERO; + pool = ttm_dma_pool_init(dev, gfp_flags, type | IS_HUGE); + if (IS_ERR_OR_NULL(pool)) + goto skip_huge; + } - pool = ttm_dma_pool_init(dev, gfp_flags, type); - if (IS_ERR_OR_NULL(pool)) { + while (num_pages >= HPAGE_PMD_NR) { + unsigned j; + + ret = ttm_dma_pool_get_pages(pool, ttm_dma, i); + if (ret != 0) + break; + + ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i], + pool->size); + if (unlikely(ret != 0)) { + ttm_dma_unpopulate(ttm_dma, dev); return -ENOMEM; } + + for (j = i + 1; j < (i + HPAGE_PMD_NR); ++j) { + ttm->pages[j] = ttm->pages[j - 1] + 1; + ttm_dma->dma_address[j] = ttm_dma->dma_address[j - 1] + + PAGE_SIZE; + } + + i += HPAGE_PMD_NR; + num_pages -= HPAGE_PMD_NR; } - INIT_LIST_HEAD(&ttm_dma->pages_list); - for (i = 0; i < ttm->num_pages; ++i) { +skip_huge: +#endif + + pool = ttm_dma_find_pool(dev, type); + if (!pool) { + gfp_t gfp_flags = ttm_dma_pool_gfp_flags(ttm_dma, false); + + pool = ttm_dma_pool_init(dev, gfp_flags, type); + if (IS_ERR_OR_NULL(pool)) + return -ENOMEM; + } + + while (num_pages) { ret = ttm_dma_pool_get_pages(pool, ttm_dma, i); if (ret != 0) { ttm_dma_unpopulate(ttm_dma, dev); @@ -903,11 +998,14 @@ int ttm_dma_populate(struct ttm_dma_tt *ttm_dma, struct device *dev) } ret = ttm_mem_global_alloc_page(mem_glob, ttm->pages[i], - false, false); + pool->size); if (unlikely(ret != 0)) { ttm_dma_unpopulate(ttm_dma, dev); return -ENOMEM; } + + ++i; + --num_pages; } if (unlikely(ttm->page_flags & TTM_PAGE_FLAG_SWAPPED)) { @@ -931,10 +1029,33 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) struct dma_page *d_page, *next; enum pool_type type; bool is_cached = false; - unsigned count = 0, i, npages = 0; + unsigned count, i, npages = 0; unsigned long irq_flags; type = ttm_to_type(ttm->page_flags, ttm->caching_state); + +#ifdef CONFIG_TRANSPARENT_HUGEPAGE + pool = ttm_dma_find_pool(dev, type | IS_HUGE); + if (pool) { + count = 0; + list_for_each_entry_safe(d_page, next, &ttm_dma->pages_list, + page_list) { + if (!(d_page->vaddr & VADDR_FLAG_HUGE_POOL)) + continue; + + count++; + ttm_mem_global_free_page(ttm->glob->mem_glob, + d_page->p, pool->size); + ttm_dma_page_put(pool, d_page); + } + + spin_lock_irqsave(&pool->lock, irq_flags); + pool->npages_in_use -= count; + pool->nfrees += count; + spin_unlock_irqrestore(&pool->lock, irq_flags); + } +#endif + pool = ttm_dma_find_pool(dev, type); if (!pool) return; @@ -943,6 +1064,7 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) ttm_to_type(ttm->page_flags, tt_cached)) == pool); /* make sure pages array match list and count number of pages */ + count = 0; list_for_each_entry(d_page, &ttm_dma->pages_list, page_list) { ttm->pages[count] = d_page->p; count++; @@ -968,13 +1090,13 @@ void ttm_dma_unpopulate(struct ttm_dma_tt *ttm_dma, struct device *dev) if (is_cached) { list_for_each_entry_safe(d_page, next, &ttm_dma->pages_list, page_list) { ttm_mem_global_free_page(ttm->glob->mem_glob, - d_page->p); + d_page->p, pool->size); ttm_dma_page_put(pool, d_page); } } else { for (i = 0; i < count; i++) { ttm_mem_global_free_page(ttm->glob->mem_glob, - ttm->pages[i]); + ttm->pages[i], pool->size); } } diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index c0bbd1ce15f0..c3dc1fd20cb4 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -148,7 +148,7 @@ static struct drm_encoder* udl_best_single_encoder(struct drm_connector *connector) { int enc_id = connector->encoder_ids[0]; - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); } static int udl_connector_set_property(struct drm_connector *connector, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 5ec24fd801cd..01be355525e4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -286,7 +286,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, drm_modeset_lock_all(dev); - fb = drm_framebuffer_lookup(dev, arg->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id); if (!fb) { DRM_ERROR("Invalid framebuffer id.\n"); ret = -ENOENT; @@ -369,7 +369,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, drm_modeset_lock_all(dev); - fb = drm_framebuffer_lookup(dev, arg->fb_id); + fb = drm_framebuffer_lookup(dev, file_priv, arg->fb_id); if (!fb) { DRM_ERROR("Invalid framebuffer id.\n"); ret = -ENOENT; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 13ac2c5a04ee..a2a93d7e2a04 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1712,7 +1712,7 @@ int vmw_kms_cursor_bypass_ioctl(struct drm_device *dev, void *data, return 0; } - crtc = drm_crtc_find(dev, arg->crtc_id); + crtc = drm_crtc_find(dev, file_priv, arg->crtc_id); if (!crtc) { ret = -ENOENT; goto out; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index d1552d3e0652..bc5f6026573d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -360,8 +360,8 @@ static int vmw_sou_crtc_page_flip(struct drm_crtc *crtc, ret = vmw_event_fence_action_queue(file_priv, fence, &event->base, - &event->event.tv_sec, - &event->event.tv_usec, + &event->event.vbl.tv_sec, + &event->event.vbl.tv_usec, true); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index ca3afae2db1f..90b5437fd787 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -549,8 +549,8 @@ static int vmw_stdu_crtc_page_flip(struct drm_crtc *crtc, ret = vmw_event_fence_action_queue(file_priv, fence, &event->base, - &event->event.tv_sec, - &event->event.tv_usec, + &event->event.vbl.tv_sec, + &event->event.vbl.tv_usec, true); vmw_fence_obj_unreference(&fence); } else { diff --git a/drivers/gpu/host1x/Makefile b/drivers/gpu/host1x/Makefile index a1d9974cfcb5..4fb61bd57aee 100644 --- a/drivers/gpu/host1x/Makefile +++ b/drivers/gpu/host1x/Makefile @@ -11,6 +11,7 @@ host1x-y = \ hw/host1x01.o \ hw/host1x02.o \ hw/host1x04.o \ - hw/host1x05.o + hw/host1x05.o \ + hw/host1x06.o obj-$(CONFIG_TEGRA_HOST1X) += host1x.o diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index f9cde03030fd..66ea5acee820 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -403,12 +403,13 @@ static int host1x_device_add(struct host1x *host1x, device->dev.coherent_dma_mask = host1x->dev->coherent_dma_mask; device->dev.dma_mask = &device->dev.coherent_dma_mask; dev_set_name(&device->dev, "%s", driver->driver.name); - of_dma_configure(&device->dev, host1x->dev->of_node); device->dev.release = host1x_device_release; device->dev.of_node = host1x->dev->of_node; device->dev.bus = &host1x_bus_type; device->dev.parent = host1x->dev; + of_dma_configure(&device->dev, host1x->dev->of_node); + err = host1x_device_parse_dt(device, driver); if (err < 0) { kfree(device); diff --git a/drivers/gpu/host1x/channel.c b/drivers/gpu/host1x/channel.c index db9b91d1384c..2fb93c27c1d9 100644 --- a/drivers/gpu/host1x/channel.c +++ b/drivers/gpu/host1x/channel.c @@ -128,8 +128,7 @@ static struct host1x_channel *acquire_unused_channel(struct host1x *host) * host1x_channel_request() - Allocate a channel * @device: Host1x unit this channel will be used to send commands to * - * Allocates a new host1x channel for @device. If there are no free channels, - * this will sleep until one becomes available. May return NULL if CDMA + * Allocates a new host1x channel for @device. May return NULL if CDMA * initialization fails. */ struct host1x_channel *host1x_channel_request(struct device *dev) diff --git a/drivers/gpu/host1x/debug.c b/drivers/gpu/host1x/debug.c index 2aae0e63214c..dc77ec452ffc 100644 --- a/drivers/gpu/host1x/debug.c +++ b/drivers/gpu/host1x/debug.c @@ -40,7 +40,19 @@ void host1x_debug_output(struct output *o, const char *fmt, ...) len = vsnprintf(o->buf, sizeof(o->buf), fmt, args); va_end(args); - o->fn(o->ctx, o->buf, len); + o->fn(o->ctx, o->buf, len, false); +} + +void host1x_debug_cont(struct output *o, const char *fmt, ...) +{ + va_list args; + int len; + + va_start(args, fmt); + len = vsnprintf(o->buf, sizeof(o->buf), fmt, args); + va_end(args); + + o->fn(o->ctx, o->buf, len, true); } static int show_channel(struct host1x_channel *ch, void *data, bool show_fifo) diff --git a/drivers/gpu/host1x/debug.h b/drivers/gpu/host1x/debug.h index 4595b2e0799f..990cce47e737 100644 --- a/drivers/gpu/host1x/debug.h +++ b/drivers/gpu/host1x/debug.h @@ -24,22 +24,28 @@ struct host1x; struct output { - void (*fn)(void *ctx, const char *str, size_t len); + void (*fn)(void *ctx, const char *str, size_t len, bool cont); void *ctx; char buf[256]; }; -static inline void write_to_seqfile(void *ctx, const char *str, size_t len) +static inline void write_to_seqfile(void *ctx, const char *str, size_t len, + bool cont) { seq_write((struct seq_file *)ctx, str, len); } -static inline void write_to_printk(void *ctx, const char *str, size_t len) +static inline void write_to_printk(void *ctx, const char *str, size_t len, + bool cont) { - pr_info("%s", str); + if (cont) + pr_cont("%s", str); + else + pr_info("%s", str); } void __printf(2, 3) host1x_debug_output(struct output *o, const char *fmt, ...); +void __printf(2, 3) host1x_debug_cont(struct output *o, const char *fmt, ...); extern unsigned int host1x_debug_trace_cmdbuf; diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c index 7f22c5c37660..773d6337aa30 100644 --- a/drivers/gpu/host1x/dev.c +++ b/drivers/gpu/host1x/dev.c @@ -39,6 +39,17 @@ #include "hw/host1x02.h" #include "hw/host1x04.h" #include "hw/host1x05.h" +#include "hw/host1x06.h" + +void host1x_hypervisor_writel(struct host1x *host1x, u32 v, u32 r) +{ + writel(v, host1x->hv_regs + r); +} + +u32 host1x_hypervisor_readl(struct host1x *host1x, u32 r) +{ + return readl(host1x->hv_regs + r); +} void host1x_sync_writel(struct host1x *host1x, u32 v, u32 r) { @@ -104,7 +115,19 @@ static const struct host1x_info host1x05_info = { .dma_mask = DMA_BIT_MASK(34), }; +static const struct host1x_info host1x06_info = { + .nb_channels = 63, + .nb_pts = 576, + .nb_mlocks = 24, + .nb_bases = 16, + .init = host1x06_init, + .sync_offset = 0x0, + .dma_mask = DMA_BIT_MASK(34), + .has_hypervisor = true, +}; + static const struct of_device_id host1x_of_match[] = { + { .compatible = "nvidia,tegra186-host1x", .data = &host1x06_info, }, { .compatible = "nvidia,tegra210-host1x", .data = &host1x05_info, }, { .compatible = "nvidia,tegra124-host1x", .data = &host1x04_info, }, { .compatible = "nvidia,tegra114-host1x", .data = &host1x02_info, }, @@ -116,20 +139,37 @@ MODULE_DEVICE_TABLE(of, host1x_of_match); static int host1x_probe(struct platform_device *pdev) { - const struct of_device_id *id; struct host1x *host; - struct resource *regs; + struct resource *regs, *hv_regs = NULL; int syncpt_irq; int err; - id = of_match_device(host1x_of_match, &pdev->dev); - if (!id) - return -EINVAL; + host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); + if (!host) + return -ENOMEM; - regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!regs) { - dev_err(&pdev->dev, "failed to get registers\n"); - return -ENXIO; + host->info = of_device_get_match_data(&pdev->dev); + + if (host->info->has_hypervisor) { + regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vm"); + if (!regs) { + dev_err(&pdev->dev, "failed to get vm registers\n"); + return -ENXIO; + } + + hv_regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, + "hypervisor"); + if (!hv_regs) { + dev_err(&pdev->dev, + "failed to get hypervisor registers\n"); + return -ENXIO; + } + } else { + regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!regs) { + dev_err(&pdev->dev, "failed to get registers\n"); + return -ENXIO; + } } syncpt_irq = platform_get_irq(pdev, 0); @@ -138,15 +178,10 @@ static int host1x_probe(struct platform_device *pdev) return syncpt_irq; } - host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL); - if (!host) - return -ENOMEM; - mutex_init(&host->devices_lock); INIT_LIST_HEAD(&host->devices); INIT_LIST_HEAD(&host->list); host->dev = &pdev->dev; - host->info = id->data; /* set common host1x device data */ platform_set_drvdata(pdev, host); @@ -155,6 +190,12 @@ static int host1x_probe(struct platform_device *pdev) if (IS_ERR(host->regs)) return PTR_ERR(host->regs); + if (host->info->has_hypervisor) { + host->hv_regs = devm_ioremap_resource(&pdev->dev, hv_regs); + if (IS_ERR(host->hv_regs)) + return PTR_ERR(host->hv_regs); + } + dma_set_mask_and_coherent(host->dev, host->info->dma_mask); if (host->info->init) { diff --git a/drivers/gpu/host1x/dev.h b/drivers/gpu/host1x/dev.h index ffdbc15b749b..502769726480 100644 --- a/drivers/gpu/host1x/dev.h +++ b/drivers/gpu/host1x/dev.h @@ -79,6 +79,9 @@ struct host1x_syncpt_ops { u32 (*load)(struct host1x_syncpt *syncpt); int (*cpu_incr)(struct host1x_syncpt *syncpt); int (*patch_wait)(struct host1x_syncpt *syncpt, void *patch_addr); + void (*assign_to_channel)(struct host1x_syncpt *syncpt, + struct host1x_channel *channel); + void (*enable_protection)(struct host1x *host); }; struct host1x_intr_ops { @@ -100,12 +103,14 @@ struct host1x_info { int (*init)(struct host1x *host1x); /* initialize per SoC ops */ unsigned int sync_offset; /* offset of syncpoint registers */ u64 dma_mask; /* mask of addressable memory */ + bool has_hypervisor; /* has hypervisor registers */ }; struct host1x { const struct host1x_info *info; void __iomem *regs; + void __iomem *hv_regs; /* hypervisor region */ struct host1x_syncpt *syncpt; struct host1x_syncpt_base *bases; struct device *dev; @@ -140,6 +145,8 @@ struct host1x { struct list_head list; }; +void host1x_hypervisor_writel(struct host1x *host1x, u32 r, u32 v); +u32 host1x_hypervisor_readl(struct host1x *host1x, u32 r); void host1x_sync_writel(struct host1x *host1x, u32 r, u32 v); u32 host1x_sync_readl(struct host1x *host1x, u32 r); void host1x_ch_writel(struct host1x_channel *ch, u32 r, u32 v); @@ -182,6 +189,18 @@ static inline int host1x_hw_syncpt_patch_wait(struct host1x *host, return host->syncpt_op->patch_wait(sp, patch_addr); } +static inline void host1x_hw_syncpt_assign_to_channel( + struct host1x *host, struct host1x_syncpt *sp, + struct host1x_channel *ch) +{ + return host->syncpt_op->assign_to_channel(sp, ch); +} + +static inline void host1x_hw_syncpt_enable_protection(struct host1x *host) +{ + return host->syncpt_op->enable_protection(host); +} + static inline int host1x_hw_intr_init_host_sync(struct host1x *host, u32 cpm, void (*syncpt_thresh_work)(struct work_struct *)) { diff --git a/drivers/gpu/host1x/hw/cdma_hw.c b/drivers/gpu/host1x/hw/cdma_hw.c index 6b231119193e..ce320534cbed 100644 --- a/drivers/gpu/host1x/hw/cdma_hw.c +++ b/drivers/gpu/host1x/hw/cdma_hw.c @@ -172,6 +172,30 @@ static void cdma_stop(struct host1x_cdma *cdma) mutex_unlock(&cdma->lock); } +static void cdma_hw_cmdproc_stop(struct host1x *host, struct host1x_channel *ch, + bool stop) +{ +#if HOST1X_HW >= 6 + host1x_ch_writel(ch, stop ? 0x1 : 0x0, HOST1X_CHANNEL_CMDPROC_STOP); +#else + u32 cmdproc_stop = host1x_sync_readl(host, HOST1X_SYNC_CMDPROC_STOP); + if (stop) + cmdproc_stop |= BIT(ch->id); + else + cmdproc_stop &= ~BIT(ch->id); + host1x_sync_writel(host, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP); +#endif +} + +static void cdma_hw_teardown(struct host1x *host, struct host1x_channel *ch) +{ +#if HOST1X_HW >= 6 + host1x_ch_writel(ch, 0x1, HOST1X_CHANNEL_TEARDOWN); +#else + host1x_sync_writel(host, BIT(ch->id), HOST1X_SYNC_CH_TEARDOWN); +#endif +} + /* * Stops both channel's command processor and CDMA immediately. * Also, tears down the channel and resets corresponding module. @@ -180,7 +204,6 @@ static void cdma_freeze(struct host1x_cdma *cdma) { struct host1x *host = cdma_to_host1x(cdma); struct host1x_channel *ch = cdma_to_channel(cdma); - u32 cmdproc_stop; if (cdma->torndown && !cdma->running) { dev_warn(host->dev, "Already torn down\n"); @@ -189,9 +212,7 @@ static void cdma_freeze(struct host1x_cdma *cdma) dev_dbg(host->dev, "freezing channel (id %d)\n", ch->id); - cmdproc_stop = host1x_sync_readl(host, HOST1X_SYNC_CMDPROC_STOP); - cmdproc_stop |= BIT(ch->id); - host1x_sync_writel(host, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP); + cdma_hw_cmdproc_stop(host, ch, true); dev_dbg(host->dev, "%s: DMA GET 0x%x, PUT HW 0x%x / shadow 0x%x\n", __func__, host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET), @@ -201,7 +222,7 @@ static void cdma_freeze(struct host1x_cdma *cdma) host1x_ch_writel(ch, HOST1X_CHANNEL_DMACTRL_DMASTOP, HOST1X_CHANNEL_DMACTRL); - host1x_sync_writel(host, BIT(ch->id), HOST1X_SYNC_CH_TEARDOWN); + cdma_hw_teardown(host, ch); cdma->running = false; cdma->torndown = true; @@ -211,15 +232,12 @@ static void cdma_resume(struct host1x_cdma *cdma, u32 getptr) { struct host1x *host1x = cdma_to_host1x(cdma); struct host1x_channel *ch = cdma_to_channel(cdma); - u32 cmdproc_stop; dev_dbg(host1x->dev, "resuming channel (id %u, DMAGET restart = 0x%x)\n", ch->id, getptr); - cmdproc_stop = host1x_sync_readl(host1x, HOST1X_SYNC_CMDPROC_STOP); - cmdproc_stop &= ~BIT(ch->id); - host1x_sync_writel(host1x, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP); + cdma_hw_cmdproc_stop(host1x, ch, false); cdma->torndown = false; cdma_timeout_restart(cdma, getptr); @@ -232,7 +250,7 @@ static void cdma_resume(struct host1x_cdma *cdma, u32 getptr) */ static void cdma_timeout_handler(struct work_struct *work) { - u32 prev_cmdproc, cmdproc_stop, syncpt_val; + u32 syncpt_val; struct host1x_cdma *cdma; struct host1x *host1x; struct host1x_channel *ch; @@ -254,12 +272,7 @@ static void cdma_timeout_handler(struct work_struct *work) } /* stop processing to get a clean snapshot */ - prev_cmdproc = host1x_sync_readl(host1x, HOST1X_SYNC_CMDPROC_STOP); - cmdproc_stop = prev_cmdproc | BIT(ch->id); - host1x_sync_writel(host1x, cmdproc_stop, HOST1X_SYNC_CMDPROC_STOP); - - dev_dbg(host1x->dev, "cdma_timeout: cmdproc was 0x%x is 0x%x\n", - prev_cmdproc, cmdproc_stop); + cdma_hw_cmdproc_stop(host1x, ch, true); syncpt_val = host1x_syncpt_load(cdma->timeout.syncpt); @@ -268,9 +281,7 @@ static void cdma_timeout_handler(struct work_struct *work) dev_dbg(host1x->dev, "cdma_timeout: expired, but buffer had completed\n"); /* restore */ - cmdproc_stop = prev_cmdproc & ~(BIT(ch->id)); - host1x_sync_writel(host1x, cmdproc_stop, - HOST1X_SYNC_CMDPROC_STOP); + cdma_hw_cmdproc_stop(host1x, ch, false); mutex_unlock(&cdma->lock); return; } diff --git a/drivers/gpu/host1x/hw/channel_hw.c b/drivers/gpu/host1x/hw/channel_hw.c index 8447a56c41ca..9af758785a11 100644 --- a/drivers/gpu/host1x/hw/channel_hw.c +++ b/drivers/gpu/host1x/hw/channel_hw.c @@ -147,6 +147,8 @@ static int channel_submit(struct host1x_job *job) syncval = host1x_syncpt_incr_max(sp, user_syncpt_incrs); + host1x_hw_syncpt_assign_to_channel(host, sp, ch); + job->syncpt_end = syncval; /* add a setclass for modules that require it */ @@ -178,10 +180,32 @@ error: return err; } +static void enable_gather_filter(struct host1x *host, + struct host1x_channel *ch) +{ +#if HOST1X_HW >= 6 + u32 val; + + if (!host->hv_regs) + return; + + val = host1x_hypervisor_readl( + host, HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(ch->id / 32)); + val |= BIT(ch->id % 32); + host1x_hypervisor_writel( + host, val, HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(ch->id / 32)); +#elif HOST1X_HW >= 4 + host1x_ch_writel(ch, + HOST1X_CHANNEL_CHANNELCTRL_KERNEL_FILTER_GBUFFER(1), + HOST1X_CHANNEL_CHANNELCTRL); +#endif +} + static int host1x_channel_init(struct host1x_channel *ch, struct host1x *dev, unsigned int index) { ch->regs = dev->regs + index * HOST1X_CHANNEL_SIZE; + enable_gather_filter(dev, ch); return 0; } diff --git a/drivers/gpu/host1x/hw/debug_hw.c b/drivers/gpu/host1x/hw/debug_hw.c index 7a4a3286e4a7..989476801f9d 100644 --- a/drivers/gpu/host1x/hw/debug_hw.c +++ b/drivers/gpu/host1x/hw/debug_hw.c @@ -30,6 +30,13 @@ enum { HOST1X_OPCODE_IMM = 0x04, HOST1X_OPCODE_RESTART = 0x05, HOST1X_OPCODE_GATHER = 0x06, + HOST1X_OPCODE_SETSTRMID = 0x07, + HOST1X_OPCODE_SETAPPID = 0x08, + HOST1X_OPCODE_SETPYLD = 0x09, + HOST1X_OPCODE_INCR_W = 0x0a, + HOST1X_OPCODE_NONINCR_W = 0x0b, + HOST1X_OPCODE_GATHER_W = 0x0c, + HOST1X_OPCODE_RESTART_W = 0x0d, HOST1X_OPCODE_EXTEND = 0x0e, }; @@ -38,67 +45,122 @@ enum { HOST1X_OPCODE_EXTEND_RELEASE_MLOCK = 0x01, }; -static unsigned int show_channel_command(struct output *o, u32 val) +#define INVALID_PAYLOAD 0xffffffff + +static unsigned int show_channel_command(struct output *o, u32 val, + u32 *payload) { - unsigned int mask, subop; + unsigned int mask, subop, num, opcode; + + opcode = val >> 28; - switch (val >> 28) { + switch (opcode) { case HOST1X_OPCODE_SETCLASS: mask = val & 0x3f; if (mask) { - host1x_debug_output(o, "SETCL(class=%03x, offset=%03x, mask=%02x, [", + host1x_debug_cont(o, "SETCL(class=%03x, offset=%03x, mask=%02x, [", val >> 6 & 0x3ff, val >> 16 & 0xfff, mask); return hweight8(mask); } - host1x_debug_output(o, "SETCL(class=%03x)\n", val >> 6 & 0x3ff); + host1x_debug_cont(o, "SETCL(class=%03x)\n", val >> 6 & 0x3ff); return 0; case HOST1X_OPCODE_INCR: - host1x_debug_output(o, "INCR(offset=%03x, [", + num = val & 0xffff; + host1x_debug_cont(o, "INCR(offset=%03x, [", val >> 16 & 0xfff); - return val & 0xffff; + if (!num) + host1x_debug_cont(o, "])\n"); + + return num; case HOST1X_OPCODE_NONINCR: - host1x_debug_output(o, "NONINCR(offset=%03x, [", + num = val & 0xffff; + host1x_debug_cont(o, "NONINCR(offset=%03x, [", val >> 16 & 0xfff); - return val & 0xffff; + if (!num) + host1x_debug_cont(o, "])\n"); + + return num; case HOST1X_OPCODE_MASK: mask = val & 0xffff; - host1x_debug_output(o, "MASK(offset=%03x, mask=%03x, [", + host1x_debug_cont(o, "MASK(offset=%03x, mask=%03x, [", val >> 16 & 0xfff, mask); + if (!mask) + host1x_debug_cont(o, "])\n"); + return hweight16(mask); case HOST1X_OPCODE_IMM: - host1x_debug_output(o, "IMM(offset=%03x, data=%03x)\n", + host1x_debug_cont(o, "IMM(offset=%03x, data=%03x)\n", val >> 16 & 0xfff, val & 0xffff); return 0; case HOST1X_OPCODE_RESTART: - host1x_debug_output(o, "RESTART(offset=%08x)\n", val << 4); + host1x_debug_cont(o, "RESTART(offset=%08x)\n", val << 4); return 0; case HOST1X_OPCODE_GATHER: - host1x_debug_output(o, "GATHER(offset=%03x, insert=%d, type=%d, count=%04x, addr=[", + host1x_debug_cont(o, "GATHER(offset=%03x, insert=%d, type=%d, count=%04x, addr=[", val >> 16 & 0xfff, val >> 15 & 0x1, val >> 14 & 0x1, val & 0x3fff); return 1; +#if HOST1X_HW >= 6 + case HOST1X_OPCODE_SETSTRMID: + host1x_debug_cont(o, "SETSTRMID(offset=%06x)\n", + val & 0x3fffff); + return 0; + + case HOST1X_OPCODE_SETAPPID: + host1x_debug_cont(o, "SETAPPID(appid=%02x)\n", val & 0xff); + return 0; + + case HOST1X_OPCODE_SETPYLD: + *payload = val & 0xffff; + host1x_debug_cont(o, "SETPYLD(data=%04x)\n", *payload); + return 0; + + case HOST1X_OPCODE_INCR_W: + case HOST1X_OPCODE_NONINCR_W: + host1x_debug_cont(o, "%s(offset=%06x, ", + opcode == HOST1X_OPCODE_INCR_W ? + "INCR_W" : "NONINCR_W", + val & 0x3fffff); + if (*payload == 0) { + host1x_debug_cont(o, "[])\n"); + return 0; + } else if (*payload == INVALID_PAYLOAD) { + host1x_debug_cont(o, "unknown)\n"); + return 0; + } else { + host1x_debug_cont(o, "["); + return *payload; + } + + case HOST1X_OPCODE_GATHER_W: + host1x_debug_cont(o, "GATHER_W(count=%04x, addr=[", + val & 0x3fff); + return 2; +#endif + case HOST1X_OPCODE_EXTEND: subop = val >> 24 & 0xf; if (subop == HOST1X_OPCODE_EXTEND_ACQUIRE_MLOCK) - host1x_debug_output(o, "ACQUIRE_MLOCK(index=%d)\n", + host1x_debug_cont(o, "ACQUIRE_MLOCK(index=%d)\n", val & 0xff); else if (subop == HOST1X_OPCODE_EXTEND_RELEASE_MLOCK) - host1x_debug_output(o, "RELEASE_MLOCK(index=%d)\n", + host1x_debug_cont(o, "RELEASE_MLOCK(index=%d)\n", val & 0xff); else - host1x_debug_output(o, "EXTEND_UNKNOWN(%08x)\n", val); + host1x_debug_cont(o, "EXTEND_UNKNOWN(%08x)\n", val); return 0; default: + host1x_debug_cont(o, "UNKNOWN\n"); return 0; } } @@ -110,6 +172,7 @@ static void show_gather(struct output *o, phys_addr_t phys_addr, /* Map dmaget cursor to corresponding mem handle */ u32 offset = phys_addr - pin_addr; unsigned int data_count = 0, i; + u32 payload = INVALID_PAYLOAD; /* * Sometimes we're given different hardware address to the same @@ -126,11 +189,11 @@ static void show_gather(struct output *o, phys_addr_t phys_addr, u32 val = *(map_addr + offset / 4 + i); if (!data_count) { - host1x_debug_output(o, "%08x: %08x:", addr, val); - data_count = show_channel_command(o, val); + host1x_debug_output(o, "%08x: %08x: ", addr, val); + data_count = show_channel_command(o, val, &payload); } else { - host1x_debug_output(o, "%08x%s", val, - data_count > 0 ? ", " : "])\n"); + host1x_debug_cont(o, "%08x%s", val, + data_count > 1 ? ", " : "])\n"); data_count--; } } @@ -174,138 +237,11 @@ static void show_channel_gathers(struct output *o, struct host1x_cdma *cdma) } } -static void host1x_debug_show_channel_cdma(struct host1x *host, - struct host1x_channel *ch, - struct output *o) -{ - struct host1x_cdma *cdma = &ch->cdma; - u32 dmaput, dmaget, dmactrl; - u32 cbstat, cbread; - u32 val, base, baseval; - - dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT); - dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET); - dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL); - cbread = host1x_sync_readl(host, HOST1X_SYNC_CBREAD(ch->id)); - cbstat = host1x_sync_readl(host, HOST1X_SYNC_CBSTAT(ch->id)); - - host1x_debug_output(o, "%u-%s: ", ch->id, dev_name(ch->dev)); - - if (HOST1X_CHANNEL_DMACTRL_DMASTOP_V(dmactrl) || - !ch->cdma.push_buffer.mapped) { - host1x_debug_output(o, "inactive\n\n"); - return; - } - - if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) == HOST1X_CLASS_HOST1X && - HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) == - HOST1X_UCLASS_WAIT_SYNCPT) - host1x_debug_output(o, "waiting on syncpt %d val %d\n", - cbread >> 24, cbread & 0xffffff); - else if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) == - HOST1X_CLASS_HOST1X && - HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) == - HOST1X_UCLASS_WAIT_SYNCPT_BASE) { - base = (cbread >> 16) & 0xff; - baseval = - host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(base)); - val = cbread & 0xffff; - host1x_debug_output(o, "waiting on syncpt %d val %d (base %d = %d; offset = %d)\n", - cbread >> 24, baseval + val, base, - baseval, val); - } else - host1x_debug_output(o, "active class %02x, offset %04x, val %08x\n", - HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat), - HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat), - cbread); - - host1x_debug_output(o, "DMAPUT %08x, DMAGET %08x, DMACTL %08x\n", - dmaput, dmaget, dmactrl); - host1x_debug_output(o, "CBREAD %08x, CBSTAT %08x\n", cbread, cbstat); - - show_channel_gathers(o, cdma); - host1x_debug_output(o, "\n"); -} - -static void host1x_debug_show_channel_fifo(struct host1x *host, - struct host1x_channel *ch, - struct output *o) -{ - u32 val, rd_ptr, wr_ptr, start, end; - unsigned int data_count = 0; - - host1x_debug_output(o, "%u: fifo:\n", ch->id); - - val = host1x_ch_readl(ch, HOST1X_CHANNEL_FIFOSTAT); - host1x_debug_output(o, "FIFOSTAT %08x\n", val); - if (HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(val)) { - host1x_debug_output(o, "[empty]\n"); - return; - } - - host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL); - host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) | - HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id), - HOST1X_SYNC_CFPEEK_CTRL); - - val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_PTRS); - rd_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(val); - wr_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(val); - - val = host1x_sync_readl(host, HOST1X_SYNC_CF_SETUP(ch->id)); - start = HOST1X_SYNC_CF_SETUP_BASE_V(val); - end = HOST1X_SYNC_CF_SETUP_LIMIT_V(val); - - do { - host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL); - host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) | - HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id) | - HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(rd_ptr), - HOST1X_SYNC_CFPEEK_CTRL); - val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_READ); - - if (!data_count) { - host1x_debug_output(o, "%08x:", val); - data_count = show_channel_command(o, val); - } else { - host1x_debug_output(o, "%08x%s", val, - data_count > 0 ? ", " : "])\n"); - data_count--; - } - - if (rd_ptr == end) - rd_ptr = start; - else - rd_ptr++; - } while (rd_ptr != wr_ptr); - - if (data_count) - host1x_debug_output(o, ", ...])\n"); - host1x_debug_output(o, "\n"); - - host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL); -} - -static void host1x_debug_show_mlocks(struct host1x *host, struct output *o) -{ - unsigned int i; - - host1x_debug_output(o, "---- mlocks ----\n"); - - for (i = 0; i < host1x_syncpt_nb_mlocks(host); i++) { - u32 owner = - host1x_sync_readl(host, HOST1X_SYNC_MLOCK_OWNER(i)); - if (HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(owner)) - host1x_debug_output(o, "%u: locked by channel %u\n", - i, HOST1X_SYNC_MLOCK_OWNER_CHID_V(owner)); - else if (HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(owner)) - host1x_debug_output(o, "%u: locked by cpu\n", i); - else - host1x_debug_output(o, "%u: unlocked\n", i); - } - - host1x_debug_output(o, "\n"); -} +#if HOST1X_HW >= 6 +#include "debug_hw_1x06.c" +#else +#include "debug_hw_1x01.c" +#endif static const struct host1x_debug_ops host1x_debug_ops = { .show_channel_cdma = host1x_debug_show_channel_cdma, diff --git a/drivers/gpu/host1x/hw/debug_hw_1x01.c b/drivers/gpu/host1x/hw/debug_hw_1x01.c new file mode 100644 index 000000000000..8790d5fd5f20 --- /dev/null +++ b/drivers/gpu/host1x/hw/debug_hw_1x01.c @@ -0,0 +1,154 @@ +/* + * Copyright (C) 2010 Google, Inc. + * Author: Erik Gilling <konkers@android.com> + * + * Copyright (C) 2011-2013 NVIDIA Corporation + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../dev.h" +#include "../debug.h" +#include "../cdma.h" +#include "../channel.h" + +static void host1x_debug_show_channel_cdma(struct host1x *host, + struct host1x_channel *ch, + struct output *o) +{ + struct host1x_cdma *cdma = &ch->cdma; + u32 dmaput, dmaget, dmactrl; + u32 cbstat, cbread; + u32 val, base, baseval; + + dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT); + dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET); + dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL); + cbread = host1x_sync_readl(host, HOST1X_SYNC_CBREAD(ch->id)); + cbstat = host1x_sync_readl(host, HOST1X_SYNC_CBSTAT(ch->id)); + + host1x_debug_output(o, "%u-%s: ", ch->id, dev_name(ch->dev)); + + if (HOST1X_CHANNEL_DMACTRL_DMASTOP_V(dmactrl) || + !ch->cdma.push_buffer.mapped) { + host1x_debug_output(o, "inactive\n\n"); + return; + } + + if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) == HOST1X_CLASS_HOST1X && + HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) == + HOST1X_UCLASS_WAIT_SYNCPT) + host1x_debug_output(o, "waiting on syncpt %d val %d\n", + cbread >> 24, cbread & 0xffffff); + else if (HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat) == + HOST1X_CLASS_HOST1X && + HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat) == + HOST1X_UCLASS_WAIT_SYNCPT_BASE) { + base = (cbread >> 16) & 0xff; + baseval = + host1x_sync_readl(host, HOST1X_SYNC_SYNCPT_BASE(base)); + val = cbread & 0xffff; + host1x_debug_output(o, "waiting on syncpt %d val %d (base %d = %d; offset = %d)\n", + cbread >> 24, baseval + val, base, + baseval, val); + } else + host1x_debug_output(o, "active class %02x, offset %04x, val %08x\n", + HOST1X_SYNC_CBSTAT_CBCLASS_V(cbstat), + HOST1X_SYNC_CBSTAT_CBOFFSET_V(cbstat), + cbread); + + host1x_debug_output(o, "DMAPUT %08x, DMAGET %08x, DMACTL %08x\n", + dmaput, dmaget, dmactrl); + host1x_debug_output(o, "CBREAD %08x, CBSTAT %08x\n", cbread, cbstat); + + show_channel_gathers(o, cdma); + host1x_debug_output(o, "\n"); +} + +static void host1x_debug_show_channel_fifo(struct host1x *host, + struct host1x_channel *ch, + struct output *o) +{ + u32 val, rd_ptr, wr_ptr, start, end; + unsigned int data_count = 0; + + host1x_debug_output(o, "%u: fifo:\n", ch->id); + + val = host1x_ch_readl(ch, HOST1X_CHANNEL_FIFOSTAT); + host1x_debug_output(o, "FIFOSTAT %08x\n", val); + if (HOST1X_CHANNEL_FIFOSTAT_CFEMPTY_V(val)) { + host1x_debug_output(o, "[empty]\n"); + return; + } + + host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL); + host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) | + HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id), + HOST1X_SYNC_CFPEEK_CTRL); + + val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_PTRS); + rd_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_RD_PTR_V(val); + wr_ptr = HOST1X_SYNC_CFPEEK_PTRS_CF_WR_PTR_V(val); + + val = host1x_sync_readl(host, HOST1X_SYNC_CF_SETUP(ch->id)); + start = HOST1X_SYNC_CF_SETUP_BASE_V(val); + end = HOST1X_SYNC_CF_SETUP_LIMIT_V(val); + + do { + host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL); + host1x_sync_writel(host, HOST1X_SYNC_CFPEEK_CTRL_ENA_F(1) | + HOST1X_SYNC_CFPEEK_CTRL_CHANNR_F(ch->id) | + HOST1X_SYNC_CFPEEK_CTRL_ADDR_F(rd_ptr), + HOST1X_SYNC_CFPEEK_CTRL); + val = host1x_sync_readl(host, HOST1X_SYNC_CFPEEK_READ); + + if (!data_count) { + host1x_debug_output(o, "%08x: ", val); + data_count = show_channel_command(o, val, NULL); + } else { + host1x_debug_cont(o, "%08x%s", val, + data_count > 1 ? ", " : "])\n"); + data_count--; + } + + if (rd_ptr == end) + rd_ptr = start; + else + rd_ptr++; + } while (rd_ptr != wr_ptr); + + if (data_count) + host1x_debug_cont(o, ", ...])\n"); + host1x_debug_output(o, "\n"); + + host1x_sync_writel(host, 0x0, HOST1X_SYNC_CFPEEK_CTRL); +} + +static void host1x_debug_show_mlocks(struct host1x *host, struct output *o) +{ + unsigned int i; + + host1x_debug_output(o, "---- mlocks ----\n"); + + for (i = 0; i < host1x_syncpt_nb_mlocks(host); i++) { + u32 owner = + host1x_sync_readl(host, HOST1X_SYNC_MLOCK_OWNER(i)); + if (HOST1X_SYNC_MLOCK_OWNER_CH_OWNS_V(owner)) + host1x_debug_output(o, "%u: locked by channel %u\n", + i, HOST1X_SYNC_MLOCK_OWNER_CHID_V(owner)); + else if (HOST1X_SYNC_MLOCK_OWNER_CPU_OWNS_V(owner)) + host1x_debug_output(o, "%u: locked by cpu\n", i); + else + host1x_debug_output(o, "%u: unlocked\n", i); + } + + host1x_debug_output(o, "\n"); +} diff --git a/drivers/gpu/host1x/hw/debug_hw_1x06.c b/drivers/gpu/host1x/hw/debug_hw_1x06.c new file mode 100644 index 000000000000..b503c740c022 --- /dev/null +++ b/drivers/gpu/host1x/hw/debug_hw_1x06.c @@ -0,0 +1,135 @@ +/* + * Copyright (C) 2010 Google, Inc. + * Author: Erik Gilling <konkers@android.com> + * + * Copyright (C) 2011-2017 NVIDIA Corporation + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include "../dev.h" +#include "../debug.h" +#include "../cdma.h" +#include "../channel.h" + +static void host1x_debug_show_channel_cdma(struct host1x *host, + struct host1x_channel *ch, + struct output *o) +{ + struct host1x_cdma *cdma = &ch->cdma; + u32 dmaput, dmaget, dmactrl; + u32 offset, class; + u32 ch_stat; + + dmaput = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAPUT); + dmaget = host1x_ch_readl(ch, HOST1X_CHANNEL_DMAGET); + dmactrl = host1x_ch_readl(ch, HOST1X_CHANNEL_DMACTRL); + offset = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDP_OFFSET); + class = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDP_CLASS); + ch_stat = host1x_ch_readl(ch, HOST1X_CHANNEL_CHANNELSTAT); + + host1x_debug_output(o, "%u-%s: ", ch->id, dev_name(ch->dev)); + + if (dmactrl & HOST1X_CHANNEL_DMACTRL_DMASTOP || + !ch->cdma.push_buffer.mapped) { + host1x_debug_output(o, "inactive\n\n"); + return; + } + + if (class == HOST1X_CLASS_HOST1X && offset == HOST1X_UCLASS_WAIT_SYNCPT) + host1x_debug_output(o, "waiting on syncpt\n"); + else + host1x_debug_output(o, "active class %02x, offset %04x\n", + class, offset); + + host1x_debug_output(o, "DMAPUT %08x, DMAGET %08x, DMACTL %08x\n", + dmaput, dmaget, dmactrl); + host1x_debug_output(o, "CHANNELSTAT %02x\n", ch_stat); + + show_channel_gathers(o, cdma); + host1x_debug_output(o, "\n"); +} + +static void host1x_debug_show_channel_fifo(struct host1x *host, + struct host1x_channel *ch, + struct output *o) +{ + u32 val, rd_ptr, wr_ptr, start, end; + u32 payload = INVALID_PAYLOAD; + unsigned int data_count = 0; + + host1x_debug_output(o, "%u: fifo:\n", ch->id); + + val = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDFIFO_STAT); + host1x_debug_output(o, "CMDFIFO_STAT %08x\n", val); + if (val & HOST1X_CHANNEL_CMDFIFO_STAT_EMPTY) { + host1x_debug_output(o, "[empty]\n"); + return; + } + + val = host1x_ch_readl(ch, HOST1X_CHANNEL_CMDFIFO_RDATA); + host1x_debug_output(o, "CMDFIFO_RDATA %08x\n", val); + + /* Peek pointer values are invalid during SLCG, so disable it */ + host1x_hypervisor_writel(host, 0x1, HOST1X_HV_ICG_EN_OVERRIDE); + + val = 0; + val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_ENABLE; + val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_CHANNEL(ch->id); + host1x_hypervisor_writel(host, val, HOST1X_HV_CMDFIFO_PEEK_CTRL); + + val = host1x_hypervisor_readl(host, HOST1X_HV_CMDFIFO_PEEK_PTRS); + rd_ptr = HOST1X_HV_CMDFIFO_PEEK_PTRS_RD_PTR_V(val); + wr_ptr = HOST1X_HV_CMDFIFO_PEEK_PTRS_WR_PTR_V(val); + + val = host1x_hypervisor_readl(host, HOST1X_HV_CMDFIFO_SETUP(ch->id)); + start = HOST1X_HV_CMDFIFO_SETUP_BASE_V(val); + end = HOST1X_HV_CMDFIFO_SETUP_LIMIT_V(val); + + do { + val = 0; + val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_ENABLE; + val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_CHANNEL(ch->id); + val |= HOST1X_HV_CMDFIFO_PEEK_CTRL_ADDR(rd_ptr); + host1x_hypervisor_writel(host, val, + HOST1X_HV_CMDFIFO_PEEK_CTRL); + + val = host1x_hypervisor_readl(host, + HOST1X_HV_CMDFIFO_PEEK_READ); + + if (!data_count) { + host1x_debug_output(o, "%03x 0x%08x: ", + rd_ptr - start, val); + data_count = show_channel_command(o, val, &payload); + } else { + host1x_debug_cont(o, "%08x%s", val, + data_count > 1 ? ", " : "])\n"); + data_count--; + } + + if (rd_ptr == end) + rd_ptr = start; + else + rd_ptr++; + } while (rd_ptr != wr_ptr); + + if (data_count) + host1x_debug_cont(o, ", ...])\n"); + host1x_debug_output(o, "\n"); + + host1x_hypervisor_writel(host, 0x0, HOST1X_HV_CMDFIFO_PEEK_CTRL); + host1x_hypervisor_writel(host, 0x0, HOST1X_HV_ICG_EN_OVERRIDE); +} + +static void host1x_debug_show_mlocks(struct host1x *host, struct output *o) +{ + /* TODO */ +} diff --git a/drivers/gpu/host1x/hw/host1x01.c b/drivers/gpu/host1x/hw/host1x01.c index 859b73beb4d0..bb124f8b4af8 100644 --- a/drivers/gpu/host1x/hw/host1x01.c +++ b/drivers/gpu/host1x/hw/host1x01.c @@ -21,6 +21,8 @@ #include "host1x01_hardware.h" /* include code */ +#define HOST1X_HW 1 + #include "cdma_hw.c" #include "channel_hw.c" #include "debug_hw.c" diff --git a/drivers/gpu/host1x/hw/host1x02.c b/drivers/gpu/host1x/hw/host1x02.c index 928946c2144b..c5f85dbedb98 100644 --- a/drivers/gpu/host1x/hw/host1x02.c +++ b/drivers/gpu/host1x/hw/host1x02.c @@ -21,6 +21,8 @@ #include "host1x02_hardware.h" /* include code */ +#define HOST1X_HW 2 + #include "cdma_hw.c" #include "channel_hw.c" #include "debug_hw.c" diff --git a/drivers/gpu/host1x/hw/host1x04.c b/drivers/gpu/host1x/hw/host1x04.c index 8007c70fa9c4..f102a1a7743f 100644 --- a/drivers/gpu/host1x/hw/host1x04.c +++ b/drivers/gpu/host1x/hw/host1x04.c @@ -21,6 +21,8 @@ #include "host1x04_hardware.h" /* include code */ +#define HOST1X_HW 4 + #include "cdma_hw.c" #include "channel_hw.c" #include "debug_hw.c" diff --git a/drivers/gpu/host1x/hw/host1x05.c b/drivers/gpu/host1x/hw/host1x05.c index 047097ce3bad..2b1239d6ec67 100644 --- a/drivers/gpu/host1x/hw/host1x05.c +++ b/drivers/gpu/host1x/hw/host1x05.c @@ -21,6 +21,8 @@ #include "host1x05_hardware.h" /* include code */ +#define HOST1X_HW 5 + #include "cdma_hw.c" #include "channel_hw.c" #include "debug_hw.c" diff --git a/drivers/gpu/host1x/hw/host1x06.c b/drivers/gpu/host1x/hw/host1x06.c new file mode 100644 index 000000000000..a66230827c59 --- /dev/null +++ b/drivers/gpu/host1x/hw/host1x06.c @@ -0,0 +1,44 @@ +/* + * Host1x init for Tegra186 SoCs + * + * Copyright (c) 2017 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* include hw specification */ +#include "host1x06.h" +#include "host1x06_hardware.h" + +/* include code */ +#define HOST1X_HW 6 + +#include "cdma_hw.c" +#include "channel_hw.c" +#include "debug_hw.c" +#include "intr_hw.c" +#include "syncpt_hw.c" + +#include "../dev.h" + +int host1x06_init(struct host1x *host) +{ + host->channel_op = &host1x_channel_ops; + host->cdma_op = &host1x_cdma_ops; + host->cdma_pb_op = &host1x_pushbuffer_ops; + host->syncpt_op = &host1x_syncpt_ops; + host->intr_op = &host1x_intr_ops; + host->debug_op = &host1x_debug_ops; + + return 0; +} diff --git a/drivers/gpu/host1x/hw/host1x06.h b/drivers/gpu/host1x/hw/host1x06.h new file mode 100644 index 000000000000..d9abe1489241 --- /dev/null +++ b/drivers/gpu/host1x/hw/host1x06.h @@ -0,0 +1,26 @@ +/* + * Host1x init for Tegra186 SoCs + * + * Copyright (c) 2017 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef HOST1X_HOST1X06_H +#define HOST1X_HOST1X06_H + +struct host1x; + +int host1x06_init(struct host1x *host); + +#endif diff --git a/drivers/gpu/host1x/hw/host1x06_hardware.h b/drivers/gpu/host1x/hw/host1x06_hardware.h new file mode 100644 index 000000000000..3039c92ea605 --- /dev/null +++ b/drivers/gpu/host1x/hw/host1x06_hardware.h @@ -0,0 +1,142 @@ +/* + * Tegra host1x Register Offsets for Tegra186 + * + * Copyright (c) 2017 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef __HOST1X_HOST1X06_HARDWARE_H +#define __HOST1X_HOST1X06_HARDWARE_H + +#include <linux/types.h> +#include <linux/bitops.h> + +#include "hw_host1x06_uclass.h" +#include "hw_host1x06_vm.h" +#include "hw_host1x06_hypervisor.h" + +static inline u32 host1x_class_host_wait_syncpt( + unsigned indx, unsigned threshold) +{ + return host1x_uclass_wait_syncpt_indx_f(indx) + | host1x_uclass_wait_syncpt_thresh_f(threshold); +} + +static inline u32 host1x_class_host_load_syncpt_base( + unsigned indx, unsigned threshold) +{ + return host1x_uclass_load_syncpt_base_base_indx_f(indx) + | host1x_uclass_load_syncpt_base_value_f(threshold); +} + +static inline u32 host1x_class_host_wait_syncpt_base( + unsigned indx, unsigned base_indx, unsigned offset) +{ + return host1x_uclass_wait_syncpt_base_indx_f(indx) + | host1x_uclass_wait_syncpt_base_base_indx_f(base_indx) + | host1x_uclass_wait_syncpt_base_offset_f(offset); +} + +static inline u32 host1x_class_host_incr_syncpt_base( + unsigned base_indx, unsigned offset) +{ + return host1x_uclass_incr_syncpt_base_base_indx_f(base_indx) + | host1x_uclass_incr_syncpt_base_offset_f(offset); +} + +static inline u32 host1x_class_host_incr_syncpt( + unsigned cond, unsigned indx) +{ + return host1x_uclass_incr_syncpt_cond_f(cond) + | host1x_uclass_incr_syncpt_indx_f(indx); +} + +static inline u32 host1x_class_host_indoff_reg_write( + unsigned mod_id, unsigned offset, bool auto_inc) +{ + u32 v = host1x_uclass_indoff_indbe_f(0xf) + | host1x_uclass_indoff_indmodid_f(mod_id) + | host1x_uclass_indoff_indroffset_f(offset); + if (auto_inc) + v |= host1x_uclass_indoff_autoinc_f(1); + return v; +} + +static inline u32 host1x_class_host_indoff_reg_read( + unsigned mod_id, unsigned offset, bool auto_inc) +{ + u32 v = host1x_uclass_indoff_indmodid_f(mod_id) + | host1x_uclass_indoff_indroffset_f(offset) + | host1x_uclass_indoff_rwn_read_v(); + if (auto_inc) + v |= host1x_uclass_indoff_autoinc_f(1); + return v; +} + +/* cdma opcodes */ +static inline u32 host1x_opcode_setclass( + unsigned class_id, unsigned offset, unsigned mask) +{ + return (0 << 28) | (offset << 16) | (class_id << 6) | mask; +} + +static inline u32 host1x_opcode_incr(unsigned offset, unsigned count) +{ + return (1 << 28) | (offset << 16) | count; +} + +static inline u32 host1x_opcode_nonincr(unsigned offset, unsigned count) +{ + return (2 << 28) | (offset << 16) | count; +} + +static inline u32 host1x_opcode_mask(unsigned offset, unsigned mask) +{ + return (3 << 28) | (offset << 16) | mask; +} + +static inline u32 host1x_opcode_imm(unsigned offset, unsigned value) +{ + return (4 << 28) | (offset << 16) | value; +} + +static inline u32 host1x_opcode_imm_incr_syncpt(unsigned cond, unsigned indx) +{ + return host1x_opcode_imm(host1x_uclass_incr_syncpt_r(), + host1x_class_host_incr_syncpt(cond, indx)); +} + +static inline u32 host1x_opcode_restart(unsigned address) +{ + return (5 << 28) | (address >> 4); +} + +static inline u32 host1x_opcode_gather(unsigned count) +{ + return (6 << 28) | count; +} + +static inline u32 host1x_opcode_gather_nonincr(unsigned offset, unsigned count) +{ + return (6 << 28) | (offset << 16) | BIT(15) | count; +} + +static inline u32 host1x_opcode_gather_incr(unsigned offset, unsigned count) +{ + return (6 << 28) | (offset << 16) | BIT(15) | BIT(14) | count; +} + +#define HOST1X_OPCODE_NOP host1x_opcode_nonincr(0, 0) + +#endif diff --git a/drivers/gpu/host1x/hw/hw_host1x04_channel.h b/drivers/gpu/host1x/hw/hw_host1x04_channel.h index 95e6f96142b9..2e8b635aa660 100644 --- a/drivers/gpu/host1x/hw/hw_host1x04_channel.h +++ b/drivers/gpu/host1x/hw/hw_host1x04_channel.h @@ -117,5 +117,17 @@ static inline u32 host1x_channel_dmactrl_dmainitget(void) } #define HOST1X_CHANNEL_DMACTRL_DMAINITGET \ host1x_channel_dmactrl_dmainitget() +static inline u32 host1x_channel_channelctrl_r(void) +{ + return 0x98; +} +#define HOST1X_CHANNEL_CHANNELCTRL \ + host1x_channel_channelctrl_r() +static inline u32 host1x_channel_channelctrl_kernel_filter_gbuffer_f(u32 v) +{ + return (v & 0x1) << 2; +} +#define HOST1X_CHANNEL_CHANNELCTRL_KERNEL_FILTER_GBUFFER(v) \ + host1x_channel_channelctrl_kernel_filter_gbuffer_f(v) #endif diff --git a/drivers/gpu/host1x/hw/hw_host1x05_channel.h b/drivers/gpu/host1x/hw/hw_host1x05_channel.h index fce6e2c1ff4c..abbbc2641ce6 100644 --- a/drivers/gpu/host1x/hw/hw_host1x05_channel.h +++ b/drivers/gpu/host1x/hw/hw_host1x05_channel.h @@ -117,5 +117,17 @@ static inline u32 host1x_channel_dmactrl_dmainitget(void) } #define HOST1X_CHANNEL_DMACTRL_DMAINITGET \ host1x_channel_dmactrl_dmainitget() +static inline u32 host1x_channel_channelctrl_r(void) +{ + return 0x98; +} +#define HOST1X_CHANNEL_CHANNELCTRL \ + host1x_channel_channelctrl_r() +static inline u32 host1x_channel_channelctrl_kernel_filter_gbuffer_f(u32 v) +{ + return (v & 0x1) << 2; +} +#define HOST1X_CHANNEL_CHANNELCTRL_KERNEL_FILTER_GBUFFER(v) \ + host1x_channel_channelctrl_kernel_filter_gbuffer_f(v) #endif diff --git a/drivers/gpu/host1x/hw/hw_host1x06_hypervisor.h b/drivers/gpu/host1x/hw/hw_host1x06_hypervisor.h new file mode 100644 index 000000000000..c05dab8a178b --- /dev/null +++ b/drivers/gpu/host1x/hw/hw_host1x06_hypervisor.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#define HOST1X_HV_SYNCPT_PROT_EN 0x1ac4 +#define HOST1X_HV_SYNCPT_PROT_EN_CH_EN BIT(1) +#define HOST1X_HV_CH_KERNEL_FILTER_GBUFFER(x) (0x2020 + (x * 4)) +#define HOST1X_HV_CMDFIFO_PEEK_CTRL 0x233c +#define HOST1X_HV_CMDFIFO_PEEK_CTRL_ADDR(x) (x) +#define HOST1X_HV_CMDFIFO_PEEK_CTRL_CHANNEL(x) ((x) << 16) +#define HOST1X_HV_CMDFIFO_PEEK_CTRL_ENABLE BIT(31) +#define HOST1X_HV_CMDFIFO_PEEK_READ 0x2340 +#define HOST1X_HV_CMDFIFO_PEEK_PTRS 0x2344 +#define HOST1X_HV_CMDFIFO_PEEK_PTRS_WR_PTR_V(x) (((x) >> 16) & 0xfff) +#define HOST1X_HV_CMDFIFO_PEEK_PTRS_RD_PTR_V(x) ((x) & 0xfff) +#define HOST1X_HV_CMDFIFO_SETUP(x) (0x2588 + (x * 4)) +#define HOST1X_HV_CMDFIFO_SETUP_LIMIT_V(x) (((x) >> 16) & 0xfff) +#define HOST1X_HV_CMDFIFO_SETUP_BASE_V(x) ((x) & 0xfff) +#define HOST1X_HV_ICG_EN_OVERRIDE 0x2aa8 diff --git a/drivers/gpu/host1x/hw/hw_host1x06_uclass.h b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h new file mode 100644 index 000000000000..4457486c72b0 --- /dev/null +++ b/drivers/gpu/host1x/hw/hw_host1x06_uclass.h @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2017 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + + /* + * Function naming determines intended use: + * + * <x>_r(void) : Returns the offset for register <x>. + * + * <x>_w(void) : Returns the word offset for word (4 byte) element <x>. + * + * <x>_<y>_s(void) : Returns size of field <y> of register <x> in bits. + * + * <x>_<y>_f(u32 v) : Returns a value based on 'v' which has been shifted + * and masked to place it at field <y> of register <x>. This value + * can be |'d with others to produce a full register value for + * register <x>. + * + * <x>_<y>_m(void) : Returns a mask for field <y> of register <x>. This + * value can be ~'d and then &'d to clear the value of field <y> for + * register <x>. + * + * <x>_<y>_<z>_f(void) : Returns the constant value <z> after being shifted + * to place it at field <y> of register <x>. This value can be |'d + * with others to produce a full register value for <x>. + * + * <x>_<y>_v(u32 r) : Returns the value of field <y> from a full register + * <x> value 'r' after being shifted to place its LSB at bit 0. + * This value is suitable for direct comparison with other unshifted + * values appropriate for use in field <y> of register <x>. + * + * <x>_<y>_<z>_v(void) : Returns the constant value for <z> defined for + * field <y> of register <x>. This value is suitable for direct + * comparison with unshifted values appropriate for use in field <y> + * of register <x>. + */ + +#ifndef HOST1X_HW_HOST1X06_UCLASS_H +#define HOST1X_HW_HOST1X06_UCLASS_H + +static inline u32 host1x_uclass_incr_syncpt_r(void) +{ + return 0x0; +} +#define HOST1X_UCLASS_INCR_SYNCPT \ + host1x_uclass_incr_syncpt_r() +static inline u32 host1x_uclass_incr_syncpt_cond_f(u32 v) +{ + return (v & 0xff) << 8; +} +#define HOST1X_UCLASS_INCR_SYNCPT_COND_F(v) \ + host1x_uclass_incr_syncpt_cond_f(v) +static inline u32 host1x_uclass_incr_syncpt_indx_f(u32 v) +{ + return (v & 0xff) << 0; +} +#define HOST1X_UCLASS_INCR_SYNCPT_INDX_F(v) \ + host1x_uclass_incr_syncpt_indx_f(v) +static inline u32 host1x_uclass_wait_syncpt_r(void) +{ + return 0x8; +} +#define HOST1X_UCLASS_WAIT_SYNCPT \ + host1x_uclass_wait_syncpt_r() +static inline u32 host1x_uclass_wait_syncpt_indx_f(u32 v) +{ + return (v & 0xff) << 24; +} +#define HOST1X_UCLASS_WAIT_SYNCPT_INDX_F(v) \ + host1x_uclass_wait_syncpt_indx_f(v) +static inline u32 host1x_uclass_wait_syncpt_thresh_f(u32 v) +{ + return (v & 0xffffff) << 0; +} +#define HOST1X_UCLASS_WAIT_SYNCPT_THRESH_F(v) \ + host1x_uclass_wait_syncpt_thresh_f(v) +static inline u32 host1x_uclass_wait_syncpt_base_r(void) +{ + return 0x9; +} +#define HOST1X_UCLASS_WAIT_SYNCPT_BASE \ + host1x_uclass_wait_syncpt_base_r() +static inline u32 host1x_uclass_wait_syncpt_base_indx_f(u32 v) +{ + return (v & 0xff) << 24; +} +#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_INDX_F(v) \ + host1x_uclass_wait_syncpt_base_indx_f(v) +static inline u32 host1x_uclass_wait_syncpt_base_base_indx_f(u32 v) +{ + return (v & 0xff) << 16; +} +#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_BASE_INDX_F(v) \ + host1x_uclass_wait_syncpt_base_base_indx_f(v) +static inline u32 host1x_uclass_wait_syncpt_base_offset_f(u32 v) +{ + return (v & 0xffff) << 0; +} +#define HOST1X_UCLASS_WAIT_SYNCPT_BASE_OFFSET_F(v) \ + host1x_uclass_wait_syncpt_base_offset_f(v) +static inline u32 host1x_uclass_load_syncpt_base_r(void) +{ + return 0xb; +} +#define HOST1X_UCLASS_LOAD_SYNCPT_BASE \ + host1x_uclass_load_syncpt_base_r() +static inline u32 host1x_uclass_load_syncpt_base_base_indx_f(u32 v) +{ + return (v & 0xff) << 24; +} +#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_BASE_INDX_F(v) \ + host1x_uclass_load_syncpt_base_base_indx_f(v) +static inline u32 host1x_uclass_load_syncpt_base_value_f(u32 v) +{ + return (v & 0xffffff) << 0; +} +#define HOST1X_UCLASS_LOAD_SYNCPT_BASE_VALUE_F(v) \ + host1x_uclass_load_syncpt_base_value_f(v) +static inline u32 host1x_uclass_incr_syncpt_base_base_indx_f(u32 v) +{ + return (v & 0xff) << 24; +} +#define HOST1X_UCLASS_INCR_SYNCPT_BASE_BASE_INDX_F(v) \ + host1x_uclass_incr_syncpt_base_base_indx_f(v) +static inline u32 host1x_uclass_incr_syncpt_base_offset_f(u32 v) +{ + return (v & 0xffffff) << 0; +} +#define HOST1X_UCLASS_INCR_SYNCPT_BASE_OFFSET_F(v) \ + host1x_uclass_incr_syncpt_base_offset_f(v) +static inline u32 host1x_uclass_indoff_r(void) +{ + return 0x2d; +} +#define HOST1X_UCLASS_INDOFF \ + host1x_uclass_indoff_r() +static inline u32 host1x_uclass_indoff_indbe_f(u32 v) +{ + return (v & 0xf) << 28; +} +#define HOST1X_UCLASS_INDOFF_INDBE_F(v) \ + host1x_uclass_indoff_indbe_f(v) +static inline u32 host1x_uclass_indoff_autoinc_f(u32 v) +{ + return (v & 0x1) << 27; +} +#define HOST1X_UCLASS_INDOFF_AUTOINC_F(v) \ + host1x_uclass_indoff_autoinc_f(v) +static inline u32 host1x_uclass_indoff_indmodid_f(u32 v) +{ + return (v & 0xff) << 18; +} +#define HOST1X_UCLASS_INDOFF_INDMODID_F(v) \ + host1x_uclass_indoff_indmodid_f(v) +static inline u32 host1x_uclass_indoff_indroffset_f(u32 v) +{ + return (v & 0xffff) << 2; +} +#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \ + host1x_uclass_indoff_indroffset_f(v) +static inline u32 host1x_uclass_indoff_rwn_read_v(void) +{ + return 1; +} +#define HOST1X_UCLASS_INDOFF_INDROFFSET_F(v) \ + host1x_uclass_indoff_indroffset_f(v) + +#endif diff --git a/drivers/gpu/host1x/hw/hw_host1x06_vm.h b/drivers/gpu/host1x/hw/hw_host1x06_vm.h new file mode 100644 index 000000000000..e54b33902332 --- /dev/null +++ b/drivers/gpu/host1x/hw/hw_host1x06_vm.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017 NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#define HOST1X_CHANNEL_DMASTART 0x0000 +#define HOST1X_CHANNEL_DMASTART_HI 0x0004 +#define HOST1X_CHANNEL_DMAPUT 0x0008 +#define HOST1X_CHANNEL_DMAPUT_HI 0x000c +#define HOST1X_CHANNEL_DMAGET 0x0010 +#define HOST1X_CHANNEL_DMAGET_HI 0x0014 +#define HOST1X_CHANNEL_DMAEND 0x0018 +#define HOST1X_CHANNEL_DMAEND_HI 0x001c +#define HOST1X_CHANNEL_DMACTRL 0x0020 +#define HOST1X_CHANNEL_DMACTRL_DMASTOP BIT(0) +#define HOST1X_CHANNEL_DMACTRL_DMAGETRST BIT(1) +#define HOST1X_CHANNEL_DMACTRL_DMAINITGET BIT(2) +#define HOST1X_CHANNEL_CMDFIFO_STAT 0x0024 +#define HOST1X_CHANNEL_CMDFIFO_STAT_EMPTY BIT(13) +#define HOST1X_CHANNEL_CMDFIFO_RDATA 0x0028 +#define HOST1X_CHANNEL_CMDP_OFFSET 0x0030 +#define HOST1X_CHANNEL_CMDP_CLASS 0x0034 +#define HOST1X_CHANNEL_CHANNELSTAT 0x0038 +#define HOST1X_CHANNEL_CMDPROC_STOP 0x0048 +#define HOST1X_CHANNEL_TEARDOWN 0x004c + +#define HOST1X_SYNC_SYNCPT_CPU_INCR(x) (0x6400 + 4*(x)) +#define HOST1X_SYNC_SYNCPT_THRESH_CPU0_INT_STATUS(x) (0x6464 + 4*(x)) +#define HOST1X_SYNC_SYNCPT_THRESH_INT_ENABLE_CPU0(x) (0x652c + 4*(x)) +#define HOST1X_SYNC_SYNCPT_THRESH_INT_DISABLE(x) (0x6590 + 4*(x)) +#define HOST1X_SYNC_SYNCPT_BASE(x) (0x8000 + 4*(x)) +#define HOST1X_SYNC_SYNCPT(x) (0x8080 + 4*(x)) +#define HOST1X_SYNC_SYNCPT_INT_THRESH(x) (0x8a00 + 4*(x)) +#define HOST1X_SYNC_SYNCPT_CH_APP(x) (0x9384 + 4*(x)) +#define HOST1X_SYNC_SYNCPT_CH_APP_CH(v) (((v) & 0x3f) << 8) diff --git a/drivers/gpu/host1x/hw/intr_hw.c b/drivers/gpu/host1x/hw/intr_hw.c index 37ebb51703fa..329239237090 100644 --- a/drivers/gpu/host1x/hw/intr_hw.c +++ b/drivers/gpu/host1x/hw/intr_hw.c @@ -72,6 +72,23 @@ static void _host1x_intr_disable_all_syncpt_intrs(struct host1x *host) } } +static void intr_hw_init(struct host1x *host, u32 cpm) +{ +#if HOST1X_HW < 6 + /* disable the ip_busy_timeout. this prevents write drops */ + host1x_sync_writel(host, 0, HOST1X_SYNC_IP_BUSY_TIMEOUT); + + /* + * increase the auto-ack timout to the maximum value. 2d will hang + * otherwise on Tegra2. + */ + host1x_sync_writel(host, 0xff, HOST1X_SYNC_CTXSW_TIMEOUT_CFG); + + /* update host clocks per usec */ + host1x_sync_writel(host, cpm, HOST1X_SYNC_USEC_CLK); +#endif +} + static int _host1x_intr_init_host_sync(struct host1x *host, u32 cpm, void (*syncpt_thresh_work)(struct work_struct *)) @@ -92,17 +109,7 @@ _host1x_intr_init_host_sync(struct host1x *host, u32 cpm, return err; } - /* disable the ip_busy_timeout. this prevents write drops */ - host1x_sync_writel(host, 0, HOST1X_SYNC_IP_BUSY_TIMEOUT); - - /* - * increase the auto-ack timout to the maximum value. 2d will hang - * otherwise on Tegra2. - */ - host1x_sync_writel(host, 0xff, HOST1X_SYNC_CTXSW_TIMEOUT_CFG); - - /* update host clocks per usec */ - host1x_sync_writel(host, cpm, HOST1X_SYNC_USEC_CLK); + intr_hw_init(host, cpm); return 0; } diff --git a/drivers/gpu/host1x/hw/syncpt_hw.c b/drivers/gpu/host1x/hw/syncpt_hw.c index 7b0270d60742..7dfd47d74f89 100644 --- a/drivers/gpu/host1x/hw/syncpt_hw.c +++ b/drivers/gpu/host1x/hw/syncpt_hw.c @@ -106,6 +106,50 @@ static int syncpt_patch_wait(struct host1x_syncpt *sp, void *patch_addr) return 0; } +/** + * syncpt_assign_to_channel() - Assign syncpoint to channel + * @sp: syncpoint + * @ch: channel + * + * On chips with the syncpoint protection feature (Tegra186+), assign @sp to + * @ch, preventing other channels from incrementing the syncpoints. If @ch is + * NULL, unassigns the syncpoint. + * + * On older chips, do nothing. + */ +static void syncpt_assign_to_channel(struct host1x_syncpt *sp, + struct host1x_channel *ch) +{ +#if HOST1X_HW >= 6 + struct host1x *host = sp->host; + + if (!host->hv_regs) + return; + + host1x_sync_writel(host, + HOST1X_SYNC_SYNCPT_CH_APP_CH(ch ? ch->id : 0xff), + HOST1X_SYNC_SYNCPT_CH_APP(sp->id)); +#endif +} + +/** + * syncpt_enable_protection() - Enable syncpoint protection + * @host: host1x instance + * + * On chips with the syncpoint protection feature (Tegra186+), enable this + * feature. On older chips, do nothing. + */ +static void syncpt_enable_protection(struct host1x *host) +{ +#if HOST1X_HW >= 6 + if (!host->hv_regs) + return; + + host1x_hypervisor_writel(host, HOST1X_HV_SYNCPT_PROT_EN_CH_EN, + HOST1X_HV_SYNCPT_PROT_EN); +#endif +} + static const struct host1x_syncpt_ops host1x_syncpt_ops = { .restore = syncpt_restore, .restore_wait_base = syncpt_restore_wait_base, @@ -113,4 +157,6 @@ static const struct host1x_syncpt_ops host1x_syncpt_ops = { .load = syncpt_load, .cpu_incr = syncpt_cpu_incr, .patch_wait = syncpt_patch_wait, + .assign_to_channel = syncpt_assign_to_channel, + .enable_protection = syncpt_enable_protection, }; diff --git a/drivers/gpu/host1x/syncpt.c b/drivers/gpu/host1x/syncpt.c index 048ac9e344ce..a2a952adc136 100644 --- a/drivers/gpu/host1x/syncpt.c +++ b/drivers/gpu/host1x/syncpt.c @@ -54,7 +54,7 @@ static void host1x_syncpt_base_free(struct host1x_syncpt_base *base) } static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, - struct device *dev, + struct host1x_client *client, unsigned long flags) { int i; @@ -76,11 +76,11 @@ static struct host1x_syncpt *host1x_syncpt_alloc(struct host1x *host, } name = kasprintf(GFP_KERNEL, "%02u-%s", sp->id, - dev ? dev_name(dev) : NULL); + client ? dev_name(client->dev) : NULL); if (!name) goto free_base; - sp->dev = dev; + sp->client = client; sp->name = name; if (flags & HOST1X_SYNCPT_CLIENT_MANAGED) @@ -398,6 +398,13 @@ int host1x_syncpt_init(struct host1x *host) for (i = 0; i < host->info->nb_pts; i++) { syncpt[i].id = i; syncpt[i].host = host; + + /* + * Unassign syncpt from channels for purposes of Tegra186 + * syncpoint protection. This prevents any channel from + * accessing it until it is reassigned. + */ + host1x_hw_syncpt_assign_to_channel(host, &syncpt[i], NULL); } for (i = 0; i < host->info->nb_bases; i++) @@ -408,6 +415,7 @@ int host1x_syncpt_init(struct host1x *host) host->bases = bases; host1x_syncpt_restore(host); + host1x_hw_syncpt_enable_protection(host); /* Allocate sync point to use for clearing waits for expired fences */ host->nop_sp = host1x_syncpt_alloc(host, NULL, 0); @@ -419,7 +427,7 @@ int host1x_syncpt_init(struct host1x *host) /** * host1x_syncpt_request() - request a syncpoint - * @dev: device requesting the syncpoint + * @client: client requesting the syncpoint * @flags: flags * * host1x client drivers can use this function to allocate a syncpoint for @@ -427,12 +435,12 @@ int host1x_syncpt_init(struct host1x *host) * use by the client exclusively. When no longer using a syncpoint, a host1x * client driver needs to release it using host1x_syncpt_free(). */ -struct host1x_syncpt *host1x_syncpt_request(struct device *dev, +struct host1x_syncpt *host1x_syncpt_request(struct host1x_client *client, unsigned long flags) { - struct host1x *host = dev_get_drvdata(dev->parent); + struct host1x *host = dev_get_drvdata(client->parent->parent); - return host1x_syncpt_alloc(host, dev, flags); + return host1x_syncpt_alloc(host, client, flags); } EXPORT_SYMBOL(host1x_syncpt_request); @@ -456,7 +464,7 @@ void host1x_syncpt_free(struct host1x_syncpt *sp) host1x_syncpt_base_free(sp->base); kfree(sp->name); sp->base = NULL; - sp->dev = NULL; + sp->client = NULL; sp->name = NULL; sp->client_managed = false; diff --git a/drivers/gpu/host1x/syncpt.h b/drivers/gpu/host1x/syncpt.h index f719205105ac..9d88d37c2397 100644 --- a/drivers/gpu/host1x/syncpt.h +++ b/drivers/gpu/host1x/syncpt.h @@ -44,7 +44,7 @@ struct host1x_syncpt { const char *name; bool client_managed; struct host1x *host; - struct device *dev; + struct host1x_client *client; struct host1x_syncpt_base *base; /* interrupt data */ diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c index 6a573d21d3cc..658fa2d3e40c 100644 --- a/drivers/gpu/ipu-v3/ipu-common.c +++ b/drivers/gpu/ipu-v3/ipu-common.c @@ -405,6 +405,14 @@ int ipu_idmac_lock_enable(struct ipuv3_channel *channel, int num_bursts) return -EINVAL; } + /* + * IPUv3EX / i.MX51 has a different register layout, and on IPUv3M / + * i.MX53 channel arbitration locking doesn't seem to work properly. + * Allow enabling the lock feature on IPUv3H / i.MX6 only. + */ + if (bursts && ipu->ipu_type != IPUV3H) + return -EINVAL; + for (i = 0; i < ARRAY_SIZE(idmac_lock_en_info); i++) { if (channel->num == idmac_lock_en_info[i].chnum) break; diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c index c35f74c83065..c860a7997cb5 100644 --- a/drivers/gpu/ipu-v3/ipu-pre.c +++ b/drivers/gpu/ipu-v3/ipu-pre.c @@ -73,6 +73,14 @@ #define IPU_PRE_STORE_ENG_CTRL_WR_NUM_BYTES(v) ((v & 0x7) << 1) #define IPU_PRE_STORE_ENG_CTRL_OUTPUT_ACTIVE_BPP(v) ((v & 0x3) << 4) +#define IPU_PRE_STORE_ENG_STATUS 0x120 +#define IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_MASK 0xffff +#define IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_X_SHIFT 0 +#define IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK 0x3fff +#define IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT 16 +#define IPU_PRE_STORE_ENG_STATUS_STORE_FIFO_FULL (1 << 30) +#define IPU_PRE_STORE_ENG_STATUS_STORE_FIELD (1 << 31) + #define IPU_PRE_STORE_ENG_SIZE 0x130 #define IPU_PRE_STORE_ENG_SIZE_INPUT_WIDTH(v) ((v & 0xffff) << 0) #define IPU_PRE_STORE_ENG_SIZE_INPUT_HEIGHT(v) ((v & 0xffff) << 16) @@ -93,6 +101,7 @@ struct ipu_pre { dma_addr_t buffer_paddr; void *buffer_virt; bool in_use; + unsigned int safe_window_end; }; static DEFINE_MUTEX(ipu_pre_list_mutex); @@ -160,6 +169,9 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width, u32 active_bpp = info->cpp[0] >> 1; u32 val; + /* calculate safe window for ctrl register updates */ + pre->safe_window_end = height - 2; + writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF); writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); @@ -199,7 +211,24 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width, void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr) { + unsigned long timeout = jiffies + msecs_to_jiffies(5); + unsigned short current_yblock; + u32 val; + writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF); + + do { + if (time_after(jiffies, timeout)) { + dev_warn(pre->dev, "timeout waiting for PRE safe window\n"); + return; + } + + val = readl(pre->regs + IPU_PRE_STORE_ENG_STATUS); + current_yblock = + (val >> IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_SHIFT) & + IPU_PRE_STORE_ENG_STATUS_STORE_BLOCK_Y_MASK; + } while (current_yblock == 0 || current_yblock >= pre->safe_window_end); + writel(IPU_PRE_CTRL_SDW_UPDATE, pre->regs + IPU_PRE_CTRL_SET); } diff --git a/drivers/gpu/ipu-v3/ipu-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c index ecc9ea44dc50..0013ca9f72c8 100644 --- a/drivers/gpu/ipu-v3/ipu-prg.c +++ b/drivers/gpu/ipu-v3/ipu-prg.c @@ -14,6 +14,7 @@ #include <drm/drm_fourcc.h> #include <linux/clk.h> #include <linux/err.h> +#include <linux/iopoll.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> #include <linux/module.h> @@ -329,6 +330,12 @@ int ipu_prg_channel_configure(struct ipuv3_channel *ipu_chan, val = IPU_PRG_REG_UPDATE_REG_UPDATE; writel(val, prg->regs + IPU_PRG_REG_UPDATE); + /* wait for both double buffers to be filled */ + readl_poll_timeout(prg->regs + IPU_PRG_STATUS, val, + (val & IPU_PRG_STATUS_BUFFER0_READY(prg_chan)) && + (val & IPU_PRG_STATUS_BUFFER1_READY(prg_chan)), + 5, 1000); + clk_disable_unprepare(prg->clk_ipg); chan->enabled = true; diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 0a3117cc29e7..374301fcbc86 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -281,6 +281,7 @@ config HID_ELECOM Support for ELECOM devices: - BM084 Bluetooth Mouse - DEFT Trackball (Wired and wireless) + - HUGE Trackball (Wired and wireless) config HID_ELO tristate "ELO USB 4000/4500 touchscreen" diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9bc91160819b..330ca983828b 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2032,6 +2032,8 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) }, #endif #if IS_ENABLED(CONFIG_HID_ELO) { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index e2c7465df69f..54aeea57d209 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c @@ -3,6 +3,7 @@ * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com> * Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com> * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu> + * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org> */ /* @@ -32,9 +33,11 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, break; case USB_DEVICE_ID_ELECOM_DEFT_WIRED: case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS: - /* The DEFT trackball has eight buttons, but its descriptor only - * reports five, disabling the three Fn buttons on the top of - * the mouse. + case USB_DEVICE_ID_ELECOM_HUGE_WIRED: + case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS: + /* The DEFT/HUGE trackball has eight buttons, but its descriptor + * only reports five, disabling the three Fn buttons on the top + * of the mouse. * * Apply the following diff to the descriptor: * @@ -62,7 +65,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, * End Collection, End Collection, */ if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) { - hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n"); + hid_info(hdev, "Fixing up Elecom DEFT/HUGE Fn buttons\n"); rdesc[13] = 8; /* Button/Variable Report Count */ rdesc[21] = 8; /* Button/Variable Usage Maximum */ rdesc[29] = 0; /* Button/Constant Report Count */ @@ -76,6 +79,8 @@ static const struct hid_device_id elecom_devices[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) }, + { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) }, { } }; MODULE_DEVICE_TABLE(hid, elecom_devices); diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b397a14ab970..be2e005c3c51 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -368,6 +368,8 @@ #define USB_DEVICE_ID_ELECOM_BM084 0x0061 #define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe #define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff +#define USB_DEVICE_ID_ELECOM_HUGE_WIRED 0x010c +#define USB_DEVICE_ID_ELECOM_HUGE_WIRELESS 0x010d #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 @@ -533,6 +535,7 @@ #define USB_VENDOR_ID_IDEACOM 0x1cb6 #define USB_DEVICE_ID_IDEACOM_IDC6650 0x6650 #define USB_DEVICE_ID_IDEACOM_IDC6651 0x6651 +#define USB_DEVICE_ID_IDEACOM_IDC6680 0x6680 #define USB_VENDOR_ID_ILITEK 0x222a #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 @@ -660,6 +663,7 @@ #define USB_DEVICE_ID_LENOVO_CBTKBD 0x6048 #define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067 #define USB_DEVICE_ID_LENOVO_X1_COVER 0x6085 +#define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3 #define USB_VENDOR_ID_LG 0x1fd2 #define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 440b999304a5..9e8c4d2ba11d 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -930,6 +930,7 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, field->application != HID_DG_PEN && field->application != HID_DG_TOUCHPAD && field->application != HID_GD_KEYBOARD && + field->application != HID_GD_SYSTEM_CONTROL && field->application != HID_CP_CONSUMER_CONTROL && field->application != HID_GD_WIRELESS_RADIO_CTLS && !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS && @@ -1419,6 +1420,12 @@ static const struct hid_device_id mt_devices[] = { USB_VENDOR_ID_ALPS_JP, HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP) }, + /* Lenovo X1 TAB Gen 2 */ + { .driver_data = MT_CLS_WIN_8_DUAL, + HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_LENOVO, + USB_DEVICE_ID_LENOVO_X1_TAB) }, + /* Anton devices */ { .driver_data = MT_CLS_EXPORT_ALL_INPUTS, MT_USB_DEVICE(USB_VENDOR_ID_ANTON, diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 5b40c2614599..ef241d66562e 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c @@ -436,17 +436,24 @@ static int rmi_post_resume(struct hid_device *hdev) if (!(data->device_flags & RMI_DEVICE)) return 0; - ret = rmi_reset_attn_mode(hdev); + /* Make sure the HID device is ready to receive events */ + ret = hid_hw_open(hdev); if (ret) return ret; + ret = rmi_reset_attn_mode(hdev); + if (ret) + goto out; + ret = rmi_driver_resume(rmi_dev, false); if (ret) { hid_warn(hdev, "Failed to resume device: %d\n", ret); - return ret; + goto out; } - return 0; +out: + hid_hw_close(hdev); + return ret; } #endif /* CONFIG_PM */ diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index ec530454e6f6..5fbe0f81ab2e 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -337,8 +337,8 @@ static void drop_ref(struct hidraw *hidraw, int exists_bit) kfree(hidraw); } else { /* close device for last reader */ - hid_hw_power(hidraw->hid, PM_HINT_NORMAL); hid_hw_close(hidraw->hid); + hid_hw_power(hidraw->hid, PM_HINT_NORMAL); } } } diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 77396145d2d0..9145c2129a96 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -543,7 +543,8 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size) { /* the worst case is computed from the set_report command with a * reportID > 15 and the maximum report length */ - int args_len = sizeof(__u8) + /* optional ReportID byte */ + int args_len = sizeof(__u8) + /* ReportID */ + sizeof(__u8) + /* optional ReportID byte */ sizeof(__u16) + /* data register */ sizeof(__u16) + /* size of the report */ report_size; /* report */ diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 089bad8a9a21..045b5da9b992 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -975,6 +975,8 @@ static int usbhid_parse(struct hid_device *hid) unsigned int rsize = 0; char *rdesc; int ret, n; + int num_descriptors; + size_t offset = offsetof(struct hid_descriptor, desc); quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), le16_to_cpu(dev->descriptor.idProduct)); @@ -997,10 +999,18 @@ static int usbhid_parse(struct hid_device *hid) return -ENODEV; } + if (hdesc->bLength < sizeof(struct hid_descriptor)) { + dbg_hid("hid descriptor is too short\n"); + return -EINVAL; + } + hid->version = le16_to_cpu(hdesc->bcdHID); hid->country = hdesc->bCountryCode; - for (n = 0; n < hdesc->bNumDescriptors; n++) + num_descriptors = min_t(int, hdesc->bNumDescriptors, + (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor)); + + for (n = 0; n < num_descriptors; n++) if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index a83fa76655b9..f489a5cfcb48 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -99,6 +99,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0A4A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_LOGITECH_OEM_USB_OPTICAL_MOUSE_0B4A, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_HP, USB_PRODUCT_ID_HP_PIXART_OEM_USB_OPTICAL_MOUSE, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_IDEACOM, USB_DEVICE_ID_IDEACOM_IDC6680, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C007, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL }, { USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KEYBOARD_G710_PLUS, HID_QUIRK_NOGET }, diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index e82a696a1d07..906e654fb0ba 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -668,8 +668,10 @@ static struct wacom_hdev_data *wacom_get_hdev_data(struct hid_device *hdev) /* Try to find an already-probed interface from the same device */ list_for_each_entry(data, &wacom_udev_list, list) { - if (compare_device_paths(hdev, data->dev, '/')) + if (compare_device_paths(hdev, data->dev, '/')) { + kref_get(&data->kref); return data; + } } /* Fallback to finding devices that appear to be "siblings" */ @@ -766,6 +768,9 @@ static int wacom_led_control(struct wacom *wacom) if (!wacom->led.groups) return -ENOTSUPP; + if (wacom->wacom_wac.features.type == REMOTE) + return -ENOTSUPP; + if (wacom->wacom_wac.pid) { /* wireless connected */ report_id = WAC_CMD_WL_LED_CONTROL; buf_size = 13; diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index bb17d7bbefd3..aa692e28b2cd 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -567,8 +567,8 @@ static int wacom_intuos_pad(struct wacom_wac *wacom) keys = data[9] & 0x07; } } else { - buttons = ((data[6] & 0x10) << 10) | - ((data[5] & 0x10) << 9) | + buttons = ((data[6] & 0x10) << 5) | + ((data[5] & 0x10) << 4) | ((data[6] & 0x0F) << 4) | (data[5] & 0x0F); } @@ -1227,11 +1227,17 @@ static void wacom_intuos_pro2_bt_pen(struct wacom_wac *wacom) continue; if (range) { + /* Fix rotation alignment: userspace expects zero at left */ + int16_t rotation = (int16_t)get_unaligned_le16(&frame[9]); + rotation += 1800/4; + if (rotation > 899) + rotation -= 1800; + input_report_abs(pen_input, ABS_X, get_unaligned_le16(&frame[1])); input_report_abs(pen_input, ABS_Y, get_unaligned_le16(&frame[3])); - input_report_abs(pen_input, ABS_TILT_X, frame[7]); - input_report_abs(pen_input, ABS_TILT_Y, frame[8]); - input_report_abs(pen_input, ABS_Z, get_unaligned_le16(&frame[9])); + input_report_abs(pen_input, ABS_TILT_X, (char)frame[7]); + input_report_abs(pen_input, ABS_TILT_Y, (char)frame[8]); + input_report_abs(pen_input, ABS_Z, rotation); input_report_abs(pen_input, ABS_WHEEL, get_unaligned_le16(&frame[11])); } input_report_abs(pen_input, ABS_PRESSURE, get_unaligned_le16(&frame[5])); @@ -1319,12 +1325,19 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom) unsigned char *data = wacom->data; int buttons = (data[282] << 1) | ((data[281] >> 6) & 0x01); - int ring = data[285]; - int prox = buttons | (ring & 0x80); + int ring = data[285] & 0x7F; + bool ringstatus = data[285] & 0x80; + bool prox = buttons || ringstatus; + + /* Fix touchring data: userspace expects 0 at left and increasing clockwise */ + ring = 71 - ring; + ring += 3*72/16; + if (ring > 71) + ring -= 72; wacom_report_numbered_buttons(pad_input, 9, buttons); - input_report_abs(pad_input, ABS_WHEEL, (ring & 0x80) ? (ring & 0x7f) : 0); + input_report_abs(pad_input, ABS_WHEEL, ringstatus ? ring : 0); input_report_key(pad_input, wacom->tool[1], prox ? 1 : 0); input_report_abs(pad_input, ABS_MISC, prox ? PAD_DEVICE_ID : 0); @@ -1616,6 +1629,20 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) return 0; } +static int wacom_offset_rotation(struct input_dev *input, struct hid_usage *usage, + int value, int num, int denom) +{ + struct input_absinfo *abs = &input->absinfo[usage->code]; + int range = (abs->maximum - abs->minimum + 1); + + value += num*range/denom; + if (value > abs->maximum) + value -= range; + else if (value < abs->minimum) + value += range; + return value; +} + int wacom_equivalent_usage(int usage) { if ((usage & HID_USAGE_PAGE) == WACOM_HID_UP_WACOMDIGITIZER) { @@ -1898,6 +1925,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field unsigned equivalent_usage = wacom_equivalent_usage(usage->hid); int i; bool is_touch_on = value; + bool do_report = false; /* * Avoid reporting this event and setting inrange_state if this usage @@ -1912,6 +1940,29 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field } switch (equivalent_usage) { + case WACOM_HID_WD_TOUCHRING: + /* + * Userspace expects touchrings to increase in value with + * clockwise gestures and have their zero point at the + * tablet's left. HID events "should" be clockwise- + * increasing and zero at top, though the MobileStudio + * Pro and 2nd-gen Intuos Pro don't do this... + */ + if (hdev->vendor == 0x56a && + (hdev->product == 0x34d || hdev->product == 0x34e || /* MobileStudio Pro */ + hdev->product == 0x357 || hdev->product == 0x358)) { /* Intuos Pro 2 */ + value = (field->logical_maximum - value); + + if (hdev->product == 0x357 || hdev->product == 0x358) + value = wacom_offset_rotation(input, usage, value, 3, 16); + else if (hdev->product == 0x34d || hdev->product == 0x34e) + value = wacom_offset_rotation(input, usage, value, 1, 2); + } + else { + value = wacom_offset_rotation(input, usage, value, 1, 4); + } + do_report = true; + break; case WACOM_HID_WD_TOUCHRINGSTATUS: if (!value) input_event(input, usage->type, usage->code, 0); @@ -1945,10 +1996,14 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field value, i); /* fall through*/ default: + do_report = true; + break; + } + + if (do_report) { input_event(input, usage->type, usage->code, value); if (value) wacom_wac->hid_data.pad_input_event_flag = true; - break; } } @@ -2086,22 +2141,34 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field wacom_wac->hid_data.tipswitch |= value; return; case HID_DG_TOOLSERIALNUMBER: - wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL); - wacom_wac->serial[0] |= (__u32)value; + if (value) { + wacom_wac->serial[0] = (wacom_wac->serial[0] & ~0xFFFFFFFFULL); + wacom_wac->serial[0] |= (__u32)value; + } return; + case HID_DG_TWIST: + /* + * Userspace expects pen twist to have its zero point when + * the buttons/finger is on the tablet's left. HID values + * are zero when buttons are toward the top. + */ + value = wacom_offset_rotation(input, usage, value, 1, 4); + break; case WACOM_HID_WD_SENSE: wacom_wac->hid_data.sense_state = value; return; case WACOM_HID_WD_SERIALHI: - wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF); - wacom_wac->serial[0] |= ((__u64)value) << 32; - /* - * Non-USI EMR devices may contain additional tool type - * information here. See WACOM_HID_WD_TOOLTYPE case for - * more details. - */ - if (value >> 20 == 1) { - wacom_wac->id[0] |= value & 0xFFFFF; + if (value) { + wacom_wac->serial[0] = (wacom_wac->serial[0] & 0xFFFFFFFF); + wacom_wac->serial[0] |= ((__u64)value) << 32; + /* + * Non-USI EMR devices may contain additional tool type + * information here. See WACOM_HID_WD_TOOLTYPE case for + * more details. + */ + if (value >> 20 == 1) { + wacom_wac->id[0] |= value & 0xFFFFF; + } } return; case WACOM_HID_WD_TOOLTYPE: @@ -2205,7 +2272,7 @@ static void wacom_wac_pen_report(struct hid_device *hdev, input_report_key(input, wacom_wac->tool[0], prox); if (wacom_wac->serial[0]) { input_event(input, EV_MSC, MSC_SERIAL, wacom_wac->serial[0]); - input_report_abs(input, ABS_MISC, id); + input_report_abs(input, ABS_MISC, prox ? id : 0); } wacom_wac->hid_data.tipswitch = false; @@ -2216,6 +2283,7 @@ static void wacom_wac_pen_report(struct hid_device *hdev, if (!prox) { wacom_wac->tool[0] = 0; wacom_wac->id[0] = 0; + wacom_wac->serial[0] = 0; } } diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index efd5db743319..894b67ac2cae 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -640,6 +640,7 @@ void vmbus_close(struct vmbus_channel *channel) */ return; } + mutex_lock(&vmbus_connection.channel_mutex); /* * Close all the sub-channels first and then close the * primary channel. @@ -648,16 +649,15 @@ void vmbus_close(struct vmbus_channel *channel) cur_channel = list_entry(cur, struct vmbus_channel, sc_list); vmbus_close_internal(cur_channel); if (cur_channel->rescind) { - mutex_lock(&vmbus_connection.channel_mutex); - hv_process_channel_removal(cur_channel, + hv_process_channel_removal( cur_channel->offermsg.child_relid); - mutex_unlock(&vmbus_connection.channel_mutex); } } /* * Now close the primary. */ vmbus_close_internal(channel); + mutex_unlock(&vmbus_connection.channel_mutex); } EXPORT_SYMBOL_GPL(vmbus_close); diff --git a/drivers/hv/channel_mgmt.c b/drivers/hv/channel_mgmt.c index 060df71c2e8b..379b0df123be 100644 --- a/drivers/hv/channel_mgmt.c +++ b/drivers/hv/channel_mgmt.c @@ -159,7 +159,7 @@ static void vmbus_rescind_cleanup(struct vmbus_channel *channel) spin_lock_irqsave(&vmbus_connection.channelmsg_lock, flags); - + channel->rescind = true; list_for_each_entry(msginfo, &vmbus_connection.chn_msg_list, msglistentry) { @@ -381,14 +381,21 @@ static void vmbus_release_relid(u32 relid) true); } -void hv_process_channel_removal(struct vmbus_channel *channel, u32 relid) +void hv_process_channel_removal(u32 relid) { unsigned long flags; - struct vmbus_channel *primary_channel; + struct vmbus_channel *primary_channel, *channel; - BUG_ON(!channel->rescind); BUG_ON(!mutex_is_locked(&vmbus_connection.channel_mutex)); + /* + * Make sure channel is valid as we may have raced. + */ + channel = relid2channel(relid); + if (!channel) + return; + + BUG_ON(!channel->rescind); if (channel->target_cpu != get_cpu()) { put_cpu(); smp_call_function_single(channel->target_cpu, @@ -515,6 +522,7 @@ static void vmbus_process_offer(struct vmbus_channel *newchannel) if (!fnew) { if (channel->sc_creation_callback != NULL) channel->sc_creation_callback(newchannel); + newchannel->probe_done = true; return; } @@ -834,7 +842,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) { struct vmbus_channel_rescind_offer *rescind; struct vmbus_channel *channel; - unsigned long flags; struct device *dev; rescind = (struct vmbus_channel_rescind_offer *)hdr; @@ -873,16 +880,6 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) return; } - spin_lock_irqsave(&channel->lock, flags); - channel->rescind = true; - spin_unlock_irqrestore(&channel->lock, flags); - - /* - * Now that we have posted the rescind state, perform - * rescind related cleanup. - */ - vmbus_rescind_cleanup(channel); - /* * Now wait for offer handling to complete. */ @@ -901,6 +898,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) if (channel->device_obj) { if (channel->chn_rescind_callback) { channel->chn_rescind_callback(channel); + vmbus_rescind_cleanup(channel); return; } /* @@ -909,6 +907,7 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) */ dev = get_device(&channel->device_obj->device); if (dev) { + vmbus_rescind_cleanup(channel); vmbus_device_unregister(channel->device_obj); put_device(dev); } @@ -921,29 +920,28 @@ static void vmbus_onoffer_rescind(struct vmbus_channel_message_header *hdr) * 1. Close all sub-channels first * 2. Then close the primary channel. */ + mutex_lock(&vmbus_connection.channel_mutex); + vmbus_rescind_cleanup(channel); if (channel->state == CHANNEL_OPEN_STATE) { /* * The channel is currently not open; * it is safe for us to cleanup the channel. */ - mutex_lock(&vmbus_connection.channel_mutex); - hv_process_channel_removal(channel, - channel->offermsg.child_relid); - mutex_unlock(&vmbus_connection.channel_mutex); + hv_process_channel_removal(rescind->child_relid); } + mutex_unlock(&vmbus_connection.channel_mutex); } } void vmbus_hvsock_device_unregister(struct vmbus_channel *channel) { - mutex_lock(&vmbus_connection.channel_mutex); - BUG_ON(!is_hvsock_channel(channel)); - channel->rescind = true; - vmbus_device_unregister(channel->device_obj); + /* We always get a rescind msg when a connection is closed. */ + while (!READ_ONCE(channel->probe_done) || !READ_ONCE(channel->rescind)) + msleep(1); - mutex_unlock(&vmbus_connection.channel_mutex); + vmbus_device_unregister(channel->device_obj); } EXPORT_SYMBOL_GPL(vmbus_hvsock_device_unregister); diff --git a/drivers/hv/hv_fcopy.c b/drivers/hv/hv_fcopy.c index daa75bd41f86..2364281d8593 100644 --- a/drivers/hv/hv_fcopy.c +++ b/drivers/hv/hv_fcopy.c @@ -170,6 +170,10 @@ static void fcopy_send_data(struct work_struct *dummy) out_src = smsg_out; break; + case WRITE_TO_FILE: + out_src = fcopy_transaction.fcopy_msg; + out_len = sizeof(struct hv_do_fcopy); + break; default: out_src = fcopy_transaction.fcopy_msg; out_len = fcopy_transaction.recv_len; diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index a9d49f6f6501..937801ac2fe0 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -768,8 +768,7 @@ static void vmbus_device_release(struct device *device) struct vmbus_channel *channel = hv_dev->channel; mutex_lock(&vmbus_connection.channel_mutex); - hv_process_channel_removal(channel, - channel->offermsg.child_relid); + hv_process_channel_removal(channel->offermsg.child_relid); mutex_unlock(&vmbus_connection.channel_mutex); kfree(hv_dev); diff --git a/drivers/hwmon/da9052-hwmon.c b/drivers/hwmon/da9052-hwmon.c index 97a62f5b9ea4..a973eb6a2890 100644 --- a/drivers/hwmon/da9052-hwmon.c +++ b/drivers/hwmon/da9052-hwmon.c @@ -477,6 +477,11 @@ static int da9052_hwmon_probe(struct platform_device *pdev) /* disable touchscreen features */ da9052_reg_write(hwmon->da9052, DA9052_TSI_CONT_A_REG, 0x00); + /* Sample every 1ms */ + da9052_reg_update(hwmon->da9052, DA9052_ADC_CONT_REG, + DA9052_ADCCONT_ADCMODE, + DA9052_ADCCONT_ADCMODE); + err = da9052_request_irq(hwmon->da9052, DA9052_IRQ_TSIREADY, "tsiready-irq", da9052_tsi_datardy_irq, hwmon); diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 5eafbaada795..dfc40c740d07 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -268,14 +268,11 @@ static int tmp102_probe(struct i2c_client *client, return err; } - tmp102->ready_time = jiffies; - if (tmp102->config_orig & TMP102_CONF_SD) { - /* - * Mark that we are not ready with data until the first - * conversion is complete - */ - tmp102->ready_time += msecs_to_jiffies(CONVERSION_TIME_MS); - } + /* + * Mark that we are not ready with data until the first + * conversion is complete + */ + tmp102->ready_time = jiffies + msecs_to_jiffies(CONVERSION_TIME_MS); hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, tmp102, diff --git a/drivers/hwmon/xgene-hwmon.c b/drivers/hwmon/xgene-hwmon.c index 9c0dbb8191ad..e1be61095532 100644 --- a/drivers/hwmon/xgene-hwmon.c +++ b/drivers/hwmon/xgene-hwmon.c @@ -630,7 +630,7 @@ static int xgene_hwmon_probe(struct platform_device *pdev) sizeof(struct slimpro_resp_msg) * ASYNC_MSG_FIFO_SIZE, GFP_KERNEL); if (rc) - goto out_mbox_free; + return -ENOMEM; INIT_WORK(&ctx->workq, xgene_hwmon_evt_work); @@ -646,7 +646,8 @@ static int xgene_hwmon_probe(struct platform_device *pdev) if (IS_ERR(ctx->mbox_chan)) { dev_err(&pdev->dev, "SLIMpro mailbox channel request failed\n"); - return -ENODEV; + rc = -ENODEV; + goto out_mbox_free; } } else { struct acpi_pcct_hw_reduced *cppc_ss; @@ -654,7 +655,8 @@ static int xgene_hwmon_probe(struct platform_device *pdev) if (device_property_read_u32(&pdev->dev, "pcc-channel", &ctx->mbox_idx)) { dev_err(&pdev->dev, "no pcc-channel property\n"); - return -ENODEV; + rc = -ENODEV; + goto out_mbox_free; } cl->rx_callback = xgene_hwmon_pcc_rx_cb; @@ -662,7 +664,8 @@ static int xgene_hwmon_probe(struct platform_device *pdev) if (IS_ERR(ctx->mbox_chan)) { dev_err(&pdev->dev, "PPC channel request failed\n"); - return -ENODEV; + rc = -ENODEV; + goto out_mbox_free; } /* @@ -675,13 +678,13 @@ static int xgene_hwmon_probe(struct platform_device *pdev) if (!cppc_ss) { dev_err(&pdev->dev, "PPC subspace not found\n"); rc = -ENODEV; - goto out_mbox_free; + goto out; } if (!ctx->mbox_chan->mbox->txdone_irq) { dev_err(&pdev->dev, "PCC IRQ not supported\n"); rc = -ENODEV; - goto out_mbox_free; + goto out; } /* @@ -696,14 +699,14 @@ static int xgene_hwmon_probe(struct platform_device *pdev) } else { dev_err(&pdev->dev, "Failed to get PCC comm region\n"); rc = -ENODEV; - goto out_mbox_free; + goto out; } if (!ctx->pcc_comm_addr) { dev_err(&pdev->dev, "Failed to ioremap PCC comm region\n"); rc = -ENOMEM; - goto out_mbox_free; + goto out; } /* diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c index bc9cebc30526..c2a2ce8ee541 100644 --- a/drivers/hwtracing/intel_th/pci.c +++ b/drivers/hwtracing/intel_th/pci.c @@ -144,6 +144,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { .driver_data = (kernel_ulong_t)0, }, { + /* Lewisburg PCH */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xa1a6), + .driver_data = (kernel_ulong_t)0, + }, + { /* Gemini Lake */ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x318e), .driver_data = (kernel_ulong_t)&intel_th_2x, @@ -158,6 +163,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9da6), .driver_data = (kernel_ulong_t)&intel_th_2x, }, + { + /* Cedar Fork PCH */ + PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x18e1), + .driver_data = (kernel_ulong_t)&intel_th_2x, + }, { 0 }, }; diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c index 9414900575d8..f129869e05a9 100644 --- a/drivers/hwtracing/stm/core.c +++ b/drivers/hwtracing/stm/core.c @@ -1119,7 +1119,7 @@ void stm_source_unregister_device(struct stm_source_data *data) stm_source_link_drop(src); - device_destroy(&stm_source_class, src->dev.devt); + device_unregister(&src->dev); } EXPORT_SYMBOL_GPL(stm_source_unregister_device); diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index c06dce2c1da7..45a3f3ca29b3 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -131,6 +131,7 @@ config I2C_I801 Gemini Lake (SOC) Cannon Lake-H (PCH) Cannon Lake-LP (PCH) + Cedar Fork (PCH) This driver can also be built as a module. If so, the module will be called i2c-i801. diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index e114e4e00d29..9e12a53ef7b8 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -68,6 +68,7 @@ * Gemini Lake (SOC) 0x31d4 32 hard yes yes yes * Cannon Lake-H (PCH) 0xa323 32 hard yes yes yes * Cannon Lake-LP (PCH) 0x9da3 32 hard yes yes yes + * Cedar Fork (PCH) 0x18df 32 hard yes yes yes * * Features supported by this driver: * Software PEC no @@ -204,6 +205,7 @@ /* Older devices have their ID defined in <linux/pci_ids.h> */ #define PCI_DEVICE_ID_INTEL_BAYTRAIL_SMBUS 0x0f12 +#define PCI_DEVICE_ID_INTEL_CDF_SMBUS 0x18df #define PCI_DEVICE_ID_INTEL_DNV_SMBUS 0x19df #define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS 0x1c22 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS 0x1d22 @@ -1025,6 +1027,7 @@ static const struct pci_device_id i801_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BRASWELL_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_SMBUS) }, + { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_CDF_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DNV_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROXTON_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS) }, @@ -1513,6 +1516,7 @@ static int i801_probe(struct pci_dev *dev, const struct pci_device_id *id) case PCI_DEVICE_ID_INTEL_CANNONLAKE_LP_SMBUS: case PCI_DEVICE_ID_INTEL_LEWISBURG_SMBUS: case PCI_DEVICE_ID_INTEL_LEWISBURG_SSKU_SMBUS: + case PCI_DEVICE_ID_INTEL_CDF_SMBUS: case PCI_DEVICE_ID_INTEL_DNV_SMBUS: case PCI_DEVICE_ID_INTEL_KABYLAKE_PCH_H_SMBUS: priv->features |= FEATURE_I2C_BLOCK_READ; diff --git a/drivers/i2c/busses/i2c-img-scb.c b/drivers/i2c/busses/i2c-img-scb.c index 84fb35f6837f..eb1d91b986fd 100644 --- a/drivers/i2c/busses/i2c-img-scb.c +++ b/drivers/i2c/busses/i2c-img-scb.c @@ -1459,6 +1459,6 @@ static struct platform_driver img_scb_i2c_driver = { }; module_platform_driver(img_scb_i2c_driver); -MODULE_AUTHOR("James Hogan <james.hogan@imgtec.com>"); +MODULE_AUTHOR("James Hogan <jhogan@kernel.org>"); MODULE_DESCRIPTION("IMG host I2C driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 54a47b40546f..f96830ffd9f1 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -1021,7 +1021,7 @@ static int i2c_imx_init_recovery_info(struct imx_i2c_struct *i2c_imx, } dev_dbg(&pdev->dev, "using scl-gpio %d and sda-gpio %d for recovery\n", - rinfo->sda_gpio, rinfo->scl_gpio); + rinfo->scl_gpio, rinfo->sda_gpio); rinfo->prepare_recovery = i2c_imx_prepare_recovery; rinfo->unprepare_recovery = i2c_imx_unprepare_recovery; @@ -1100,7 +1100,7 @@ static int i2c_imx_probe(struct platform_device *pdev) } /* Request IRQ */ - ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, 0, + ret = devm_request_irq(&pdev->dev, irq, i2c_imx_isr, IRQF_SHARED, pdev->name, i2c_imx); if (ret) { dev_err(&pdev->dev, "can't claim irq %d\n", irq); diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index 22ffcb73c185..b51adffa4841 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c @@ -340,12 +340,15 @@ static int ismt_process_desc(const struct ismt_desc *desc, data->word = dma_buffer[0] | (dma_buffer[1] << 8); break; case I2C_SMBUS_BLOCK_DATA: - case I2C_SMBUS_I2C_BLOCK_DATA: if (desc->rxbytes != dma_buffer[0] + 1) return -EMSGSIZE; memcpy(data->block, dma_buffer, desc->rxbytes); break; + case I2C_SMBUS_I2C_BLOCK_DATA: + memcpy(&data->block[1], dma_buffer, desc->rxbytes); + data->block[0] = desc->rxbytes; + break; } return 0; } diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 1ebb5e947e0b..23c2ea2baedc 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -360,6 +360,7 @@ static int omap_i2c_init(struct omap_i2c_dev *omap) unsigned long fclk_rate = 12000000; unsigned long internal_clk = 0; struct clk *fclk; + int error; if (omap->rev >= OMAP_I2C_REV_ON_3430_3530) { /* @@ -378,6 +379,13 @@ static int omap_i2c_init(struct omap_i2c_dev *omap) * do this bit unconditionally. */ fclk = clk_get(omap->dev, "fck"); + if (IS_ERR(fclk)) { + error = PTR_ERR(fclk); + dev_err(omap->dev, "could not get fck: %i\n", error); + + return error; + } + fclk_rate = clk_get_rate(fclk); clk_put(fclk); @@ -410,6 +418,12 @@ static int omap_i2c_init(struct omap_i2c_dev *omap) else internal_clk = 4000; fclk = clk_get(omap->dev, "fck"); + if (IS_ERR(fclk)) { + error = PTR_ERR(fclk); + dev_err(omap->dev, "could not get fck: %i\n", error); + + return error; + } fclk_rate = clk_get_rate(fclk) / 1000; clk_put(fclk); diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c index 0ecdb47a23ab..174579d32e5f 100644 --- a/drivers/i2c/busses/i2c-piix4.c +++ b/drivers/i2c/busses/i2c-piix4.c @@ -85,6 +85,9 @@ /* SB800 constants */ #define SB800_PIIX4_SMB_IDX 0xcd6 +#define KERNCZ_IMC_IDX 0x3e +#define KERNCZ_IMC_DATA 0x3f + /* * SB800 port is selected by bits 2:1 of the smb_en register (0x2c) * or the smb_sel register (0x2e), depending on bit 0 of register 0x2f. @@ -94,6 +97,12 @@ #define SB800_PIIX4_PORT_IDX_ALT 0x2e #define SB800_PIIX4_PORT_IDX_SEL 0x2f #define SB800_PIIX4_PORT_IDX_MASK 0x06 +#define SB800_PIIX4_PORT_IDX_SHIFT 1 + +/* On kerncz, SmBus0Sel is at bit 20:19 of PMx00 DecodeEn */ +#define SB800_PIIX4_PORT_IDX_KERNCZ 0x02 +#define SB800_PIIX4_PORT_IDX_MASK_KERNCZ 0x18 +#define SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ 3 /* insmod parameters */ @@ -149,6 +158,8 @@ static const struct dmi_system_id piix4_dmi_ibm[] = { */ static DEFINE_MUTEX(piix4_mutex_sb800); static u8 piix4_port_sel_sb800; +static u8 piix4_port_mask_sb800; +static u8 piix4_port_shift_sb800; static const char *piix4_main_port_names_sb800[PIIX4_MAX_ADAPTERS] = { " port 0", " port 2", " port 3", " port 4" }; @@ -159,6 +170,7 @@ struct i2c_piix4_adapdata { /* SB800 */ bool sb800_main; + bool notify_imc; u8 port; /* Port number, shifted */ }; @@ -347,7 +359,19 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, /* Find which register is used for port selection */ if (PIIX4_dev->vendor == PCI_VENDOR_ID_AMD) { - piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT; + switch (PIIX4_dev->device) { + case PCI_DEVICE_ID_AMD_KERNCZ_SMBUS: + piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_KERNCZ; + piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK_KERNCZ; + piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT_KERNCZ; + break; + case PCI_DEVICE_ID_AMD_HUDSON2_SMBUS: + default: + piix4_port_sel_sb800 = SB800_PIIX4_PORT_IDX_ALT; + piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; + piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; + break; + } } else { mutex_lock(&piix4_mutex_sb800); outb_p(SB800_PIIX4_PORT_IDX_SEL, SB800_PIIX4_SMB_IDX); @@ -355,6 +379,8 @@ static int piix4_setup_sb800(struct pci_dev *PIIX4_dev, piix4_port_sel_sb800 = (port_sel & 0x01) ? SB800_PIIX4_PORT_IDX_ALT : SB800_PIIX4_PORT_IDX; + piix4_port_mask_sb800 = SB800_PIIX4_PORT_IDX_MASK; + piix4_port_shift_sb800 = SB800_PIIX4_PORT_IDX_SHIFT; mutex_unlock(&piix4_mutex_sb800); } @@ -572,6 +598,67 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr, return 0; } +static uint8_t piix4_imc_read(uint8_t idx) +{ + outb_p(idx, KERNCZ_IMC_IDX); + return inb_p(KERNCZ_IMC_DATA); +} + +static void piix4_imc_write(uint8_t idx, uint8_t value) +{ + outb_p(idx, KERNCZ_IMC_IDX); + outb_p(value, KERNCZ_IMC_DATA); +} + +static int piix4_imc_sleep(void) +{ + int timeout = MAX_TIMEOUT; + + if (!request_muxed_region(KERNCZ_IMC_IDX, 2, "smbus_kerncz_imc")) + return -EBUSY; + + /* clear response register */ + piix4_imc_write(0x82, 0x00); + /* request ownership flag */ + piix4_imc_write(0x83, 0xB4); + /* kick off IMC Mailbox command 96 */ + piix4_imc_write(0x80, 0x96); + + while (timeout--) { + if (piix4_imc_read(0x82) == 0xfa) { + release_region(KERNCZ_IMC_IDX, 2); + return 0; + } + usleep_range(1000, 2000); + } + + release_region(KERNCZ_IMC_IDX, 2); + return -ETIMEDOUT; +} + +static void piix4_imc_wakeup(void) +{ + int timeout = MAX_TIMEOUT; + + if (!request_muxed_region(KERNCZ_IMC_IDX, 2, "smbus_kerncz_imc")) + return; + + /* clear response register */ + piix4_imc_write(0x82, 0x00); + /* release ownership flag */ + piix4_imc_write(0x83, 0xB5); + /* kick off IMC Mailbox command 96 */ + piix4_imc_write(0x80, 0x96); + + while (timeout--) { + if (piix4_imc_read(0x82) == 0xfa) + break; + usleep_range(1000, 2000); + } + + release_region(KERNCZ_IMC_IDX, 2); +} + /* * Handles access to multiple SMBus ports on the SB800. * The port is selected by bits 2:1 of the smb_en register (0x2c). @@ -612,12 +699,47 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, return -EBUSY; } + /* + * Notify the IMC (Integrated Micro Controller) if required. + * Among other responsibilities, the IMC is in charge of monitoring + * the System fans and temperature sensors, and act accordingly. + * All this is done through SMBus and can/will collide + * with our transactions if they are long (BLOCK_DATA). + * Therefore we need to request the ownership flag during those + * transactions. + */ + if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) { + int ret; + + ret = piix4_imc_sleep(); + switch (ret) { + case -EBUSY: + dev_warn(&adap->dev, + "IMC base address index region 0x%x already in use.\n", + KERNCZ_IMC_IDX); + break; + case -ETIMEDOUT: + dev_warn(&adap->dev, + "Failed to communicate with the IMC.\n"); + break; + default: + break; + } + + /* If IMC communication fails do not retry */ + if (ret) { + dev_warn(&adap->dev, + "Continuing without IMC notification.\n"); + adapdata->notify_imc = false; + } + } + outb_p(piix4_port_sel_sb800, SB800_PIIX4_SMB_IDX); smba_en_lo = inb_p(SB800_PIIX4_SMB_IDX + 1); port = adapdata->port; - if ((smba_en_lo & SB800_PIIX4_PORT_IDX_MASK) != port) - outb_p((smba_en_lo & ~SB800_PIIX4_PORT_IDX_MASK) | port, + if ((smba_en_lo & piix4_port_mask_sb800) != port) + outb_p((smba_en_lo & ~piix4_port_mask_sb800) | port, SB800_PIIX4_SMB_IDX + 1); retval = piix4_access(adap, addr, flags, read_write, @@ -628,6 +750,9 @@ static s32 piix4_access_sb800(struct i2c_adapter *adap, u16 addr, /* Release the semaphore */ outb_p(smbslvcnt | 0x20, SMBSLVCNT); + if ((size == I2C_SMBUS_BLOCK_DATA) && adapdata->notify_imc) + piix4_imc_wakeup(); + mutex_unlock(&piix4_mutex_sb800); return retval; @@ -679,7 +804,7 @@ static struct i2c_adapter *piix4_main_adapters[PIIX4_MAX_ADAPTERS]; static struct i2c_adapter *piix4_aux_adapter; static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, - bool sb800_main, u8 port, + bool sb800_main, u8 port, bool notify_imc, const char *name, struct i2c_adapter **padap) { struct i2c_adapter *adap; @@ -706,7 +831,8 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, adapdata->smba = smba; adapdata->sb800_main = sb800_main; - adapdata->port = port << 1; + adapdata->port = port << piix4_port_shift_sb800; + adapdata->notify_imc = notify_imc; /* set up the sysfs linkage to our parent device */ adap->dev.parent = &dev->dev; @@ -728,14 +854,15 @@ static int piix4_add_adapter(struct pci_dev *dev, unsigned short smba, return 0; } -static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba) +static int piix4_add_adapters_sb800(struct pci_dev *dev, unsigned short smba, + bool notify_imc) { struct i2c_piix4_adapdata *adapdata; int port; int retval; for (port = 0; port < PIIX4_MAX_ADAPTERS; port++) { - retval = piix4_add_adapter(dev, smba, true, port, + retval = piix4_add_adapter(dev, smba, true, port, notify_imc, piix4_main_port_names_sb800[port], &piix4_main_adapters[port]); if (retval < 0) @@ -769,6 +896,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && dev->revision >= 0x40) || dev->vendor == PCI_VENDOR_ID_AMD) { + bool notify_imc = false; is_sb800 = true; if (!request_region(SB800_PIIX4_SMB_IDX, 2, "smba_idx")) { @@ -778,6 +906,20 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) return -EBUSY; } + if (dev->vendor == PCI_VENDOR_ID_AMD && + dev->device == PCI_DEVICE_ID_AMD_KERNCZ_SMBUS) { + u8 imc; + + /* + * Detect if IMC is active or not, this method is + * described on coreboot's AMD IMC notes + */ + pci_bus_read_config_byte(dev->bus, PCI_DEVFN(0x14, 3), + 0x40, &imc); + if (imc & 0x80) + notify_imc = true; + } + /* base address location etc changed in SB800 */ retval = piix4_setup_sb800(dev, id, 0); if (retval < 0) { @@ -789,7 +931,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) * Try to register multiplexed main SMBus adapter, * give up if we can't */ - retval = piix4_add_adapters_sb800(dev, retval); + retval = piix4_add_adapters_sb800(dev, retval, notify_imc); if (retval < 0) { release_region(SB800_PIIX4_SMB_IDX, 2); return retval; @@ -800,7 +942,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) return retval; /* Try to register main SMBus adapter, give up if we can't */ - retval = piix4_add_adapter(dev, retval, false, 0, "", + retval = piix4_add_adapter(dev, retval, false, 0, false, "", &piix4_main_adapters[0]); if (retval < 0) return retval; @@ -827,7 +969,7 @@ static int piix4_probe(struct pci_dev *dev, const struct pci_device_id *id) if (retval > 0) { /* Try to add the aux adapter if it exists, * piix4_add_adapter will clean up if this fails */ - piix4_add_adapter(dev, retval, false, 0, + piix4_add_adapter(dev, retval, false, 0, false, is_sb800 ? piix4_aux_port_name_sb800 : "", &piix4_aux_adapter); } diff --git a/drivers/i2c/busses/i2c-sprd.c b/drivers/i2c/busses/i2c-sprd.c index 22e08ae1704f..25fcc3c1e32b 100644 --- a/drivers/i2c/busses/i2c-sprd.c +++ b/drivers/i2c/busses/i2c-sprd.c @@ -627,6 +627,7 @@ static const struct dev_pm_ops sprd_i2c_pm_ops = { static const struct of_device_id sprd_i2c_of_match[] = { { .compatible = "sprd,sc9860-i2c", }, + {}, }; static struct platform_driver sprd_i2c_driver = { diff --git a/drivers/i2c/busses/i2c-stm32f7.c b/drivers/i2c/busses/i2c-stm32f7.c index 47c67b0ca896..d4a6e9c2e9aa 100644 --- a/drivers/i2c/busses/i2c-stm32f7.c +++ b/drivers/i2c/busses/i2c-stm32f7.c @@ -215,7 +215,7 @@ struct stm32f7_i2c_dev { unsigned int msg_num; unsigned int msg_id; struct stm32f7_i2c_msg f7_msg; - struct stm32f7_i2c_setup *setup; + struct stm32f7_i2c_setup setup; struct stm32f7_i2c_timings timing; }; @@ -265,7 +265,7 @@ static struct stm32f7_i2c_spec i2c_specs[] = { }, }; -struct stm32f7_i2c_setup stm32f7_setup = { +static const struct stm32f7_i2c_setup stm32f7_setup = { .rise_time = STM32F7_I2C_RISE_TIME_DEFAULT, .fall_time = STM32F7_I2C_FALL_TIME_DEFAULT, .dnf = STM32F7_I2C_DNF_DEFAULT, @@ -537,7 +537,7 @@ static void stm32f7_i2c_hw_config(struct stm32f7_i2c_dev *i2c_dev) writel_relaxed(timing, i2c_dev->base + STM32F7_I2C_TIMINGR); /* Enable I2C */ - if (i2c_dev->setup->analog_filter) + if (i2c_dev->setup.analog_filter) stm32f7_i2c_clr_bits(i2c_dev->base + STM32F7_I2C_CR1, STM32F7_I2C_CR1_ANFOFF); else @@ -887,22 +887,19 @@ static int stm32f7_i2c_probe(struct platform_device *pdev) } setup = of_device_get_match_data(&pdev->dev); - i2c_dev->setup->rise_time = setup->rise_time; - i2c_dev->setup->fall_time = setup->fall_time; - i2c_dev->setup->dnf = setup->dnf; - i2c_dev->setup->analog_filter = setup->analog_filter; + i2c_dev->setup = *setup; ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-rising-time-ns", &rise_time); if (!ret) - i2c_dev->setup->rise_time = rise_time; + i2c_dev->setup.rise_time = rise_time; ret = device_property_read_u32(i2c_dev->dev, "i2c-scl-falling-time-ns", &fall_time); if (!ret) - i2c_dev->setup->fall_time = fall_time; + i2c_dev->setup.fall_time = fall_time; - ret = stm32f7_i2c_setup_timing(i2c_dev, i2c_dev->setup); + ret = stm32f7_i2c_setup_timing(i2c_dev, &i2c_dev->setup); if (ret) goto clk_free; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 01b2adfd8226..eaf39e5db08b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1451,6 +1451,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, if (hwif_init(hwif) == 0) { printk(KERN_INFO "%s: failed to initialize IDE " "interface\n", hwif->name); + device_unregister(hwif->portdev); device_unregister(&hwif->gendev); ide_disable_port(hwif); continue; diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c index 86aa88aeb3a6..acf874800ca4 100644 --- a/drivers/ide/ide-scan-pci.c +++ b/drivers/ide/ide-scan-pci.c @@ -56,6 +56,7 @@ static int __init ide_scan_pcidev(struct pci_dev *dev) { struct list_head *l; struct pci_driver *d; + int ret; list_for_each(l, &ide_pci_drivers) { d = list_entry(l, struct pci_driver, node); @@ -63,10 +64,14 @@ static int __init ide_scan_pcidev(struct pci_dev *dev) const struct pci_device_id *id = pci_match_id(d->id_table, dev); - if (id != NULL && d->probe(dev, id) >= 0) { - dev->driver = d; - pci_dev_get(dev); - return 1; + if (id != NULL) { + pci_assign_irq(dev); + ret = d->probe(dev, id); + if (ret >= 0) { + dev->driver = d; + pci_dev_get(dev); + return 1; + } } } } diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 112d2fe1bcdb..fdc8e813170c 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -179,6 +179,7 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); /** * ide_pci_enable - do PCI enables * @dev: PCI device + * @bars: PCI BARs mask * @d: IDE port info * * Enable the IDE PCI device. We attempt to enable the device in full @@ -189,9 +190,10 @@ EXPORT_SYMBOL_GPL(ide_setup_pci_noise); * Returns zero on success or an error code */ -static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) +static int ide_pci_enable(struct pci_dev *dev, int bars, + const struct ide_port_info *d) { - int ret, bars; + int ret; if (pci_enable_device(dev)) { ret = pci_enable_device_io(dev); @@ -216,18 +218,6 @@ static int ide_pci_enable(struct pci_dev *dev, const struct ide_port_info *d) goto out; } - if (d->host_flags & IDE_HFLAG_SINGLE) - bars = (1 << 2) - 1; - else - bars = (1 << 4) - 1; - - if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { - if (d->host_flags & IDE_HFLAG_CS5520) - bars |= (1 << 2); - else - bars |= (1 << 4); - } - ret = pci_request_selected_regions(dev, bars, d->name); if (ret < 0) printk(KERN_ERR "%s %s: can't reserve resources\n", @@ -403,6 +393,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) /** * ide_setup_pci_controller - set up IDE PCI * @dev: PCI device + * @bars: PCI BARs mask * @d: IDE port info * @noisy: verbose flag * @@ -411,7 +402,7 @@ int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) * and enables it if need be */ -static int ide_setup_pci_controller(struct pci_dev *dev, +static int ide_setup_pci_controller(struct pci_dev *dev, int bars, const struct ide_port_info *d, int noisy) { int ret; @@ -420,7 +411,7 @@ static int ide_setup_pci_controller(struct pci_dev *dev, if (noisy) ide_setup_pci_noise(dev, d); - ret = ide_pci_enable(dev, d); + ret = ide_pci_enable(dev, bars, d); if (ret < 0) goto out; @@ -428,16 +419,20 @@ static int ide_setup_pci_controller(struct pci_dev *dev, if (ret < 0) { printk(KERN_ERR "%s %s: error accessing PCI regs\n", d->name, pci_name(dev)); - goto out; + goto out_free_bars; } if (!(pcicmd & PCI_COMMAND_IO)) { /* is device disabled? */ ret = ide_pci_configure(dev, d); if (ret < 0) - goto out; + goto out_free_bars; printk(KERN_INFO "%s %s: device enabled (Linux)\n", d->name, pci_name(dev)); } + goto out; + +out_free_bars: + pci_release_selected_regions(dev, bars); out: return ret; } @@ -540,13 +535,28 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, { struct pci_dev *pdev[] = { dev1, dev2 }; struct ide_host *host; - int ret, i, n_ports = dev2 ? 4 : 2; + int ret, i, n_ports = dev2 ? 4 : 2, bars; struct ide_hw hw[4], *hws[] = { NULL, NULL, NULL, NULL }; + if (d->host_flags & IDE_HFLAG_SINGLE) + bars = (1 << 2) - 1; + else + bars = (1 << 4) - 1; + + if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { + if (d->host_flags & IDE_HFLAG_CS5520) + bars |= (1 << 2); + else + bars |= (1 << 4); + } + for (i = 0; i < n_ports / 2; i++) { - ret = ide_setup_pci_controller(pdev[i], d, !i); - if (ret < 0) + ret = ide_setup_pci_controller(pdev[i], bars, d, !i); + if (ret < 0) { + if (i == 1) + pci_release_selected_regions(pdev[0], bars); goto out; + } ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); } @@ -554,7 +564,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, host = ide_host_alloc(d, hws, n_ports); if (host == NULL) { ret = -ENOMEM; - goto out; + goto out_free_bars; } host->dev[0] = &dev1->dev; @@ -576,7 +586,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, * do_ide_setup_pci_device() on the first device! */ if (ret < 0) - goto out; + goto out_free_bars; /* fixup IRQ */ if (ide_pci_is_in_compatibility_mode(pdev[i])) { @@ -589,6 +599,13 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, ret = ide_host_register(host, d, hws); if (ret) ide_host_free(host); + else + goto out; + +out_free_bars: + i = n_ports / 2; + while (i--) + pci_release_selected_regions(pdev[i], bars); out: return ret; } diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig index 57625653fcb6..1d13bf03c758 100644 --- a/drivers/iio/adc/Kconfig +++ b/drivers/iio/adc/Kconfig @@ -243,6 +243,8 @@ config DA9150_GPADC config DLN2_ADC tristate "Diolan DLN-2 ADC driver support" depends on MFD_DLN2 + select IIO_BUFFER + select IIO_TRIGGERED_BUFFER help Say yes here to build support for Diolan DLN-2 ADC. diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c index e6706a09e100..47c3d7f32900 100644 --- a/drivers/iio/adc/ad7793.c +++ b/drivers/iio/adc/ad7793.c @@ -257,7 +257,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, unsigned int vref_mv) { struct ad7793_state *st = iio_priv(indio_dev); - int i, ret = -1; + int i, ret; unsigned long long scale_uv; u32 id; @@ -266,7 +266,7 @@ static int ad7793_setup(struct iio_dev *indio_dev, return ret; /* reset the serial interface */ - ret = spi_write(st->sd.spi, (u8 *)&ret, sizeof(ret)); + ret = ad_sd_reset(&st->sd, 32); if (ret < 0) goto out; usleep_range(500, 2000); /* Wait for at least 500us */ diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c index d10bd0c97233..22c4c17cd996 100644 --- a/drivers/iio/adc/ad_sigma_delta.c +++ b/drivers/iio/adc/ad_sigma_delta.c @@ -177,6 +177,34 @@ out: } EXPORT_SYMBOL_GPL(ad_sd_read_reg); +/** + * ad_sd_reset() - Reset the serial interface + * + * @sigma_delta: The sigma delta device + * @reset_length: Number of SCLKs with DIN = 1 + * + * Returns 0 on success, an error code otherwise. + **/ +int ad_sd_reset(struct ad_sigma_delta *sigma_delta, + unsigned int reset_length) +{ + uint8_t *buf; + unsigned int size; + int ret; + + size = DIV_ROUND_UP(reset_length, 8); + buf = kcalloc(size, sizeof(*buf), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + memset(buf, 0xff, size); + ret = spi_write(sigma_delta->spi, buf, size); + kfree(buf); + + return ret; +} +EXPORT_SYMBOL_GPL(ad_sd_reset); + static int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta, unsigned int mode, unsigned int channel) { diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c index bc5b38e3a147..a70ef7fec95f 100644 --- a/drivers/iio/adc/at91-sama5d2_adc.c +++ b/drivers/iio/adc/at91-sama5d2_adc.c @@ -225,6 +225,7 @@ struct at91_adc_trigger { char *name; unsigned int trgmod_value; unsigned int edge_type; + bool hw_trig; }; struct at91_adc_state { @@ -254,16 +255,25 @@ static const struct at91_adc_trigger at91_adc_trigger_list[] = { .name = "external_rising", .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_RISE, .edge_type = IRQ_TYPE_EDGE_RISING, + .hw_trig = true, }, { .name = "external_falling", .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_FALL, .edge_type = IRQ_TYPE_EDGE_FALLING, + .hw_trig = true, }, { .name = "external_any", .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_EXT_TRIG_ANY, .edge_type = IRQ_TYPE_EDGE_BOTH, + .hw_trig = true, + }, + { + .name = "software", + .trgmod_value = AT91_SAMA5D2_TRGR_TRGMOD_NO_TRIGGER, + .edge_type = IRQ_TYPE_NONE, + .hw_trig = false, }, }; @@ -597,7 +607,7 @@ static int at91_adc_probe(struct platform_device *pdev) struct at91_adc_state *st; struct resource *res; int ret, i; - u32 edge_type; + u32 edge_type = IRQ_TYPE_NONE; indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st)); if (!indio_dev) @@ -641,14 +651,14 @@ static int at91_adc_probe(struct platform_device *pdev) ret = of_property_read_u32(pdev->dev.of_node, "atmel,trigger-edge-type", &edge_type); if (ret) { - dev_err(&pdev->dev, - "invalid or missing value for atmel,trigger-edge-type\n"); - return ret; + dev_dbg(&pdev->dev, + "atmel,trigger-edge-type not specified, only software trigger available\n"); } st->selected_trig = NULL; - for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT; i++) + /* find the right trigger, or no trigger at all */ + for (i = 0; i < AT91_SAMA5D2_HW_TRIG_CNT + 1; i++) if (at91_adc_trigger_list[i].edge_type == edge_type) { st->selected_trig = &at91_adc_trigger_list[i]; break; @@ -717,24 +727,27 @@ static int at91_adc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, indio_dev); - ret = at91_adc_buffer_init(indio_dev); - if (ret < 0) { - dev_err(&pdev->dev, "couldn't initialize the buffer.\n"); - goto per_clk_disable_unprepare; - } + if (st->selected_trig->hw_trig) { + ret = at91_adc_buffer_init(indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "couldn't initialize the buffer.\n"); + goto per_clk_disable_unprepare; + } - ret = at91_adc_trigger_init(indio_dev); - if (ret < 0) { - dev_err(&pdev->dev, "couldn't setup the triggers.\n"); - goto per_clk_disable_unprepare; + ret = at91_adc_trigger_init(indio_dev); + if (ret < 0) { + dev_err(&pdev->dev, "couldn't setup the triggers.\n"); + goto per_clk_disable_unprepare; + } } ret = iio_device_register(indio_dev); if (ret < 0) goto per_clk_disable_unprepare; - dev_info(&pdev->dev, "setting up trigger as %s\n", - st->selected_trig->name); + if (st->selected_trig->hw_trig) + dev_info(&pdev->dev, "setting up trigger as %s\n", + st->selected_trig->name); dev_info(&pdev->dev, "version: %x\n", readl_relaxed(st->base + AT91_SAMA5D2_VERSION)); diff --git a/drivers/iio/adc/mcp320x.c b/drivers/iio/adc/mcp320x.c index 634717ae12f3..071dd23a33d9 100644 --- a/drivers/iio/adc/mcp320x.c +++ b/drivers/iio/adc/mcp320x.c @@ -17,6 +17,8 @@ * MCP3204 * MCP3208 * ------------ + * 13 bit converter + * MCP3301 * * Datasheet can be found here: * http://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf mcp3001 @@ -96,7 +98,7 @@ static int mcp320x_channel_to_tx_data(int device_index, } static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, - bool differential, int device_index) + bool differential, int device_index, int *val) { int ret; @@ -117,19 +119,25 @@ static int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel, switch (device_index) { case mcp3001: - return (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); + *val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3); + return 0; case mcp3002: case mcp3004: case mcp3008: - return (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); + *val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6); + return 0; case mcp3201: - return (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); + *val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1); + return 0; case mcp3202: case mcp3204: case mcp3208: - return (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); + *val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4); + return 0; case mcp3301: - return sign_extend32((adc->rx_buf[0] & 0x1f) << 8 | adc->rx_buf[1], 12); + *val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8 + | adc->rx_buf[1], 12); + return 0; default: return -EINVAL; } @@ -150,12 +158,10 @@ static int mcp320x_read_raw(struct iio_dev *indio_dev, switch (mask) { case IIO_CHAN_INFO_RAW: ret = mcp320x_adc_conversion(adc, channel->address, - channel->differential, device_index); - + channel->differential, device_index, val); if (ret < 0) goto out; - *val = ret; ret = IIO_VAL_INT; break; @@ -312,6 +318,7 @@ static int mcp320x_probe(struct spi_device *spi) indio_dev->name = spi_get_device_id(spi)->name; indio_dev->modes = INDIO_DIRECT_MODE; indio_dev->info = &mcp320x_info; + spi_set_drvdata(spi, indio_dev); chip_info = &mcp320x_chip_infos[spi_get_device_id(spi)->driver_data]; indio_dev->channels = chip_info->channels; diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c index e3c15f88075f..4df32cf1650e 100644 --- a/drivers/iio/adc/stm32-adc.c +++ b/drivers/iio/adc/stm32-adc.c @@ -1666,7 +1666,7 @@ static int stm32_adc_chan_of_init(struct iio_dev *indio_dev) num_channels = of_property_count_u32_elems(node, "st,adc-channels"); if (num_channels < 0 || - num_channels >= adc_info->max_channels) { + num_channels > adc_info->max_channels) { dev_err(&indio_dev->dev, "Bad st,adc-channels?\n"); return num_channels < 0 ? num_channels : -EINVAL; } diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c index d1210024f6bc..e0dc20488335 100644 --- a/drivers/iio/adc/ti-ads1015.c +++ b/drivers/iio/adc/ti-ads1015.c @@ -52,7 +52,7 @@ #define ADS1015_CFG_COMP_QUE_MASK GENMASK(1, 0) #define ADS1015_CFG_COMP_LAT_MASK BIT(2) -#define ADS1015_CFG_COMP_POL_MASK BIT(2) +#define ADS1015_CFG_COMP_POL_MASK BIT(3) #define ADS1015_CFG_COMP_MODE_MASK BIT(4) #define ADS1015_CFG_DR_MASK GENMASK(7, 5) #define ADS1015_CFG_MOD_MASK BIT(8) @@ -1017,10 +1017,12 @@ static int ads1015_probe(struct i2c_client *client, switch (irq_trig) { case IRQF_TRIGGER_LOW: - cfg_comp |= ADS1015_CFG_COMP_POL_LOW; + cfg_comp |= ADS1015_CFG_COMP_POL_LOW << + ADS1015_CFG_COMP_POL_SHIFT; break; case IRQF_TRIGGER_HIGH: - cfg_comp |= ADS1015_CFG_COMP_POL_HIGH; + cfg_comp |= ADS1015_CFG_COMP_POL_HIGH << + ADS1015_CFG_COMP_POL_SHIFT; break; default: return -EINVAL; diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c index 1edd99f0c5e5..e3cfb91bffc6 100644 --- a/drivers/iio/adc/twl4030-madc.c +++ b/drivers/iio/adc/twl4030-madc.c @@ -887,21 +887,27 @@ static int twl4030_madc_probe(struct platform_device *pdev) /* Enable 3v1 bias regulator for MADC[3:6] */ madc->usb3v1 = devm_regulator_get(madc->dev, "vusb3v1"); - if (IS_ERR(madc->usb3v1)) - return -ENODEV; + if (IS_ERR(madc->usb3v1)) { + ret = -ENODEV; + goto err_i2c; + } ret = regulator_enable(madc->usb3v1); - if (ret) + if (ret) { dev_err(madc->dev, "could not enable 3v1 bias regulator\n"); + goto err_i2c; + } ret = iio_device_register(iio_dev); if (ret) { dev_err(&pdev->dev, "could not register iio device\n"); - goto err_i2c; + goto err_usb3v1; } return 0; +err_usb3v1: + regulator_disable(madc->usb3v1); err_i2c: twl4030_madc_set_current_generator(madc, 0, 0); err_current_generator: diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index d99bb1460fe2..02e833b14db0 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c @@ -463,8 +463,17 @@ int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable) u8 drdy_mask; struct st_sensor_data *sdata = iio_priv(indio_dev); - if (!sdata->sensor_settings->drdy_irq.addr) + if (!sdata->sensor_settings->drdy_irq.addr) { + /* + * there are some devices (e.g. LIS3MDL) where drdy line is + * routed to a given pin and it is not possible to select a + * different one. Take into account irq status register + * to understand if irq trigger can be properly supported + */ + if (sdata->sensor_settings->drdy_irq.addr_stat_drdy) + sdata->hw_irq_trigger = enable; return 0; + } /* Enable/Disable the interrupt generator 1. */ if (sdata->sensor_settings->drdy_irq.ig1.en_addr > 0) { diff --git a/drivers/iio/dummy/iio_simple_dummy_events.c b/drivers/iio/dummy/iio_simple_dummy_events.c index ed63ffd849f8..7ec2a0bb0807 100644 --- a/drivers/iio/dummy/iio_simple_dummy_events.c +++ b/drivers/iio/dummy/iio_simple_dummy_events.c @@ -72,6 +72,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev, st->event_en = state; else return -EINVAL; + break; default: return -EINVAL; } diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 17ec4cee51dc..a47428b4d31b 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -310,8 +310,10 @@ static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, ret = indio_dev->info->debugfs_reg_access(indio_dev, indio_dev->cached_reg_addr, 0, &val); - if (ret) + if (ret) { dev_err(indio_dev->dev.parent, "%s: read failed\n", __func__); + return ret; + } len = snprintf(buf, sizeof(buf), "0x%X\n", val); diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c index e68368b5b2a3..08aafba4481c 100644 --- a/drivers/iio/magnetometer/st_magn_core.c +++ b/drivers/iio/magnetometer/st_magn_core.c @@ -315,6 +315,10 @@ static const struct st_sensor_settings st_magn_sensors_settings[] = { }, }, }, + .drdy_irq = { + /* drdy line is routed drdy pin */ + .addr_stat_drdy = ST_SENSORS_DEFAULT_STAT_ADDR, + }, .multi_read_bit = true, .bootime = 2, }, diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c index 0d2ea3ee371b..8f26428804a2 100644 --- a/drivers/iio/pressure/bmp280-core.c +++ b/drivers/iio/pressure/bmp280-core.c @@ -573,7 +573,7 @@ static int bmp280_chip_config(struct bmp280_data *data) u8 osrs = BMP280_OSRS_TEMP_X(data->oversampling_temp + 1) | BMP280_OSRS_PRESS_X(data->oversampling_press + 1); - ret = regmap_update_bits(data->regmap, BMP280_REG_CTRL_MEAS, + ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS, BMP280_OSRS_TEMP_MASK | BMP280_OSRS_PRESS_MASK | BMP280_MODE_MASK, diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c index ebfb1de7377f..91431454eb85 100644 --- a/drivers/iio/pressure/zpa2326.c +++ b/drivers/iio/pressure/zpa2326.c @@ -865,7 +865,6 @@ complete: static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, struct zpa2326_private *private) { - int ret; unsigned int val; long timeout; @@ -887,14 +886,11 @@ static int zpa2326_wait_oneshot_completion(const struct iio_dev *indio_dev, /* Timed out. */ zpa2326_warn(indio_dev, "no one shot interrupt occurred (%ld)", timeout); - ret = -ETIME; - } else if (timeout < 0) { - zpa2326_warn(indio_dev, - "wait for one shot interrupt cancelled"); - ret = -ERESTARTSYS; + return -ETIME; } - return ret; + zpa2326_warn(indio_dev, "wait for one shot interrupt cancelled"); + return -ERESTARTSYS; } static int zpa2326_init_managed_irq(struct device *parent, diff --git a/drivers/iio/proximity/as3935.c b/drivers/iio/proximity/as3935.c index 0eeff29b61be..4a48b7ba3a1c 100644 --- a/drivers/iio/proximity/as3935.c +++ b/drivers/iio/proximity/as3935.c @@ -39,8 +39,12 @@ #define AS3935_AFE_GAIN_MAX 0x1F #define AS3935_AFE_PWR_BIT BIT(0) +#define AS3935_NFLWDTH 0x01 +#define AS3935_NFLWDTH_MASK 0x7f + #define AS3935_INT 0x03 #define AS3935_INT_MASK 0x0f +#define AS3935_DISTURB_INT BIT(2) #define AS3935_EVENT_INT BIT(3) #define AS3935_NOISE_INT BIT(0) @@ -48,6 +52,7 @@ #define AS3935_DATA_MASK 0x3F #define AS3935_TUNE_CAP 0x08 +#define AS3935_DEFAULTS 0x3C #define AS3935_CALIBRATE 0x3D #define AS3935_READ_DATA BIT(14) @@ -62,7 +67,9 @@ struct as3935_state { struct mutex lock; struct delayed_work work; + unsigned long noise_tripped; u32 tune_cap; + u32 nflwdth_reg; u8 buffer[16]; /* 8-bit data + 56-bit padding + 64-bit timestamp */ u8 buf[2] ____cacheline_aligned; }; @@ -145,12 +152,29 @@ static ssize_t as3935_sensor_sensitivity_store(struct device *dev, return len; } +static ssize_t as3935_noise_level_tripped_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct as3935_state *st = iio_priv(dev_to_iio_dev(dev)); + int ret; + + mutex_lock(&st->lock); + ret = sprintf(buf, "%d\n", !time_after(jiffies, st->noise_tripped + HZ)); + mutex_unlock(&st->lock); + + return ret; +} + static IIO_DEVICE_ATTR(sensor_sensitivity, S_IRUGO | S_IWUSR, as3935_sensor_sensitivity_show, as3935_sensor_sensitivity_store, 0); +static IIO_DEVICE_ATTR(noise_level_tripped, S_IRUGO, + as3935_noise_level_tripped_show, NULL, 0); static struct attribute *as3935_attributes[] = { &iio_dev_attr_sensor_sensitivity.dev_attr.attr, + &iio_dev_attr_noise_level_tripped.dev_attr.attr, NULL, }; @@ -246,7 +270,11 @@ static void as3935_event_work(struct work_struct *work) case AS3935_EVENT_INT: iio_trigger_poll_chained(st->trig); break; + case AS3935_DISTURB_INT: case AS3935_NOISE_INT: + mutex_lock(&st->lock); + st->noise_tripped = jiffies; + mutex_unlock(&st->lock); dev_warn(&st->spi->dev, "noise level is too high\n"); break; } @@ -269,15 +297,14 @@ static irqreturn_t as3935_interrupt_handler(int irq, void *private) static void calibrate_as3935(struct as3935_state *st) { - /* mask disturber interrupt bit */ - as3935_write(st, AS3935_INT, BIT(5)); - + as3935_write(st, AS3935_DEFAULTS, 0x96); as3935_write(st, AS3935_CALIBRATE, 0x96); as3935_write(st, AS3935_TUNE_CAP, BIT(5) | (st->tune_cap / TUNE_CAP_DIV)); mdelay(2); as3935_write(st, AS3935_TUNE_CAP, (st->tune_cap / TUNE_CAP_DIV)); + as3935_write(st, AS3935_NFLWDTH, st->nflwdth_reg); } #ifdef CONFIG_PM_SLEEP @@ -370,6 +397,15 @@ static int as3935_probe(struct spi_device *spi) return -EINVAL; } + ret = of_property_read_u32(np, + "ams,nflwdth", &st->nflwdth_reg); + if (!ret && st->nflwdth_reg > AS3935_NFLWDTH_MASK) { + dev_err(&spi->dev, + "invalid nflwdth setting of %d\n", + st->nflwdth_reg); + return -EINVAL; + } + indio_dev->dev.parent = &spi->dev; indio_dev->name = spi_get_device_id(spi)->name; indio_dev->channels = as3935_channels; @@ -384,6 +420,7 @@ static int as3935_probe(struct spi_device *spi) return -ENOMEM; st->trig = trig; + st->noise_tripped = jiffies - HZ; trig->dev.parent = indio_dev->dev.parent; iio_trigger_set_drvdata(trig, indio_dev); trig->ops = &iio_interrupt_trigger_ops; diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c index 9b9053494daf..eb212f8c8879 100644 --- a/drivers/iio/trigger/stm32-timer-trigger.c +++ b/drivers/iio/trigger/stm32-timer-trigger.c @@ -174,6 +174,7 @@ static void stm32_timer_stop(struct stm32_timer_trigger *priv) clk_disable(priv->clk); /* Stop timer */ + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN, 0); regmap_write(priv->regmap, TIM_PSC, 0); regmap_write(priv->regmap, TIM_ARR, 0); @@ -715,8 +716,9 @@ static ssize_t stm32_count_set_preset(struct iio_dev *indio_dev, if (ret) return ret; + /* TIMx_ARR register shouldn't be buffered (ARPE=0) */ + regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, 0); regmap_write(priv->regmap, TIM_ARR, preset); - regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_ARPE, TIM_CR1_ARPE); return len; } diff --git a/drivers/infiniband/core/iwpm_msg.c b/drivers/infiniband/core/iwpm_msg.c index 30825bb9b8e9..8861c052155a 100644 --- a/drivers/infiniband/core/iwpm_msg.c +++ b/drivers/infiniband/core/iwpm_msg.c @@ -100,6 +100,8 @@ int iwpm_register_pid(struct iwpm_dev_data *pm_msg, u8 nl_client) if (ret) goto pid_query_error; + nlmsg_end(skb, nlh); + pr_debug("%s: Multicasting a nlmsg (dev = %s ifname = %s iwpm = %s)\n", __func__, pm_msg->dev_name, pm_msg->if_name, iwpm_ulib_name); @@ -170,6 +172,8 @@ int iwpm_add_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client) &pm_msg->loc_addr, IWPM_NLA_MANAGE_ADDR); if (ret) goto add_mapping_error; + + nlmsg_end(skb, nlh); nlmsg_request->req_buffer = pm_msg; ret = rdma_nl_unicast_wait(skb, iwpm_user_pid); @@ -246,6 +250,8 @@ int iwpm_add_and_query_mapping(struct iwpm_sa_data *pm_msg, u8 nl_client) &pm_msg->rem_addr, IWPM_NLA_QUERY_REMOTE_ADDR); if (ret) goto query_mapping_error; + + nlmsg_end(skb, nlh); nlmsg_request->req_buffer = pm_msg; ret = rdma_nl_unicast_wait(skb, iwpm_user_pid); @@ -308,6 +314,8 @@ int iwpm_remove_mapping(struct sockaddr_storage *local_addr, u8 nl_client) if (ret) goto remove_mapping_error; + nlmsg_end(skb, nlh); + ret = rdma_nl_unicast_wait(skb, iwpm_user_pid); if (ret) { skb = NULL; /* skb is freed in the netlink send-op handling */ diff --git a/drivers/infiniband/core/iwpm_util.c b/drivers/infiniband/core/iwpm_util.c index c81c55942626..3c4faadb8cdd 100644 --- a/drivers/infiniband/core/iwpm_util.c +++ b/drivers/infiniband/core/iwpm_util.c @@ -597,6 +597,9 @@ static int send_mapinfo_num(u32 mapping_num, u8 nl_client, int iwpm_pid) &mapping_num, IWPM_NLA_MAPINFO_SEND_NUM); if (ret) goto mapinfo_num_error; + + nlmsg_end(skb, nlh); + ret = rdma_nl_unicast(skb, iwpm_pid); if (ret) { skb = NULL; @@ -678,6 +681,8 @@ int iwpm_send_mapinfo(u8 nl_client, int iwpm_pid) if (ret) goto send_mapping_info_unlock; + nlmsg_end(skb, nlh); + iwpm_print_sockaddr(&map_info->local_sockaddr, "send_mapping_info: Local sockaddr:"); iwpm_print_sockaddr(&map_info->mapped_sockaddr, diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c index b12e58787c3d..1fb72c356e36 100644 --- a/drivers/infiniband/core/netlink.c +++ b/drivers/infiniband/core/netlink.c @@ -175,13 +175,24 @@ static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, !netlink_capable(skb, CAP_NET_ADMIN)) return -EPERM; + /* + * LS responses overload the 0x100 (NLM_F_ROOT) flag. Don't + * mistakenly call the .dump() function. + */ + if (index == RDMA_NL_LS) { + if (cb_table[op].doit) + return cb_table[op].doit(skb, nlh, extack); + return -EINVAL; + } /* FIXME: Convert IWCM to properly handle doit callbacks */ if ((nlh->nlmsg_flags & NLM_F_DUMP) || index == RDMA_NL_RDMA_CM || index == RDMA_NL_IWCM) { struct netlink_dump_control c = { .dump = cb_table[op].dump, }; - return netlink_dump_start(nls, skb, nlh, &c); + if (c.dump) + return netlink_dump_start(nls, skb, nlh, &c); + return -EINVAL; } if (cb_table[op].doit) diff --git a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c index d1f5345f04f0..42ca5346777d 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_ctrl.c +++ b/drivers/infiniband/hw/i40iw/i40iw_ctrl.c @@ -48,7 +48,7 @@ * @wqe: cqp wqe for header * @header: header for the cqp wqe */ -static inline void i40iw_insert_wqe_hdr(u64 *wqe, u64 header) +void i40iw_insert_wqe_hdr(u64 *wqe, u64 header) { wmb(); /* make sure WQE is populated before polarity is set */ set_64bit_val(wqe, 24, header); diff --git a/drivers/infiniband/hw/i40iw/i40iw_p.h b/drivers/infiniband/hw/i40iw/i40iw_p.h index e217a1259f57..5498ad01c280 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_p.h +++ b/drivers/infiniband/hw/i40iw/i40iw_p.h @@ -59,6 +59,8 @@ enum i40iw_status_code i40iw_sc_mr_fast_register(struct i40iw_sc_qp *qp, struct i40iw_fast_reg_stag_info *info, bool post_sq); +void i40iw_insert_wqe_hdr(u64 *wqe, u64 header); + /* HMC/FPM functions */ enum i40iw_status_code i40iw_sc_init_iw_hmc(struct i40iw_sc_dev *dev, u8 hmc_fn_id); diff --git a/drivers/infiniband/hw/i40iw/i40iw_puda.c b/drivers/infiniband/hw/i40iw/i40iw_puda.c index c2cab20c4bc5..59f70676f0e0 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_puda.c +++ b/drivers/infiniband/hw/i40iw/i40iw_puda.c @@ -123,12 +123,11 @@ static void i40iw_puda_post_recvbuf(struct i40iw_puda_rsrc *rsrc, u32 wqe_idx, get_64bit_val(wqe, 24, &offset24); offset24 = (offset24) ? 0 : LS_64(1, I40IWQPSQ_VALID); - set_64bit_val(wqe, 24, offset24); set_64bit_val(wqe, 0, buf->mem.pa); set_64bit_val(wqe, 8, LS_64(buf->mem.size, I40IWQPSQ_FRAG_LEN)); - set_64bit_val(wqe, 24, offset24); + i40iw_insert_wqe_hdr(wqe, offset24); } /** @@ -409,9 +408,7 @@ enum i40iw_status_code i40iw_puda_send(struct i40iw_sc_qp *qp, set_64bit_val(wqe, 8, LS_64(info->len, I40IWQPSQ_FRAG_LEN)); set_64bit_val(wqe, 16, header[0]); - /* Ensure all data is written before writing valid bit */ - wmb(); - set_64bit_val(wqe, 24, header[1]); + i40iw_insert_wqe_hdr(wqe, header[1]); i40iw_debug_buf(qp->dev, I40IW_DEBUG_PUDA, "PUDA SEND WQE", wqe, 32); i40iw_qp_post_wr(&qp->qp_uk); @@ -539,7 +536,7 @@ static enum i40iw_status_code i40iw_puda_qp_wqe(struct i40iw_sc_dev *dev, struct LS_64(2, I40IW_CQPSQ_QP_NEXTIWSTATE) | LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID); - set_64bit_val(wqe, 24, header); + i40iw_insert_wqe_hdr(wqe, header); i40iw_debug_buf(cqp->dev, I40IW_DEBUG_PUDA, "PUDA CQE", wqe, 32); i40iw_sc_cqp_post_sq(cqp); @@ -655,7 +652,7 @@ static enum i40iw_status_code i40iw_puda_cq_wqe(struct i40iw_sc_dev *dev, struct LS_64(1, I40IW_CQPSQ_CQ_ENCEQEMASK) | LS_64(1, I40IW_CQPSQ_CQ_CEQIDVALID) | LS_64(cqp->polarity, I40IW_CQPSQ_WQEVALID); - set_64bit_val(wqe, 24, header); + i40iw_insert_wqe_hdr(wqe, header); i40iw_debug_buf(dev, I40IW_DEBUG_PUDA, "PUDA CQE", wqe, I40IW_CQP_WQE_SIZE * 8); diff --git a/drivers/infiniband/hw/i40iw/i40iw_verbs.c b/drivers/infiniband/hw/i40iw/i40iw_verbs.c index 28b3d02d511b..62be0a41ad0b 100644 --- a/drivers/infiniband/hw/i40iw/i40iw_verbs.c +++ b/drivers/infiniband/hw/i40iw/i40iw_verbs.c @@ -826,12 +826,14 @@ static int i40iw_query_qp(struct ib_qp *ibqp, attr->cap.max_inline_data = I40IW_MAX_INLINE_DATA_SIZE; attr->cap.max_send_sge = I40IW_MAX_WQ_FRAGMENT_COUNT; attr->cap.max_recv_sge = I40IW_MAX_WQ_FRAGMENT_COUNT; + attr->port_num = 1; init_attr->event_handler = iwqp->ibqp.event_handler; init_attr->qp_context = iwqp->ibqp.qp_context; init_attr->send_cq = iwqp->ibqp.send_cq; init_attr->recv_cq = iwqp->ibqp.recv_cq; init_attr->srq = iwqp->ibqp.srq; init_attr->cap = attr->cap; + init_attr->port_num = 1; return 0; } diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index d6fbad8f34aa..552f7bd4ecc3 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -4174,9 +4174,9 @@ err_bfreg: err_uar_page: mlx5_put_uars_page(dev->mdev, dev->mdev->priv.uar); -err_cnt: - mlx5_ib_cleanup_cong_debugfs(dev); err_cong: + mlx5_ib_cleanup_cong_debugfs(dev); +err_cnt: if (MLX5_CAP_GEN(dev->mdev, max_qp_cnt)) mlx5_ib_dealloc_counters(dev); diff --git a/drivers/infiniband/hw/qedr/qedr.h b/drivers/infiniband/hw/qedr/qedr.h index b2bb42e2805d..254083b524bd 100644 --- a/drivers/infiniband/hw/qedr/qedr.h +++ b/drivers/infiniband/hw/qedr/qedr.h @@ -387,7 +387,7 @@ struct qedr_qp { u8 wqe_size; u8 smac[ETH_ALEN]; - u16 vlan_id; + u16 vlan; int rc; } *rqe_wr_id; diff --git a/drivers/infiniband/hw/qedr/qedr_cm.c b/drivers/infiniband/hw/qedr/qedr_cm.c index 4689e802b332..ad8965397cf7 100644 --- a/drivers/infiniband/hw/qedr/qedr_cm.c +++ b/drivers/infiniband/hw/qedr/qedr_cm.c @@ -105,7 +105,7 @@ void qedr_ll2_complete_rx_packet(void *cxt, qp->rqe_wr_id[qp->rq.gsi_cons].rc = data->u.data_length_error ? -EINVAL : 0; - qp->rqe_wr_id[qp->rq.gsi_cons].vlan_id = data->vlan; + qp->rqe_wr_id[qp->rq.gsi_cons].vlan = data->vlan; /* note: length stands for data length i.e. GRH is excluded */ qp->rqe_wr_id[qp->rq.gsi_cons].sg_list[0].length = data->length.data_length; @@ -694,6 +694,7 @@ int qedr_gsi_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) struct qedr_cq *cq = get_qedr_cq(ibcq); struct qedr_qp *qp = dev->gsi_qp; unsigned long flags; + u16 vlan_id; int i = 0; spin_lock_irqsave(&cq->cq_lock, flags); @@ -712,9 +713,14 @@ int qedr_gsi_poll_cq(struct ib_cq *ibcq, int num_entries, struct ib_wc *wc) wc[i].wc_flags |= IB_WC_GRH | IB_WC_IP_CSUM_OK; ether_addr_copy(wc[i].smac, qp->rqe_wr_id[qp->rq.cons].smac); wc[i].wc_flags |= IB_WC_WITH_SMAC; - if (qp->rqe_wr_id[qp->rq.cons].vlan_id) { + + vlan_id = qp->rqe_wr_id[qp->rq.cons].vlan & + VLAN_VID_MASK; + if (vlan_id) { wc[i].wc_flags |= IB_WC_WITH_VLAN; - wc[i].vlan_id = qp->rqe_wr_id[qp->rq.cons].vlan_id; + wc[i].vlan_id = vlan_id; + wc[i].sl = (qp->rqe_wr_id[qp->rq.cons].vlan & + VLAN_PRIO_MASK) >> VLAN_PRIO_SHIFT; } qedr_inc_sw_cons(&qp->rq); diff --git a/drivers/input/input.c b/drivers/input/input.c index d268fdc23c64..762bfb9487dc 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -933,58 +933,52 @@ int input_set_keycode(struct input_dev *dev, } EXPORT_SYMBOL(input_set_keycode); +bool input_match_device_id(const struct input_dev *dev, + const struct input_device_id *id) +{ + if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) + if (id->bustype != dev->id.bustype) + return false; + + if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) + if (id->vendor != dev->id.vendor) + return false; + + if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) + if (id->product != dev->id.product) + return false; + + if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) + if (id->version != dev->id.version) + return false; + + if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX) || + !bitmap_subset(id->keybit, dev->keybit, KEY_MAX) || + !bitmap_subset(id->relbit, dev->relbit, REL_MAX) || + !bitmap_subset(id->absbit, dev->absbit, ABS_MAX) || + !bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX) || + !bitmap_subset(id->ledbit, dev->ledbit, LED_MAX) || + !bitmap_subset(id->sndbit, dev->sndbit, SND_MAX) || + !bitmap_subset(id->ffbit, dev->ffbit, FF_MAX) || + !bitmap_subset(id->swbit, dev->swbit, SW_MAX) || + !bitmap_subset(id->propbit, dev->propbit, INPUT_PROP_MAX)) { + return false; + } + + return true; +} +EXPORT_SYMBOL(input_match_device_id); + static const struct input_device_id *input_match_device(struct input_handler *handler, struct input_dev *dev) { const struct input_device_id *id; for (id = handler->id_table; id->flags || id->driver_info; id++) { - - if (id->flags & INPUT_DEVICE_ID_MATCH_BUS) - if (id->bustype != dev->id.bustype) - continue; - - if (id->flags & INPUT_DEVICE_ID_MATCH_VENDOR) - if (id->vendor != dev->id.vendor) - continue; - - if (id->flags & INPUT_DEVICE_ID_MATCH_PRODUCT) - if (id->product != dev->id.product) - continue; - - if (id->flags & INPUT_DEVICE_ID_MATCH_VERSION) - if (id->version != dev->id.version) - continue; - - if (!bitmap_subset(id->evbit, dev->evbit, EV_MAX)) - continue; - - if (!bitmap_subset(id->keybit, dev->keybit, KEY_MAX)) - continue; - - if (!bitmap_subset(id->relbit, dev->relbit, REL_MAX)) - continue; - - if (!bitmap_subset(id->absbit, dev->absbit, ABS_MAX)) - continue; - - if (!bitmap_subset(id->mscbit, dev->mscbit, MSC_MAX)) - continue; - - if (!bitmap_subset(id->ledbit, dev->ledbit, LED_MAX)) - continue; - - if (!bitmap_subset(id->sndbit, dev->sndbit, SND_MAX)) - continue; - - if (!bitmap_subset(id->ffbit, dev->ffbit, FF_MAX)) - continue; - - if (!bitmap_subset(id->swbit, dev->swbit, SW_MAX)) - continue; - - if (!handler->match || handler->match(handler, dev)) + if (input_match_device_id(dev, id) && + (!handler->match || handler->match(handler, dev))) { return id; + } } return NULL; diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 29d677c714d2..7b29a8944039 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c @@ -747,6 +747,68 @@ static void joydev_cleanup(struct joydev *joydev) input_close_device(handle); } +/* + * These codes are copied from from hid-ids.h, unfortunately there is no common + * usb_ids/bt_ids.h header. + */ +#define USB_VENDOR_ID_SONY 0x054c +#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 +#define USB_DEVICE_ID_SONY_PS4_CONTROLLER 0x05c4 +#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_2 0x09cc +#define USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE 0x0ba0 + +#define USB_VENDOR_ID_THQ 0x20d6 +#define USB_DEVICE_ID_THQ_PS3_UDRAW 0xcb17 + +#define ACCEL_DEV(vnd, prd) \ + { \ + .flags = INPUT_DEVICE_ID_MATCH_VENDOR | \ + INPUT_DEVICE_ID_MATCH_PRODUCT | \ + INPUT_DEVICE_ID_MATCH_PROPBIT, \ + .vendor = (vnd), \ + .product = (prd), \ + .propbit = { BIT_MASK(INPUT_PROP_ACCELEROMETER) }, \ + } + +static const struct input_device_id joydev_blacklist[] = { + /* Avoid touchpads and touchscreens */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH) }, + }, + /* Avoid tablets, digitisers and similar devices */ + { + .flags = INPUT_DEVICE_ID_MATCH_EVBIT | + INPUT_DEVICE_ID_MATCH_KEYBIT, + .evbit = { BIT_MASK(EV_KEY) }, + .keybit = { [BIT_WORD(BTN_DIGI)] = BIT_MASK(BTN_DIGI) }, + }, + /* Disable accelerometers on composite devices */ + ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), + ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), + ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_2), + ACCEL_DEV(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER_DONGLE), + ACCEL_DEV(USB_VENDOR_ID_THQ, USB_DEVICE_ID_THQ_PS3_UDRAW), + { /* sentinel */ } +}; + +static bool joydev_dev_is_blacklisted(struct input_dev *dev) +{ + const struct input_device_id *id; + + for (id = joydev_blacklist; id->flags; id++) { + if (input_match_device_id(dev, id)) { + dev_dbg(&dev->dev, + "joydev: blacklisting '%s'\n", dev->name); + return true; + } + } + + return false; +} + static bool joydev_dev_is_absolute_mouse(struct input_dev *dev) { DECLARE_BITMAP(jd_scratch, KEY_CNT); @@ -807,12 +869,8 @@ static bool joydev_dev_is_absolute_mouse(struct input_dev *dev) static bool joydev_match(struct input_handler *handler, struct input_dev *dev) { - /* Avoid touchpads and touchscreens */ - if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_TOUCH, dev->keybit)) - return false; - - /* Avoid tablets, digitisers and similar devices */ - if (test_bit(EV_KEY, dev->evbit) && test_bit(BTN_DIGI, dev->keybit)) + /* Disable blacklisted devices */ + if (joydev_dev_is_blacklisted(dev)) return false; /* Avoid absolute mice */ diff --git a/drivers/input/keyboard/tca8418_keypad.c b/drivers/input/keyboard/tca8418_keypad.c index e37e335e406f..6da607d3b811 100644 --- a/drivers/input/keyboard/tca8418_keypad.c +++ b/drivers/input/keyboard/tca8418_keypad.c @@ -234,14 +234,7 @@ static irqreturn_t tca8418_irq_handler(int irq, void *dev_id) static int tca8418_configure(struct tca8418_keypad *keypad_data, u32 rows, u32 cols) { - int reg, error; - - /* Write config register, if this fails assume device not present */ - error = tca8418_write_byte(keypad_data, REG_CFG, - CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN); - if (error < 0) - return -ENODEV; - + int reg, error = 0; /* Assemble a mask for row and column registers */ reg = ~(~0 << rows); @@ -257,6 +250,12 @@ static int tca8418_configure(struct tca8418_keypad *keypad_data, error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS2, reg >> 8); error |= tca8418_write_byte(keypad_data, REG_DEBOUNCE_DIS3, reg >> 16); + if (error) + return error; + + error = tca8418_write_byte(keypad_data, REG_CFG, + CFG_INT_CFG | CFG_OVR_FLOW_IEN | CFG_KE_IEN); + return error; } @@ -268,6 +267,7 @@ static int tca8418_keypad_probe(struct i2c_client *client, struct input_dev *input; u32 rows = 0, cols = 0; int error, row_shift, max_keys; + u8 reg; /* Check i2c driver capabilities */ if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE)) { @@ -301,10 +301,10 @@ static int tca8418_keypad_probe(struct i2c_client *client, keypad_data->client = client; keypad_data->row_shift = row_shift; - /* Initialize the chip or fail if chip isn't present */ - error = tca8418_configure(keypad_data, rows, cols); - if (error < 0) - return error; + /* Read key lock register, if this fails assume device not present */ + error = tca8418_read_byte(keypad_data, REG_KEY_LCK_EC, ®); + if (error) + return -ENODEV; /* Configure input device */ input = devm_input_allocate_device(dev); @@ -340,6 +340,11 @@ static int tca8418_keypad_probe(struct i2c_client *client, return error; } + /* Initialize the chip */ + error = tca8418_configure(keypad_data, rows, cols); + if (error < 0) + return error; + error = input_register_device(input); if (error) { dev_err(dev, "Unable to register input device, error: %d\n", diff --git a/drivers/input/misc/axp20x-pek.c b/drivers/input/misc/axp20x-pek.c index 6cee5adc3b5c..debeeaeb8812 100644 --- a/drivers/input/misc/axp20x-pek.c +++ b/drivers/input/misc/axp20x-pek.c @@ -403,6 +403,7 @@ static const struct platform_device_id axp_pek_id_match[] = { }, { /* sentinel */ } }; +MODULE_DEVICE_TABLE(platform, axp_pek_id_match); static struct platform_driver axp20x_pek_driver = { .probe = axp20x_pek_probe, @@ -417,4 +418,3 @@ module_platform_driver(axp20x_pek_driver); MODULE_DESCRIPTION("axp20x Power Button"); MODULE_AUTHOR("Carlo Caione <carlo@caione.org>"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:axp20x-pek"); diff --git a/drivers/input/misc/ims-pcu.c b/drivers/input/misc/ims-pcu.c index 6bf82ea8c918..ae473123583b 100644 --- a/drivers/input/misc/ims-pcu.c +++ b/drivers/input/misc/ims-pcu.c @@ -1635,13 +1635,25 @@ ims_pcu_get_cdc_union_desc(struct usb_interface *intf) return NULL; } - while (buflen > 0) { + while (buflen >= sizeof(*union_desc)) { union_desc = (struct usb_cdc_union_desc *)buf; + if (union_desc->bLength > buflen) { + dev_err(&intf->dev, "Too large descriptor\n"); + return NULL; + } + if (union_desc->bDescriptorType == USB_DT_CS_INTERFACE && union_desc->bDescriptorSubType == USB_CDC_UNION_TYPE) { dev_dbg(&intf->dev, "Found union header\n"); - return union_desc; + + if (union_desc->bLength >= sizeof(*union_desc)) + return union_desc; + + dev_err(&intf->dev, + "Union descriptor to short (%d vs %zd\n)", + union_desc->bLength, sizeof(*union_desc)); + return NULL; } buflen -= union_desc->bLength; diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index 0e761d079dc4..6d6b092e2da9 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1258,6 +1258,7 @@ static const struct acpi_device_id elan_acpi_id[] = { { "ELAN0605", 0 }, { "ELAN0609", 0 }, { "ELAN060B", 0 }, + { "ELAN0611", 0 }, { "ELAN1000", 0 }, { } }; diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 5af0b7d200bc..ee5466a374bf 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -1709,8 +1709,7 @@ static int synaptics_create_intertouch(struct psmouse *psmouse, .sensor_pdata = { .sensor_type = rmi_sensor_touchpad, .axis_align.flip_y = true, - /* to prevent cursors jumps: */ - .kernel_tracking = true, + .kernel_tracking = false, .topbuttonpad = topbuttonpad, }, .f30_data = { diff --git a/drivers/input/rmi4/rmi_f30.c b/drivers/input/rmi4/rmi_f30.c index 34dfee555b20..82e0f0d43d55 100644 --- a/drivers/input/rmi4/rmi_f30.c +++ b/drivers/input/rmi4/rmi_f30.c @@ -232,9 +232,10 @@ static int rmi_f30_map_gpios(struct rmi_function *fn, unsigned int trackstick_button = BTN_LEFT; bool button_mapped = false; int i; + int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END); f30->gpioled_key_map = devm_kcalloc(&fn->dev, - f30->gpioled_count, + button_count, sizeof(f30->gpioled_key_map[0]), GFP_KERNEL); if (!f30->gpioled_key_map) { @@ -242,7 +243,7 @@ static int rmi_f30_map_gpios(struct rmi_function *fn, return -ENOMEM; } - for (i = 0; i < f30->gpioled_count; i++) { + for (i = 0; i < button_count; i++) { if (!rmi_f30_is_valid_button(i, f30->ctrl)) continue; diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index b796e891e2ee..4b8b9d7aa75e 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -230,13 +230,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, /* Walk this report and pull out the info we need */ while (i < length) { - prefix = report[i]; - - /* Skip over prefix */ - i++; + prefix = report[i++]; /* Determine data size and save the data in the proper variable */ - size = PREF_SIZE(prefix); + size = (1U << PREF_SIZE(prefix)) >> 1; + if (i + size > length) { + dev_err(ddev, + "Not enough data (need %d, have %d)\n", + i + size, length); + break; + } + switch (size) { case 1: data = report[i]; @@ -244,8 +248,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report, case 2: data16 = get_unaligned_le16(&report[i]); break; - case 3: - size = 4; + case 4: data32 = get_unaligned_le32(&report[i]); break; } diff --git a/drivers/input/touchscreen/goodix.c b/drivers/input/touchscreen/goodix.c index 32d2762448aa..b3bbad7d2282 100644 --- a/drivers/input/touchscreen/goodix.c +++ b/drivers/input/touchscreen/goodix.c @@ -72,6 +72,9 @@ struct goodix_ts_data { #define GOODIX_REG_CONFIG_DATA 0x8047 #define GOODIX_REG_ID 0x8140 +#define GOODIX_BUFFER_STATUS_READY BIT(7) +#define GOODIX_BUFFER_STATUS_TIMEOUT 20 + #define RESOLUTION_LOC 1 #define MAX_CONTACTS_LOC 5 #define TRIGGER_LOC 6 @@ -195,35 +198,53 @@ static int goodix_get_cfg_len(u16 id) static int goodix_ts_read_input_report(struct goodix_ts_data *ts, u8 *data) { + unsigned long max_timeout; int touch_num; int error; - error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, data, - GOODIX_CONTACT_SIZE + 1); - if (error) { - dev_err(&ts->client->dev, "I2C transfer error: %d\n", error); - return error; - } + /* + * The 'buffer status' bit, which indicates that the data is valid, is + * not set as soon as the interrupt is raised, but slightly after. + * This takes around 10 ms to happen, so we poll for 20 ms. + */ + max_timeout = jiffies + msecs_to_jiffies(GOODIX_BUFFER_STATUS_TIMEOUT); + do { + error = goodix_i2c_read(ts->client, GOODIX_READ_COOR_ADDR, + data, GOODIX_CONTACT_SIZE + 1); + if (error) { + dev_err(&ts->client->dev, "I2C transfer error: %d\n", + error); + return error; + } - if (!(data[0] & 0x80)) - return -EAGAIN; + if (data[0] & GOODIX_BUFFER_STATUS_READY) { + touch_num = data[0] & 0x0f; + if (touch_num > ts->max_touch_num) + return -EPROTO; + + if (touch_num > 1) { + data += 1 + GOODIX_CONTACT_SIZE; + error = goodix_i2c_read(ts->client, + GOODIX_READ_COOR_ADDR + + 1 + GOODIX_CONTACT_SIZE, + data, + GOODIX_CONTACT_SIZE * + (touch_num - 1)); + if (error) + return error; + } + + return touch_num; + } - touch_num = data[0] & 0x0f; - if (touch_num > ts->max_touch_num) - return -EPROTO; - - if (touch_num > 1) { - data += 1 + GOODIX_CONTACT_SIZE; - error = goodix_i2c_read(ts->client, - GOODIX_READ_COOR_ADDR + - 1 + GOODIX_CONTACT_SIZE, - data, - GOODIX_CONTACT_SIZE * (touch_num - 1)); - if (error) - return error; - } + usleep_range(1000, 2000); /* Poll every 1 - 2 ms */ + } while (time_before(jiffies, max_timeout)); - return touch_num; + /* + * The Goodix panel will send spurious interrupts after a + * 'finger up' event, which will always cause a timeout. + */ + return 0; } static void goodix_ts_report_touch(struct goodix_ts_data *ts, u8 *coor_data) diff --git a/drivers/input/touchscreen/stmfts.c b/drivers/input/touchscreen/stmfts.c index 157fdb4bb2e8..8c6c6178ec12 100644 --- a/drivers/input/touchscreen/stmfts.c +++ b/drivers/input/touchscreen/stmfts.c @@ -663,12 +663,10 @@ static int stmfts_probe(struct i2c_client *client, sdata->input->open = stmfts_input_open; sdata->input->close = stmfts_input_close; + input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_X); + input_set_capability(sdata->input, EV_ABS, ABS_MT_POSITION_Y); touchscreen_parse_properties(sdata->input, true, &sdata->prop); - input_set_abs_params(sdata->input, ABS_MT_POSITION_X, 0, - sdata->prop.max_x, 0, 0); - input_set_abs_params(sdata->input, ABS_MT_POSITION_Y, 0, - sdata->prop.max_y, 0, 0); input_set_abs_params(sdata->input, ABS_MT_TOUCH_MAJOR, 0, 255, 0, 0); input_set_abs_params(sdata->input, ABS_MT_TOUCH_MINOR, 0, 255, 0, 0); input_set_abs_params(sdata->input, ABS_MT_ORIENTATION, 0, 255, 0, 0); diff --git a/drivers/input/touchscreen/ti_am335x_tsc.c b/drivers/input/touchscreen/ti_am335x_tsc.c index 7953381d939a..f1043ae71dcc 100644 --- a/drivers/input/touchscreen/ti_am335x_tsc.c +++ b/drivers/input/touchscreen/ti_am335x_tsc.c @@ -161,7 +161,7 @@ static void titsc_step_config(struct titsc *ts_dev) break; case 5: config |= ts_dev->bit_xp | STEPCONFIG_INP_AN4 | - ts_dev->bit_xn | ts_dev->bit_yp; + STEPCONFIG_XNP | STEPCONFIG_YPN; break; case 8: config |= ts_dev->bit_yp | STEPCONFIG_INP(ts_dev->inp_xp); diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 51f8215877f5..8e8874d23717 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -2773,14 +2773,16 @@ int __init amd_iommu_init_api(void) int __init amd_iommu_init_dma_ops(void) { - swiotlb = iommu_pass_through ? 1 : 0; + swiotlb = (iommu_pass_through || sme_me_mask) ? 1 : 0; iommu_detected = 1; /* * In case we don't initialize SWIOTLB (actually the common case - * when AMD IOMMU is enabled), make sure there are global - * dma_ops set as a fall-back for devices not handled by this - * driver (for example non-PCI devices). + * when AMD IOMMU is enabled and SME is not active), make sure there + * are global dma_ops set as a fall-back for devices not handled by + * this driver (for example non-PCI devices). When SME is active, + * make sure that swiotlb variable remains set so the global dma_ops + * continue to be SWIOTLB. */ if (!swiotlb) dma_ops = &nommu_dma_ops; @@ -3046,6 +3048,7 @@ static size_t amd_iommu_unmap(struct iommu_domain *dom, unsigned long iova, mutex_unlock(&domain->api_lock); domain_flush_tlb_pde(domain); + domain_flush_complete(domain); return unmap_size; } diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index f596fcc32898..25c2c75f5332 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -709,7 +709,7 @@ static const struct dev_pm_ops sysmmu_pm_ops = { pm_runtime_force_resume) }; -static const struct of_device_id sysmmu_of_match[] __initconst = { +static const struct of_device_id sysmmu_of_match[] = { { .compatible = "samsung,exynos-sysmmu", }, { }, }; diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c index e8d89343d613..e88395605e32 100644 --- a/drivers/irqchip/irq-gic-v3-its.c +++ b/drivers/irqchip/irq-gic-v3-its.c @@ -107,6 +107,10 @@ struct its_node { #define ITS_ITT_ALIGN SZ_256 +/* The maximum number of VPEID bits supported by VLPI commands */ +#define ITS_MAX_VPEID_BITS (16) +#define ITS_MAX_VPEID (1 << (ITS_MAX_VPEID_BITS)) + /* Convert page order to size in bytes */ #define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o)) @@ -308,7 +312,7 @@ static void its_encode_size(struct its_cmd_block *cmd, u8 size) static void its_encode_itt(struct its_cmd_block *cmd, u64 itt_addr) { - its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 50, 8); + its_mask_encode(&cmd->raw_cmd[2], itt_addr >> 8, 51, 8); } static void its_encode_valid(struct its_cmd_block *cmd, int valid) @@ -318,7 +322,7 @@ static void its_encode_valid(struct its_cmd_block *cmd, int valid) static void its_encode_target(struct its_cmd_block *cmd, u64 target_addr) { - its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 50, 16); + its_mask_encode(&cmd->raw_cmd[2], target_addr >> 16, 51, 16); } static void its_encode_collection(struct its_cmd_block *cmd, u16 col) @@ -358,7 +362,7 @@ static void its_encode_its_list(struct its_cmd_block *cmd, u16 its_list) static void its_encode_vpt_addr(struct its_cmd_block *cmd, u64 vpt_pa) { - its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 50, 16); + its_mask_encode(&cmd->raw_cmd[3], vpt_pa >> 16, 51, 16); } static void its_encode_vpt_size(struct its_cmd_block *cmd, u8 vpt_size) @@ -1478,9 +1482,9 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser, u64 val = its_read_baser(its, baser); u64 esz = GITS_BASER_ENTRY_SIZE(val); u64 type = GITS_BASER_TYPE(val); + u64 baser_phys, tmp; u32 alloc_pages; void *base; - u64 tmp; retry_alloc_baser: alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); @@ -1496,8 +1500,24 @@ retry_alloc_baser: if (!base) return -ENOMEM; + baser_phys = virt_to_phys(base); + + /* Check if the physical address of the memory is above 48bits */ + if (IS_ENABLED(CONFIG_ARM64_64K_PAGES) && (baser_phys >> 48)) { + + /* 52bit PA is supported only when PageSize=64K */ + if (psz != SZ_64K) { + pr_err("ITS: no 52bit PA support when psz=%d\n", psz); + free_pages((unsigned long)base, order); + return -ENXIO; + } + + /* Convert 52bit PA to 48bit field */ + baser_phys = GITS_BASER_PHYS_52_to_48(baser_phys); + } + retry_baser: - val = (virt_to_phys(base) | + val = (baser_phys | (type << GITS_BASER_TYPE_SHIFT) | ((esz - 1) << GITS_BASER_ENTRY_SIZE_SHIFT) | ((alloc_pages - 1) << GITS_BASER_PAGES_SHIFT) | @@ -1582,13 +1602,12 @@ retry_baser: static bool its_parse_indirect_baser(struct its_node *its, struct its_baser *baser, - u32 psz, u32 *order) + u32 psz, u32 *order, u32 ids) { u64 tmp = its_read_baser(its, baser); u64 type = GITS_BASER_TYPE(tmp); u64 esz = GITS_BASER_ENTRY_SIZE(tmp); u64 val = GITS_BASER_InnerShareable | GITS_BASER_RaWaWb; - u32 ids = its->device_ids; u32 new_order = *order; bool indirect = false; @@ -1680,9 +1699,13 @@ static int its_alloc_tables(struct its_node *its) continue; case GITS_BASER_TYPE_DEVICE: + indirect = its_parse_indirect_baser(its, baser, + psz, &order, + its->device_ids); case GITS_BASER_TYPE_VCPU: indirect = its_parse_indirect_baser(its, baser, - psz, &order); + psz, &order, + ITS_MAX_VPEID_BITS); break; } @@ -2551,7 +2574,7 @@ static struct irq_chip its_vpe_irq_chip = { static int its_vpe_id_alloc(void) { - return ida_simple_get(&its_vpeid_ida, 0, 1 << 16, GFP_KERNEL); + return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL); } static void its_vpe_id_free(u16 id) @@ -2851,7 +2874,7 @@ static int its_init_vpe_domain(void) return -ENOMEM; } - BUG_ON(entries != vpe_proxy.dev->nr_ites); + BUG_ON(entries > vpe_proxy.dev->nr_ites); raw_spin_lock_init(&vpe_proxy.lock); vpe_proxy.next_victim = 0; diff --git a/drivers/irqchip/irq-tango.c b/drivers/irqchip/irq-tango.c index bdbb5c0ff7fe..0c085303a583 100644 --- a/drivers/irqchip/irq-tango.c +++ b/drivers/irqchip/irq-tango.c @@ -141,7 +141,7 @@ static void __init tangox_irq_init_chip(struct irq_chip_generic *gc, for (i = 0; i < 2; i++) { ct[i].chip.irq_ack = irq_gc_ack_set_bit; ct[i].chip.irq_mask = irq_gc_mask_disable_reg; - ct[i].chip.irq_mask_ack = irq_gc_mask_disable_reg_and_ack; + ct[i].chip.irq_mask_ack = irq_gc_mask_disable_and_ack_set; ct[i].chip.irq_unmask = irq_gc_unmask_enable_reg; ct[i].chip.irq_set_type = tangox_irq_set_type; ct[i].chip.name = gc->domain->name; diff --git a/drivers/md/bcache/closure.c b/drivers/md/bcache/closure.c index 7d5286b05036..1841d0359bac 100644 --- a/drivers/md/bcache/closure.c +++ b/drivers/md/bcache/closure.c @@ -64,7 +64,7 @@ EXPORT_SYMBOL(closure_put); void __closure_wake_up(struct closure_waitlist *wait_list) { struct llist_node *list; - struct closure *cl; + struct closure *cl, *t; struct llist_node *reverse = NULL; list = llist_del_all(&wait_list->list); @@ -73,7 +73,7 @@ void __closure_wake_up(struct closure_waitlist *wait_list) reverse = llist_reverse_order(list); /* Then do the wakeups */ - llist_for_each_entry(cl, reverse, list) { + llist_for_each_entry_safe(cl, t, reverse, list) { closure_set_waiting(cl, 0); closure_sub(cl, CLOSURE_WAITING + 1); } diff --git a/drivers/md/dm-core.h b/drivers/md/dm-core.h index 24eddbdf2ab4..203144762f36 100644 --- a/drivers/md/dm-core.h +++ b/drivers/md/dm-core.h @@ -149,5 +149,6 @@ static inline bool dm_message_test_buffer_overflow(char *result, unsigned maxlen extern atomic_t dm_global_event_nr; extern wait_queue_head_t dm_global_eventq; +void dm_issue_global_event(void); #endif diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index a55ffd4f5933..96ab46512e1f 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -2466,6 +2466,7 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key kfree(cipher_api); return ret; } + kfree(cipher_api); return 0; bad_mem: @@ -2584,6 +2585,10 @@ static int crypt_ctr_optional(struct dm_target *ti, unsigned int argc, char **ar ti->error = "Invalid feature value for sector_size"; return -EINVAL; } + if (ti->len & ((cc->sector_size >> SECTOR_SHIFT) - 1)) { + ti->error = "Device size is not multiple of sector_size feature"; + return -EINVAL; + } cc->sector_shift = __ffs(cc->sector_size) - SECTOR_SHIFT; } else if (!strcasecmp(opt_string, "iv_large_sectors")) set_bit(CRYPT_IV_LARGE_SECTORS, &cc->cipher_flags); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 8756a6850431..e52676fa9832 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -477,9 +477,13 @@ static int remove_all(struct file *filp, struct dm_ioctl *param, size_t param_si * Round up the ptr to an 8-byte boundary. */ #define ALIGN_MASK 7 +static inline size_t align_val(size_t val) +{ + return (val + ALIGN_MASK) & ~ALIGN_MASK; +} static inline void *align_ptr(void *ptr) { - return (void *) (((size_t) (ptr + ALIGN_MASK)) & ~ALIGN_MASK); + return (void *)align_val((size_t)ptr); } /* @@ -505,7 +509,7 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ struct hash_cell *hc; size_t len, needed = 0; struct gendisk *disk; - struct dm_name_list *nl, *old_nl = NULL; + struct dm_name_list *orig_nl, *nl, *old_nl = NULL; uint32_t *event_nr; down_write(&_hash_lock); @@ -516,17 +520,15 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ */ for (i = 0; i < NUM_BUCKETS; i++) { list_for_each_entry (hc, _name_buckets + i, name_list) { - needed += sizeof(struct dm_name_list); - needed += strlen(hc->name) + 1; - needed += ALIGN_MASK; - needed += (sizeof(uint32_t) + ALIGN_MASK) & ~ALIGN_MASK; + needed += align_val(offsetof(struct dm_name_list, name) + strlen(hc->name) + 1); + needed += align_val(sizeof(uint32_t)); } } /* * Grab our output buffer. */ - nl = get_result_buffer(param, param_size, &len); + nl = orig_nl = get_result_buffer(param, param_size, &len); if (len < needed) { param->flags |= DM_BUFFER_FULL_FLAG; goto out; @@ -549,11 +551,16 @@ static int list_devices(struct file *filp, struct dm_ioctl *param, size_t param_ strcpy(nl->name, hc->name); old_nl = nl; - event_nr = align_ptr(((void *) (nl + 1)) + strlen(hc->name) + 1); + event_nr = align_ptr(nl->name + strlen(hc->name) + 1); *event_nr = dm_get_event_nr(hc->md); nl = align_ptr(event_nr + 1); } } + /* + * If mismatch happens, security may be compromised due to buffer + * overflow, so it's better to crash. + */ + BUG_ON((char *)nl - (char *)orig_nl != needed); out: up_write(&_hash_lock); @@ -1621,7 +1628,8 @@ static int target_message(struct file *filp, struct dm_ioctl *param, size_t para * which has a variable size, is not used by the function processing * the ioctl. */ -#define IOCTL_FLAGS_NO_PARAMS 1 +#define IOCTL_FLAGS_NO_PARAMS 1 +#define IOCTL_FLAGS_ISSUE_GLOBAL_EVENT 2 /*----------------------------------------------------------------- * Implementation of open/close/ioctl on the special char @@ -1635,12 +1643,12 @@ static ioctl_fn lookup_ioctl(unsigned int cmd, int *ioctl_flags) ioctl_fn fn; } _ioctls[] = { {DM_VERSION_CMD, 0, NULL}, /* version is dealt with elsewhere */ - {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS, remove_all}, + {DM_REMOVE_ALL_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, remove_all}, {DM_LIST_DEVICES_CMD, 0, list_devices}, - {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_create}, - {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS, dev_remove}, - {DM_DEV_RENAME_CMD, 0, dev_rename}, + {DM_DEV_CREATE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_create}, + {DM_DEV_REMOVE_CMD, IOCTL_FLAGS_NO_PARAMS | IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_remove}, + {DM_DEV_RENAME_CMD, IOCTL_FLAGS_ISSUE_GLOBAL_EVENT, dev_rename}, {DM_DEV_SUSPEND_CMD, IOCTL_FLAGS_NO_PARAMS, dev_suspend}, {DM_DEV_STATUS_CMD, IOCTL_FLAGS_NO_PARAMS, dev_status}, {DM_DEV_WAIT_CMD, 0, dev_wait}, @@ -1869,6 +1877,9 @@ static int ctl_ioctl(struct file *file, uint command, struct dm_ioctl __user *us unlikely(ioctl_flags & IOCTL_FLAGS_NO_PARAMS)) DMERR("ioctl %d tried to output some data but has IOCTL_FLAGS_NO_PARAMS set", cmd); + if (!r && ioctl_flags & IOCTL_FLAGS_ISSUE_GLOBAL_EVENT) + dm_issue_global_event(); + /* * Copy the results back to userland. */ diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 1ac58c5651b7..2245d06d2045 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c @@ -3297,11 +3297,10 @@ static const char *__raid_dev_status(struct raid_set *rs, struct md_rdev *rdev, static sector_t rs_get_progress(struct raid_set *rs, sector_t resync_max_sectors, bool *array_in_sync) { - sector_t r, recovery_cp, curr_resync_completed; + sector_t r, curr_resync_completed; struct mddev *mddev = &rs->md; curr_resync_completed = mddev->curr_resync_completed ?: mddev->recovery_cp; - recovery_cp = mddev->recovery_cp; *array_in_sync = false; if (rs_is_raid0(rs)) { @@ -3330,9 +3329,11 @@ static sector_t rs_get_progress(struct raid_set *rs, } else if (test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) r = curr_resync_completed; else - r = recovery_cp; + r = mddev->recovery_cp; - if (r == MaxSector) { + if ((r == MaxSector) || + (test_bit(MD_RECOVERY_DONE, &mddev->recovery) && + (mddev->curr_resync_completed == resync_max_sectors))) { /* * Sync complete. */ @@ -3892,7 +3893,7 @@ static void raid_resume(struct dm_target *ti) static struct target_type raid_target = { .name = "raid", - .version = {1, 12, 1}, + .version = {1, 13, 0}, .module = THIS_MODULE, .ctr = raid_ctr, .dtr = raid_dtr, diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 6e54145969c5..4be85324f44d 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -52,6 +52,12 @@ static struct workqueue_struct *deferred_remove_workqueue; atomic_t dm_global_event_nr = ATOMIC_INIT(0); DECLARE_WAIT_QUEUE_HEAD(dm_global_eventq); +void dm_issue_global_event(void) +{ + atomic_inc(&dm_global_event_nr); + wake_up(&dm_global_eventq); +} + /* * One of these is allocated per bio. */ @@ -1865,9 +1871,8 @@ static void event_callback(void *context) dm_send_uevents(&uevents, &disk_to_dev(md->disk)->kobj); atomic_inc(&md->event_nr); - atomic_inc(&dm_global_event_nr); wake_up(&md->eventq); - wake_up(&dm_global_eventq); + dm_issue_global_event(); } /* @@ -2283,6 +2288,7 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table) } map = __bind(md, table, &limits); + dm_issue_global_event(); out: mutex_unlock(&md->suspend_lock); diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index eed6c397d840..f8a808d45034 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -1797,12 +1797,19 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, */ switch (msg->msg[1]) { case CEC_MSG_GET_CEC_VERSION: - case CEC_MSG_GIVE_DEVICE_VENDOR_ID: case CEC_MSG_ABORT: case CEC_MSG_GIVE_DEVICE_POWER_STATUS: - case CEC_MSG_GIVE_PHYSICAL_ADDR: case CEC_MSG_GIVE_OSD_NAME: + /* + * These messages reply with a directed message, so ignore if + * the initiator is Unregistered. + */ + if (!adap->passthrough && from_unregistered) + return 0; + /* Fall through */ + case CEC_MSG_GIVE_DEVICE_VENDOR_ID: case CEC_MSG_GIVE_FEATURES: + case CEC_MSG_GIVE_PHYSICAL_ADDR: /* * Skip processing these messages if the passthrough mode * is on. @@ -1810,7 +1817,7 @@ static int cec_receive_notify(struct cec_adapter *adap, struct cec_msg *msg, if (adap->passthrough) goto skip_processing; /* Ignore if addressing is wrong */ - if (is_broadcast || from_unregistered) + if (is_broadcast) return 0; break; diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 2fcba1616168..9139d01ba7ed 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c @@ -141,22 +141,39 @@ struct dvb_frontend_private { static void dvb_frontend_invoke_release(struct dvb_frontend *fe, void (*release)(struct dvb_frontend *fe)); -static void dvb_frontend_free(struct kref *ref) +static void __dvb_frontend_free(struct dvb_frontend *fe) { - struct dvb_frontend *fe = - container_of(ref, struct dvb_frontend, refcount); struct dvb_frontend_private *fepriv = fe->frontend_priv; + if (!fepriv) + return; + dvb_free_device(fepriv->dvbdev); dvb_frontend_invoke_release(fe, fe->ops.release); kfree(fepriv); + fe->frontend_priv = NULL; +} + +static void dvb_frontend_free(struct kref *ref) +{ + struct dvb_frontend *fe = + container_of(ref, struct dvb_frontend, refcount); + + __dvb_frontend_free(fe); } static void dvb_frontend_put(struct dvb_frontend *fe) { - kref_put(&fe->refcount, dvb_frontend_free); + /* + * Check if the frontend was registered, as otherwise + * kref was not initialized yet. + */ + if (fe->frontend_priv) + kref_put(&fe->refcount, dvb_frontend_free); + else + __dvb_frontend_free(fe); } static void dvb_frontend_get(struct dvb_frontend *fe) diff --git a/drivers/media/dvb-frontends/dib3000mc.c b/drivers/media/dvb-frontends/dib3000mc.c index 224283fe100a..4d086a7248e9 100644 --- a/drivers/media/dvb-frontends/dib3000mc.c +++ b/drivers/media/dvb-frontends/dib3000mc.c @@ -55,29 +55,57 @@ struct dib3000mc_state { static u16 dib3000mc_read_word(struct dib3000mc_state *state, u16 reg) { - u8 wb[2] = { (reg >> 8) | 0x80, reg & 0xff }; - u8 rb[2]; struct i2c_msg msg[2] = { - { .addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2 }, - { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 }, + { .addr = state->i2c_addr >> 1, .flags = 0, .len = 2 }, + { .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .len = 2 }, }; + u16 word; + u8 *b; + + b = kmalloc(4, GFP_KERNEL); + if (!b) + return 0; + + b[0] = (reg >> 8) | 0x80; + b[1] = reg; + b[2] = 0; + b[3] = 0; + + msg[0].buf = b; + msg[1].buf = b + 2; if (i2c_transfer(state->i2c_adap, msg, 2) != 2) dprintk("i2c read error on %d\n",reg); - return (rb[0] << 8) | rb[1]; + word = (b[2] << 8) | b[3]; + kfree(b); + + return word; } static int dib3000mc_write_word(struct dib3000mc_state *state, u16 reg, u16 val) { - u8 b[4] = { - (reg >> 8) & 0xff, reg & 0xff, - (val >> 8) & 0xff, val & 0xff, - }; struct i2c_msg msg = { - .addr = state->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4 + .addr = state->i2c_addr >> 1, .flags = 0, .len = 4 }; - return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; + int rc; + u8 *b; + + b = kmalloc(4, GFP_KERNEL); + if (!b) + return -ENOMEM; + + b[0] = reg >> 8; + b[1] = reg; + b[2] = val >> 8; + b[3] = val; + + msg.buf = b; + + rc = i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0; + kfree(b); + + return rc; } static int dib3000mc_identify(struct dib3000mc_state *state) diff --git a/drivers/media/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index 7bec3e028bee..5553b89b804e 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -753,13 +753,19 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, struct i2c_adapter *i2c, unsigned int pll_desc_id) { - u8 b1 [] = { 0 }; - struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, - .buf = b1, .len = 1 }; + u8 *b1; + struct i2c_msg msg = { .addr = pll_addr, .flags = I2C_M_RD, .len = 1 }; struct dvb_pll_priv *priv = NULL; int ret; const struct dvb_pll_desc *desc; + b1 = kmalloc(1, GFP_KERNEL); + if (!b1) + return NULL; + + b1[0] = 0; + msg.buf = b1; + if ((id[dvb_pll_devcount] > DVB_PLL_UNDEFINED) && (id[dvb_pll_devcount] < ARRAY_SIZE(pll_list))) pll_desc_id = id[dvb_pll_devcount]; @@ -773,15 +779,19 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, fe->ops.i2c_gate_ctrl(fe, 1); ret = i2c_transfer (i2c, &msg, 1); - if (ret != 1) + if (ret != 1) { + kfree(b1); return NULL; + } if (fe->ops.i2c_gate_ctrl) fe->ops.i2c_gate_ctrl(fe, 0); } priv = kzalloc(sizeof(struct dvb_pll_priv), GFP_KERNEL); - if (priv == NULL) + if (!priv) { + kfree(b1); return NULL; + } priv->pll_i2c_address = pll_addr; priv->i2c = i2c; @@ -811,6 +821,8 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr, "insmod option" : "autodetected"); } + kfree(b1); + return fe; } EXPORT_SYMBOL(dvb_pll_attach); diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 7e7cc49b8674..3c4f7fa7b9d8 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -112,7 +112,7 @@ config VIDEO_PXA27x config VIDEO_QCOM_CAMSS tristate "Qualcomm 8x16 V4L2 Camera Subsystem driver" - depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API + depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API && HAS_DMA depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST select VIDEOBUF2_DMA_SG select V4L2_FWNODE diff --git a/drivers/media/platform/qcom/camss-8x16/camss-vfe.c b/drivers/media/platform/qcom/camss-8x16/camss-vfe.c index b21b3c2dc77f..b22d2dfcd3c2 100644 --- a/drivers/media/platform/qcom/camss-8x16/camss-vfe.c +++ b/drivers/media/platform/qcom/camss-8x16/camss-vfe.c @@ -2660,7 +2660,7 @@ static int vfe_get_selection(struct v4l2_subdev *sd, * * Return -EINVAL or zero on success */ -int vfe_set_selection(struct v4l2_subdev *sd, +static int vfe_set_selection(struct v4l2_subdev *sd, struct v4l2_subdev_pad_config *cfg, struct v4l2_subdev_selection *sel) { diff --git a/drivers/media/platform/qcom/venus/helpers.c b/drivers/media/platform/qcom/venus/helpers.c index 68933d208063..9b2a401a4891 100644 --- a/drivers/media/platform/qcom/venus/helpers.c +++ b/drivers/media/platform/qcom/venus/helpers.c @@ -682,6 +682,7 @@ void venus_helper_vb2_stop_streaming(struct vb2_queue *q) hfi_session_abort(inst); load_scale_clocks(core); + INIT_LIST_HEAD(&inst->registeredbufs); } venus_helper_buffers_done(inst, VB2_BUF_STATE_ERROR); diff --git a/drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c b/drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c index 1edf667d562a..146ae6f25cdb 100644 --- a/drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c +++ b/drivers/media/platform/s5p-cec/exynos_hdmi_cecctrl.c @@ -172,7 +172,8 @@ u32 s5p_cec_get_status(struct s5p_cec_dev *cec) { u32 status = 0; - status = readb(cec->reg + S5P_CEC_STATUS_0); + status = readb(cec->reg + S5P_CEC_STATUS_0) & 0xf; + status |= (readb(cec->reg + S5P_CEC_TX_STAT1) & 0xf) << 4; status |= readb(cec->reg + S5P_CEC_STATUS_1) << 8; status |= readb(cec->reg + S5P_CEC_STATUS_2) << 16; status |= readb(cec->reg + S5P_CEC_STATUS_3) << 24; diff --git a/drivers/media/platform/s5p-cec/s5p_cec.c b/drivers/media/platform/s5p-cec/s5p_cec.c index 58d200e7c838..8837e2678bde 100644 --- a/drivers/media/platform/s5p-cec/s5p_cec.c +++ b/drivers/media/platform/s5p-cec/s5p_cec.c @@ -92,7 +92,10 @@ static irqreturn_t s5p_cec_irq_handler(int irq, void *priv) dev_dbg(cec->dev, "irq received\n"); if (status & CEC_STATUS_TX_DONE) { - if (status & CEC_STATUS_TX_ERROR) { + if (status & CEC_STATUS_TX_NACK) { + dev_dbg(cec->dev, "CEC_STATUS_TX_NACK set\n"); + cec->tx = STATE_NACK; + } else if (status & CEC_STATUS_TX_ERROR) { dev_dbg(cec->dev, "CEC_STATUS_TX_ERROR set\n"); cec->tx = STATE_ERROR; } else { @@ -135,6 +138,12 @@ static irqreturn_t s5p_cec_irq_handler_thread(int irq, void *priv) cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); cec->tx = STATE_IDLE; break; + case STATE_NACK: + cec_transmit_done(cec->adap, + CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_NACK, + 0, 1, 0, 0); + cec->tx = STATE_IDLE; + break; case STATE_ERROR: cec_transmit_done(cec->adap, CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_ERROR, diff --git a/drivers/media/platform/s5p-cec/s5p_cec.h b/drivers/media/platform/s5p-cec/s5p_cec.h index 8bcd8dc1aeb9..86ded522ef27 100644 --- a/drivers/media/platform/s5p-cec/s5p_cec.h +++ b/drivers/media/platform/s5p-cec/s5p_cec.h @@ -35,6 +35,7 @@ #define CEC_STATUS_TX_TRANSFERRING (1 << 1) #define CEC_STATUS_TX_DONE (1 << 2) #define CEC_STATUS_TX_ERROR (1 << 3) +#define CEC_STATUS_TX_NACK (1 << 4) #define CEC_STATUS_TX_BYTES (0xFF << 8) #define CEC_STATUS_RX_RUNNING (1 << 16) #define CEC_STATUS_RX_RECEIVING (1 << 17) @@ -55,6 +56,7 @@ enum cec_state { STATE_IDLE, STATE_BUSY, STATE_DONE, + STATE_NACK, STATE_ERROR }; diff --git a/drivers/media/rc/ir-sharp-decoder.c b/drivers/media/rc/ir-sharp-decoder.c index ed43a4212479..129b558acc92 100644 --- a/drivers/media/rc/ir-sharp-decoder.c +++ b/drivers/media/rc/ir-sharp-decoder.c @@ -245,5 +245,5 @@ module_init(ir_sharp_decode_init); module_exit(ir_sharp_decode_exit); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("James Hogan <james.hogan@imgtec.com>"); +MODULE_AUTHOR("James Hogan <jhogan@kernel.org>"); MODULE_DESCRIPTION("Sharp IR protocol decoder"); diff --git a/drivers/media/tuners/mt2060.c b/drivers/media/tuners/mt2060.c index 2e487f9a2cc3..4983eeb39f36 100644 --- a/drivers/media/tuners/mt2060.c +++ b/drivers/media/tuners/mt2060.c @@ -38,41 +38,74 @@ MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off)."); static int mt2060_readreg(struct mt2060_priv *priv, u8 reg, u8 *val) { struct i2c_msg msg[2] = { - { .addr = priv->cfg->i2c_address, .flags = 0, .buf = ®, .len = 1 }, - { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .buf = val, .len = 1 }, + { .addr = priv->cfg->i2c_address, .flags = 0, .len = 1 }, + { .addr = priv->cfg->i2c_address, .flags = I2C_M_RD, .len = 1 }, }; + int rc = 0; + u8 *b; + + b = kmalloc(2, GFP_KERNEL); + if (!b) + return -ENOMEM; + + b[0] = reg; + b[1] = 0; + + msg[0].buf = b; + msg[1].buf = b + 1; if (i2c_transfer(priv->i2c, msg, 2) != 2) { printk(KERN_WARNING "mt2060 I2C read failed\n"); - return -EREMOTEIO; + rc = -EREMOTEIO; } - return 0; + *val = b[1]; + kfree(b); + + return rc; } // Writes a single register static int mt2060_writereg(struct mt2060_priv *priv, u8 reg, u8 val) { - u8 buf[2] = { reg, val }; struct i2c_msg msg = { - .addr = priv->cfg->i2c_address, .flags = 0, .buf = buf, .len = 2 + .addr = priv->cfg->i2c_address, .flags = 0, .len = 2 }; + u8 *buf; + int rc = 0; + + buf = kmalloc(2, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + buf[0] = reg; + buf[1] = val; + + msg.buf = buf; if (i2c_transfer(priv->i2c, &msg, 1) != 1) { printk(KERN_WARNING "mt2060 I2C write failed\n"); - return -EREMOTEIO; + rc = -EREMOTEIO; } - return 0; + kfree(buf); + return rc; } // Writes a set of consecutive registers static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) { int rem, val_len; - u8 xfer_buf[16]; + u8 *xfer_buf; + int rc = 0; struct i2c_msg msg = { - .addr = priv->cfg->i2c_address, .flags = 0, .buf = xfer_buf + .addr = priv->cfg->i2c_address, .flags = 0 }; + xfer_buf = kmalloc(16, GFP_KERNEL); + if (!xfer_buf) + return -ENOMEM; + + msg.buf = xfer_buf; + for (rem = len - 1; rem > 0; rem -= priv->i2c_max_regs) { val_len = min_t(int, rem, priv->i2c_max_regs); msg.len = 1 + val_len; @@ -81,11 +114,13 @@ static int mt2060_writeregs(struct mt2060_priv *priv,u8 *buf, u8 len) if (i2c_transfer(priv->i2c, &msg, 1) != 1) { printk(KERN_WARNING "mt2060 I2C write failed (len=%i)\n", val_len); - return -EREMOTEIO; + rc = -EREMOTEIO; + break; } } - return 0; + kfree(xfer_buf); + return rc; } // Initialisation sequences diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c index 9f389f36566d..a9806ba6116d 100644 --- a/drivers/media/v4l2-core/videobuf2-dma-contig.c +++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c @@ -479,7 +479,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, { struct vb2_dc_buf *buf; struct frame_vector *vec; - unsigned long offset; + unsigned int offset; int n_pages, i; int ret = 0; struct sg_table *sgt; @@ -507,7 +507,7 @@ static void *vb2_dc_get_userptr(struct device *dev, unsigned long vaddr, buf->dev = dev; buf->dma_dir = dma_dir; - offset = vaddr & ~PAGE_MASK; + offset = lower_32_bits(offset_in_page(vaddr)); vec = vb2_create_framevec(vaddr, size, dma_dir == DMA_FROM_DEVICE || dma_dir == DMA_BIDIRECTIONAL); if (IS_ERR(vec)) { diff --git a/drivers/misc/cxl/cxllib.c b/drivers/misc/cxl/cxllib.c index 5dba23ca2e5f..dc9bc1807fdf 100644 --- a/drivers/misc/cxl/cxllib.c +++ b/drivers/misc/cxl/cxllib.c @@ -219,8 +219,17 @@ int cxllib_handle_fault(struct mm_struct *mm, u64 addr, u64 size, u64 flags) down_read(&mm->mmap_sem); - for (dar = addr; dar < addr + size; dar += page_size) { - if (!vma || dar < vma->vm_start || dar > vma->vm_end) { + vma = find_vma(mm, addr); + if (!vma) { + pr_err("Can't find vma for addr %016llx\n", addr); + rc = -EFAULT; + goto out; + } + /* get the size of the pages allocated */ + page_size = vma_kernel_pagesize(vma); + + for (dar = (addr & ~(page_size - 1)); dar < (addr + size); dar += page_size) { + if (dar < vma->vm_start || dar >= vma->vm_end) { vma = find_vma(mm, addr); if (!vma) { pr_err("Can't find vma for addr %016llx\n", addr); diff --git a/drivers/misc/mei/hw-me-regs.h b/drivers/misc/mei/hw-me-regs.h index c8307e8b4c16..0ccccbaf530d 100644 --- a/drivers/misc/mei/hw-me-regs.h +++ b/drivers/misc/mei/hw-me-regs.h @@ -127,6 +127,8 @@ #define MEI_DEV_ID_BXT_M 0x1A9A /* Broxton M */ #define MEI_DEV_ID_APL_I 0x5A9A /* Apollo Lake I */ +#define MEI_DEV_ID_GLK 0x319A /* Gemini Lake */ + #define MEI_DEV_ID_KBP 0xA2BA /* Kaby Point */ #define MEI_DEV_ID_KBP_2 0xA2BB /* Kaby Point 2 */ diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index 4ff40d319676..78b3172c8e6e 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c @@ -93,6 +93,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = { {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)}, + {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)}, {MEI_PCI_DEVICE(MEI_DEV_ID_KBP_2, MEI_ME_PCH8_CFG)}, @@ -226,12 +228,15 @@ static int mei_me_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; /* - * For not wake-able HW runtime pm framework - * can't be used on pci device level. - * Use domain runtime pm callbacks instead. - */ - if (!pci_dev_run_wake(pdev)) - mei_me_set_pm_domain(dev); + * ME maps runtime suspend/resume to D0i states, + * hence we need to go around native PCI runtime service which + * eventually brings the device into D3cold/hot state, + * but the mei device cannot wake up from D3 unlike from D0i3. + * To get around the PCI device native runtime pm, + * ME uses runtime pm domain handlers which take precedence + * over the driver's pm handlers. + */ + mei_me_set_pm_domain(dev); if (mei_pg_is_enabled(dev)) pm_runtime_put_noidle(&pdev->dev); @@ -271,8 +276,7 @@ static void mei_me_shutdown(struct pci_dev *pdev) dev_dbg(&pdev->dev, "shutdown\n"); mei_stop(dev); - if (!pci_dev_run_wake(pdev)) - mei_me_unset_pm_domain(dev); + mei_me_unset_pm_domain(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); @@ -300,8 +304,7 @@ static void mei_me_remove(struct pci_dev *pdev) dev_dbg(&pdev->dev, "stop\n"); mei_stop(dev); - if (!pci_dev_run_wake(pdev)) - mei_me_unset_pm_domain(dev); + mei_me_unset_pm_domain(dev); mei_disable_interrupts(dev); diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index e38a5f144373..0566f9bfa7de 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -144,12 +144,14 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) pdev->dev_flags |= PCI_DEV_FLAGS_NEEDS_RESUME; /* - * For not wake-able HW runtime pm framework - * can't be used on pci device level. - * Use domain runtime pm callbacks instead. - */ - if (!pci_dev_run_wake(pdev)) - mei_txe_set_pm_domain(dev); + * TXE maps runtime suspend/resume to own power gating states, + * hence we need to go around native PCI runtime service which + * eventually brings the device into D3cold/hot state. + * But the TXE device cannot wake up from D3 unlike from own + * power gating. To get around PCI device native runtime pm, + * TXE uses runtime pm domain handlers which take precedence. + */ + mei_txe_set_pm_domain(dev); pm_runtime_put_noidle(&pdev->dev); @@ -186,8 +188,7 @@ static void mei_txe_shutdown(struct pci_dev *pdev) dev_dbg(&pdev->dev, "shutdown\n"); mei_stop(dev); - if (!pci_dev_run_wake(pdev)) - mei_txe_unset_pm_domain(dev); + mei_txe_unset_pm_domain(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); @@ -215,8 +216,7 @@ static void mei_txe_remove(struct pci_dev *pdev) mei_stop(dev); - if (!pci_dev_run_wake(pdev)) - mei_txe_unset_pm_domain(dev); + mei_txe_unset_pm_domain(dev); mei_disable_interrupts(dev); free_irq(pdev->irq, dev); @@ -318,15 +318,7 @@ static int mei_txe_pm_runtime_suspend(struct device *device) else ret = -EAGAIN; - /* - * If everything is okay we're about to enter PCI low - * power state (D3) therefor we need to disable the - * interrupts towards host. - * However if device is not wakeable we do not enter - * D-low state and we need to keep the interrupt kicking - */ - if (!ret && pci_dev_run_wake(pdev)) - mei_disable_interrupts(dev); + /* keep irq on we are staying in D0 */ dev_dbg(&pdev->dev, "rpm: txe: runtime suspend ret=%d\n", ret); diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 29fc1e662891..2ad7b5c69156 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -1634,8 +1634,6 @@ static void mmc_blk_data_prep(struct mmc_queue *mq, struct mmc_queue_req *mqrq, } mqrq->areq.mrq = &brq->mrq; - - mmc_queue_bounce_pre(mqrq); } static void mmc_blk_rw_rq_prep(struct mmc_queue_req *mqrq, @@ -1829,7 +1827,6 @@ static void mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *new_req) brq = &mq_rq->brq; old_req = mmc_queue_req_to_req(mq_rq); type = rq_data_dir(old_req) == READ ? MMC_BLK_READ : MMC_BLK_WRITE; - mmc_queue_bounce_post(mq_rq); switch (status) { case MMC_BLK_SUCCESS: diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index a7eb623f8daa..36217ad5e9b1 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c @@ -1286,6 +1286,23 @@ out_err: return err; } +static void mmc_select_driver_type(struct mmc_card *card) +{ + int card_drv_type, drive_strength, drv_type; + + card_drv_type = card->ext_csd.raw_driver_strength | + mmc_driver_type_mask(0); + + drive_strength = mmc_select_drive_strength(card, + card->ext_csd.hs200_max_dtr, + card_drv_type, &drv_type); + + card->drive_strength = drive_strength; + + if (drv_type) + mmc_set_driver_type(card->host, drv_type); +} + static int mmc_select_hs400es(struct mmc_card *card) { struct mmc_host *host = card->host; @@ -1341,6 +1358,8 @@ static int mmc_select_hs400es(struct mmc_card *card) goto out_err; } + mmc_select_driver_type(card); + /* Switch card to HS400 */ val = EXT_CSD_TIMING_HS400 | card->drive_strength << EXT_CSD_DRV_STR_SHIFT; @@ -1374,23 +1393,6 @@ out_err: return err; } -static void mmc_select_driver_type(struct mmc_card *card) -{ - int card_drv_type, drive_strength, drv_type; - - card_drv_type = card->ext_csd.raw_driver_strength | - mmc_driver_type_mask(0); - - drive_strength = mmc_select_drive_strength(card, - card->ext_csd.hs200_max_dtr, - card_drv_type, &drv_type); - - card->drive_strength = drive_strength; - - if (drv_type) - mmc_set_driver_type(card->host, drv_type); -} - /* * For device supporting HS200 mode, the following sequence * should be done before executing the tuning process. diff --git a/drivers/mmc/core/queue.c b/drivers/mmc/core/queue.c index 74c663b1c0a7..0a4e77a5ba33 100644 --- a/drivers/mmc/core/queue.c +++ b/drivers/mmc/core/queue.c @@ -23,8 +23,6 @@ #include "core.h" #include "card.h" -#define MMC_QUEUE_BOUNCESZ 65536 - /* * Prepare a MMC request. This just filters out odd stuff. */ @@ -150,26 +148,6 @@ static void mmc_queue_setup_discard(struct request_queue *q, queue_flag_set_unlocked(QUEUE_FLAG_SECERASE, q); } -static unsigned int mmc_queue_calc_bouncesz(struct mmc_host *host) -{ - unsigned int bouncesz = MMC_QUEUE_BOUNCESZ; - - if (host->max_segs != 1 || (host->caps & MMC_CAP_NO_BOUNCE_BUFF)) - return 0; - - if (bouncesz > host->max_req_size) - bouncesz = host->max_req_size; - if (bouncesz > host->max_seg_size) - bouncesz = host->max_seg_size; - if (bouncesz > host->max_blk_count * 512) - bouncesz = host->max_blk_count * 512; - - if (bouncesz <= 512) - return 0; - - return bouncesz; -} - /** * mmc_init_request() - initialize the MMC-specific per-request data * @q: the request queue @@ -184,26 +162,9 @@ static int mmc_init_request(struct request_queue *q, struct request *req, struct mmc_card *card = mq->card; struct mmc_host *host = card->host; - if (card->bouncesz) { - mq_rq->bounce_buf = kmalloc(card->bouncesz, gfp); - if (!mq_rq->bounce_buf) - return -ENOMEM; - if (card->bouncesz > 512) { - mq_rq->sg = mmc_alloc_sg(1, gfp); - if (!mq_rq->sg) - return -ENOMEM; - mq_rq->bounce_sg = mmc_alloc_sg(card->bouncesz / 512, - gfp); - if (!mq_rq->bounce_sg) - return -ENOMEM; - } - } else { - mq_rq->bounce_buf = NULL; - mq_rq->bounce_sg = NULL; - mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp); - if (!mq_rq->sg) - return -ENOMEM; - } + mq_rq->sg = mmc_alloc_sg(host->max_segs, gfp); + if (!mq_rq->sg) + return -ENOMEM; return 0; } @@ -212,13 +173,6 @@ static void mmc_exit_request(struct request_queue *q, struct request *req) { struct mmc_queue_req *mq_rq = req_to_mmc_queue_req(req); - /* It is OK to kfree(NULL) so this will be smooth */ - kfree(mq_rq->bounce_sg); - mq_rq->bounce_sg = NULL; - - kfree(mq_rq->bounce_buf); - mq_rq->bounce_buf = NULL; - kfree(mq_rq->sg); mq_rq->sg = NULL; } @@ -242,12 +196,6 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, if (mmc_dev(host)->dma_mask && *mmc_dev(host)->dma_mask) limit = (u64)dma_max_pfn(mmc_dev(host)) << PAGE_SHIFT; - /* - * mmc_init_request() depends on card->bouncesz so it must be calculated - * before blk_init_allocated_queue() starts allocating requests. - */ - card->bouncesz = mmc_queue_calc_bouncesz(host); - mq->card = card; mq->queue = blk_alloc_queue(GFP_KERNEL); if (!mq->queue) @@ -271,17 +219,11 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, if (mmc_can_erase(card)) mmc_queue_setup_discard(mq->queue, card); - if (card->bouncesz) { - blk_queue_max_hw_sectors(mq->queue, card->bouncesz / 512); - blk_queue_max_segments(mq->queue, card->bouncesz / 512); - blk_queue_max_segment_size(mq->queue, card->bouncesz); - } else { - blk_queue_bounce_limit(mq->queue, limit); - blk_queue_max_hw_sectors(mq->queue, - min(host->max_blk_count, host->max_req_size / 512)); - blk_queue_max_segments(mq->queue, host->max_segs); - blk_queue_max_segment_size(mq->queue, host->max_seg_size); - } + blk_queue_bounce_limit(mq->queue, limit); + blk_queue_max_hw_sectors(mq->queue, + min(host->max_blk_count, host->max_req_size / 512)); + blk_queue_max_segments(mq->queue, host->max_segs); + blk_queue_max_segment_size(mq->queue, host->max_seg_size); sema_init(&mq->thread_sem, 1); @@ -370,56 +312,7 @@ void mmc_queue_resume(struct mmc_queue *mq) */ unsigned int mmc_queue_map_sg(struct mmc_queue *mq, struct mmc_queue_req *mqrq) { - unsigned int sg_len; - size_t buflen; - struct scatterlist *sg; struct request *req = mmc_queue_req_to_req(mqrq); - int i; - - if (!mqrq->bounce_buf) - return blk_rq_map_sg(mq->queue, req, mqrq->sg); - - sg_len = blk_rq_map_sg(mq->queue, req, mqrq->bounce_sg); - - mqrq->bounce_sg_len = sg_len; - - buflen = 0; - for_each_sg(mqrq->bounce_sg, sg, sg_len, i) - buflen += sg->length; - - sg_init_one(mqrq->sg, mqrq->bounce_buf, buflen); - - return 1; -} - -/* - * If writing, bounce the data to the buffer before the request - * is sent to the host driver - */ -void mmc_queue_bounce_pre(struct mmc_queue_req *mqrq) -{ - if (!mqrq->bounce_buf) - return; - - if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != WRITE) - return; - - sg_copy_to_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len, - mqrq->bounce_buf, mqrq->sg[0].length); -} - -/* - * If reading, bounce the data from the buffer after the request - * has been handled by the host driver - */ -void mmc_queue_bounce_post(struct mmc_queue_req *mqrq) -{ - if (!mqrq->bounce_buf) - return; - - if (rq_data_dir(mmc_queue_req_to_req(mqrq)) != READ) - return; - sg_copy_from_buffer(mqrq->bounce_sg, mqrq->bounce_sg_len, - mqrq->bounce_buf, mqrq->sg[0].length); + return blk_rq_map_sg(mq->queue, req, mqrq->sg); } diff --git a/drivers/mmc/core/queue.h b/drivers/mmc/core/queue.h index 04fc89360a7a..f18d3f656baa 100644 --- a/drivers/mmc/core/queue.h +++ b/drivers/mmc/core/queue.h @@ -49,9 +49,6 @@ enum mmc_drv_op { struct mmc_queue_req { struct mmc_blk_request brq; struct scatterlist *sg; - char *bounce_buf; - struct scatterlist *bounce_sg; - unsigned int bounce_sg_len; struct mmc_async_req areq; enum mmc_drv_op drv_op; int drv_op_result; @@ -81,11 +78,8 @@ extern int mmc_init_queue(struct mmc_queue *, struct mmc_card *, spinlock_t *, extern void mmc_cleanup_queue(struct mmc_queue *); extern void mmc_queue_suspend(struct mmc_queue *); extern void mmc_queue_resume(struct mmc_queue *); - extern unsigned int mmc_queue_map_sg(struct mmc_queue *, struct mmc_queue_req *); -extern void mmc_queue_bounce_pre(struct mmc_queue_req *); -extern void mmc_queue_bounce_post(struct mmc_queue_req *); extern int mmc_access_rpmb(struct mmc_queue *); diff --git a/drivers/mmc/host/cavium.c b/drivers/mmc/host/cavium.c index 27fb625cbcf3..fbd29f00fca0 100644 --- a/drivers/mmc/host/cavium.c +++ b/drivers/mmc/host/cavium.c @@ -1038,7 +1038,7 @@ int cvm_mmc_of_slot_probe(struct device *dev, struct cvm_mmc_host *host) */ mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | MMC_CAP_ERASE | MMC_CAP_CMD23 | MMC_CAP_POWER_OFF_CARD | - MMC_CAP_3_3V_DDR | MMC_CAP_NO_BOUNCE_BUFF; + MMC_CAP_3_3V_DDR; if (host->use_sg) mmc->max_segs = 16; diff --git a/drivers/mmc/host/meson-gx-mmc.c b/drivers/mmc/host/meson-gx-mmc.c index c885c2d4b904..85745ef179e2 100644 --- a/drivers/mmc/host/meson-gx-mmc.c +++ b/drivers/mmc/host/meson-gx-mmc.c @@ -531,8 +531,7 @@ static int meson_mmc_clk_init(struct meson_host *host) div->shift = __ffs(CLK_DIV_MASK); div->width = __builtin_popcountl(CLK_DIV_MASK); div->hw.init = &init; - div->flags = (CLK_DIVIDER_ONE_BASED | - CLK_DIVIDER_ROUND_CLOSEST); + div->flags = CLK_DIVIDER_ONE_BASED; clk = devm_clk_register(host->dev, &div->hw); if (WARN_ON(IS_ERR(clk))) @@ -717,6 +716,22 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode, static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode) { struct meson_host *host = mmc_priv(mmc); + int ret; + + /* + * If this is the initial tuning, try to get a sane Rx starting + * phase before doing the actual tuning. + */ + if (!mmc->doing_retune) { + ret = meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk); + + if (ret) + return ret; + } + + ret = meson_mmc_clk_phase_tuning(mmc, opcode, host->tx_clk); + if (ret) + return ret; return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk); } @@ -746,6 +761,11 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) case MMC_POWER_UP: if (!IS_ERR(mmc->supply.vmmc)) mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd); + + /* Reset phases */ + clk_set_phase(host->rx_clk, 0); + clk_set_phase(host->tx_clk, 270); + break; case MMC_POWER_ON: @@ -759,8 +779,6 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) host->vqmmc_enabled = true; } - /* Reset rx phase */ - clk_set_phase(host->rx_clk, 0); break; } diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 59ab194cb009..c763b404510f 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c @@ -702,11 +702,7 @@ static int pxamci_probe(struct platform_device *pdev) pxamci_init_ocr(host); - /* - * This architecture used to disable bounce buffers through its - * defconfig, now it is done at runtime as a host property. - */ - mmc->caps = MMC_CAP_NO_BOUNCE_BUFF; + mmc->caps = 0; host->cmdat = 0; if (!cpu_is_pxa25x()) { mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index d0ccc6729fd2..67d787fa3306 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -448,6 +448,8 @@ static void intel_dsm_init(struct intel_host *intel_host, struct device *dev, int err; u32 val; + intel_host->d3_retune = true; + err = __intel_dsm(intel_host, dev, INTEL_DSM_FNS, &intel_host->dsm_fns); if (err) { pr_debug("%s: DSM not supported, error %d\n", diff --git a/drivers/mmc/host/sdhci-xenon.c b/drivers/mmc/host/sdhci-xenon.c index 2eec2e652c53..0842bbc2d7ad 100644 --- a/drivers/mmc/host/sdhci-xenon.c +++ b/drivers/mmc/host/sdhci-xenon.c @@ -466,6 +466,7 @@ static int xenon_probe(struct platform_device *pdev) { struct sdhci_pltfm_host *pltfm_host; struct sdhci_host *host; + struct xenon_priv *priv; int err; host = sdhci_pltfm_init(pdev, &sdhci_xenon_pdata, @@ -474,6 +475,7 @@ static int xenon_probe(struct platform_device *pdev) return PTR_ERR(host); pltfm_host = sdhci_priv(host); + priv = sdhci_pltfm_priv(pltfm_host); /* * Link Xenon specific mmc_host_ops function, @@ -491,9 +493,20 @@ static int xenon_probe(struct platform_device *pdev) if (err) goto free_pltfm; + priv->axi_clk = devm_clk_get(&pdev->dev, "axi"); + if (IS_ERR(priv->axi_clk)) { + err = PTR_ERR(priv->axi_clk); + if (err == -EPROBE_DEFER) + goto err_clk; + } else { + err = clk_prepare_enable(priv->axi_clk); + if (err) + goto err_clk; + } + err = mmc_of_parse(host->mmc); if (err) - goto err_clk; + goto err_clk_axi; sdhci_get_of_property(pdev); @@ -502,11 +515,11 @@ static int xenon_probe(struct platform_device *pdev) /* Xenon specific dt parse */ err = xenon_probe_dt(pdev); if (err) - goto err_clk; + goto err_clk_axi; err = xenon_sdhc_prepare(host); if (err) - goto err_clk; + goto err_clk_axi; pm_runtime_get_noresume(&pdev->dev); pm_runtime_set_active(&pdev->dev); @@ -527,6 +540,8 @@ remove_sdhc: pm_runtime_disable(&pdev->dev); pm_runtime_put_noidle(&pdev->dev); xenon_sdhc_unprepare(host); +err_clk_axi: + clk_disable_unprepare(priv->axi_clk); err_clk: clk_disable_unprepare(pltfm_host->clk); free_pltfm: @@ -538,6 +553,7 @@ static int xenon_remove(struct platform_device *pdev) { struct sdhci_host *host = platform_get_drvdata(pdev); struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); + struct xenon_priv *priv = sdhci_pltfm_priv(pltfm_host); pm_runtime_get_sync(&pdev->dev); pm_runtime_disable(&pdev->dev); @@ -546,7 +562,7 @@ static int xenon_remove(struct platform_device *pdev) sdhci_remove_host(host, 0); xenon_sdhc_unprepare(host); - + clk_disable_unprepare(priv->axi_clk); clk_disable_unprepare(pltfm_host->clk); sdhci_pltfm_free(pdev); diff --git a/drivers/mmc/host/sdhci-xenon.h b/drivers/mmc/host/sdhci-xenon.h index 2bc0510c0769..9994995c7c56 100644 --- a/drivers/mmc/host/sdhci-xenon.h +++ b/drivers/mmc/host/sdhci-xenon.h @@ -83,6 +83,7 @@ struct xenon_priv { unsigned char bus_width; unsigned char timing; unsigned int clock; + struct clk *axi_clk; int phy_type; /* diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 13f0f219d8aa..a13a4896a8bd 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -182,22 +182,23 @@ /* FLEXCAN hardware feature flags * * Below is some version info we got: - * SOC Version IP-Version Glitch- [TR]WRN_INT Memory err RTR re- - * Filter? connected? detection ception in MB - * MX25 FlexCAN2 03.00.00.00 no no no no - * MX28 FlexCAN2 03.00.04.00 yes yes no no - * MX35 FlexCAN2 03.00.00.00 no no no no - * MX53 FlexCAN2 03.00.00.00 yes no no no - * MX6s FlexCAN3 10.00.12.00 yes yes no yes - * VF610 FlexCAN3 ? no yes yes yes? + * SOC Version IP-Version Glitch- [TR]WRN_INT IRQ Err Memory err RTR re- + * Filter? connected? Passive detection ception in MB + * MX25 FlexCAN2 03.00.00.00 no no ? no no + * MX28 FlexCAN2 03.00.04.00 yes yes no no no + * MX35 FlexCAN2 03.00.00.00 no no ? no no + * MX53 FlexCAN2 03.00.00.00 yes no no no no + * MX6s FlexCAN3 10.00.12.00 yes yes no no yes + * VF610 FlexCAN3 ? no yes ? yes yes? * * Some SOCs do not have the RX_WARN & TX_WARN interrupt line connected. */ -#define FLEXCAN_QUIRK_BROKEN_ERR_STATE BIT(1) /* [TR]WRN_INT not connected */ +#define FLEXCAN_QUIRK_BROKEN_WERR_STATE BIT(1) /* [TR]WRN_INT not connected */ #define FLEXCAN_QUIRK_DISABLE_RXFG BIT(2) /* Disable RX FIFO Global mask */ #define FLEXCAN_QUIRK_ENABLE_EACEN_RRS BIT(3) /* Enable EACEN and RRS bit in ctrl2 */ #define FLEXCAN_QUIRK_DISABLE_MECR BIT(4) /* Disable Memory error detection */ #define FLEXCAN_QUIRK_USE_OFF_TIMESTAMP BIT(5) /* Use timestamp based offloading */ +#define FLEXCAN_QUIRK_BROKEN_PERR_STATE BIT(6) /* No interrupt for error passive */ /* Structure of the message buffer */ struct flexcan_mb { @@ -281,14 +282,17 @@ struct flexcan_priv { }; static const struct flexcan_devtype_data fsl_p1010_devtype_data = { - .quirks = FLEXCAN_QUIRK_BROKEN_ERR_STATE, + .quirks = FLEXCAN_QUIRK_BROKEN_WERR_STATE | + FLEXCAN_QUIRK_BROKEN_PERR_STATE, }; -static const struct flexcan_devtype_data fsl_imx28_devtype_data; +static const struct flexcan_devtype_data fsl_imx28_devtype_data = { + .quirks = FLEXCAN_QUIRK_BROKEN_PERR_STATE, +}; static const struct flexcan_devtype_data fsl_imx6q_devtype_data = { .quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS | - FLEXCAN_QUIRK_USE_OFF_TIMESTAMP, + FLEXCAN_QUIRK_USE_OFF_TIMESTAMP | FLEXCAN_QUIRK_BROKEN_PERR_STATE, }; static const struct flexcan_devtype_data fsl_vf610_devtype_data = { @@ -335,6 +339,22 @@ static inline void flexcan_write(u32 val, void __iomem *addr) } #endif +static inline void flexcan_error_irq_enable(const struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs = priv->regs; + u32 reg_ctrl = (priv->reg_ctrl_default | FLEXCAN_CTRL_ERR_MSK); + + flexcan_write(reg_ctrl, ®s->ctrl); +} + +static inline void flexcan_error_irq_disable(const struct flexcan_priv *priv) +{ + struct flexcan_regs __iomem *regs = priv->regs; + u32 reg_ctrl = (priv->reg_ctrl_default & ~FLEXCAN_CTRL_ERR_MSK); + + flexcan_write(reg_ctrl, ®s->ctrl); +} + static inline int flexcan_transceiver_enable(const struct flexcan_priv *priv) { if (!priv->reg_xceiver) @@ -713,6 +733,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) struct flexcan_regs __iomem *regs = priv->regs; irqreturn_t handled = IRQ_NONE; u32 reg_iflag1, reg_esr; + enum can_state last_state = priv->can.state; reg_iflag1 = flexcan_read(®s->iflag1); @@ -765,8 +786,10 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) flexcan_write(reg_esr & FLEXCAN_ESR_ALL_INT, ®s->esr); } - /* state change interrupt */ - if (reg_esr & FLEXCAN_ESR_ERR_STATE) + /* state change interrupt or broken error state quirk fix is enabled */ + if ((reg_esr & FLEXCAN_ESR_ERR_STATE) || + (priv->devtype_data->quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE | + FLEXCAN_QUIRK_BROKEN_PERR_STATE))) flexcan_irq_state(dev, reg_esr); /* bus error IRQ - handle if bus error reporting is activated */ @@ -774,6 +797,44 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) flexcan_irq_bus_err(dev, reg_esr); + /* availability of error interrupt among state transitions in case + * bus error reporting is de-activated and + * FLEXCAN_QUIRK_BROKEN_PERR_STATE is enabled: + * +--------------------------------------------------------------+ + * | +----------------------------------------------+ [stopped / | + * | | | sleeping] -+ + * +-+-> active <-> warning <-> passive -> bus off -+ + * ___________^^^^^^^^^^^^_______________________________ + * disabled(1) enabled disabled + * + * (1): enabled if FLEXCAN_QUIRK_BROKEN_WERR_STATE is enabled + */ + if ((last_state != priv->can.state) && + (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE) && + !(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) { + switch (priv->can.state) { + case CAN_STATE_ERROR_ACTIVE: + if (priv->devtype_data->quirks & + FLEXCAN_QUIRK_BROKEN_WERR_STATE) + flexcan_error_irq_enable(priv); + else + flexcan_error_irq_disable(priv); + break; + + case CAN_STATE_ERROR_WARNING: + flexcan_error_irq_enable(priv); + break; + + case CAN_STATE_ERROR_PASSIVE: + case CAN_STATE_BUS_OFF: + flexcan_error_irq_disable(priv); + break; + + default: + break; + } + } + return handled; } @@ -887,7 +948,7 @@ static int flexcan_chip_start(struct net_device *dev) * on most Flexcan cores, too. Otherwise we don't get * any error warning or passive interrupts. */ - if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_ERR_STATE || + if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE || priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; else diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 68ef0a4cd821..b0c80859f746 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -342,7 +342,7 @@ static int sun4i_can_start(struct net_device *dev) /* enter the selected mode */ mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); - if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK) + if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) mod_reg_val |= SUN4I_MSEL_LOOPBACK_MODE; else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) mod_reg_val |= SUN4I_MSEL_LISTEN_ONLY_MODE; @@ -811,7 +811,6 @@ static int sun4ican_probe(struct platform_device *pdev) priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_LOOPBACK | - CAN_CTRLMODE_PRESUME_ACK | CAN_CTRLMODE_3_SAMPLES; priv->base = addr; priv->clk = clk; diff --git a/drivers/net/can/usb/esd_usb2.c b/drivers/net/can/usb/esd_usb2.c index be928ce62d32..9fdb0f0bfa06 100644 --- a/drivers/net/can/usb/esd_usb2.c +++ b/drivers/net/can/usb/esd_usb2.c @@ -333,7 +333,7 @@ static void esd_usb2_rx_can_msg(struct esd_usb2_net_priv *priv, } cf->can_id = id & ESD_IDMASK; - cf->can_dlc = get_can_dlc(msg->msg.rx.dlc); + cf->can_dlc = get_can_dlc(msg->msg.rx.dlc & ~ESD_RTR); if (id & ESD_EXTID) cf->can_id |= CAN_EFF_FLAG; diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c index afcc1312dbaf..68ac3e88a8ce 100644 --- a/drivers/net/can/usb/gs_usb.c +++ b/drivers/net/can/usb/gs_usb.c @@ -375,6 +375,8 @@ static void gs_usb_receive_bulk_callback(struct urb *urb) gs_free_tx_context(txc); + atomic_dec(&dev->active_tx_urbs); + netif_wake_queue(netdev); } @@ -463,14 +465,6 @@ static void gs_usb_xmit_callback(struct urb *urb) urb->transfer_buffer_length, urb->transfer_buffer, urb->transfer_dma); - - atomic_dec(&dev->active_tx_urbs); - - if (!netif_device_present(netdev)) - return; - - if (netif_queue_stopped(netdev)) - netif_wake_queue(netdev); } static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb, diff --git a/drivers/net/can/usb/kvaser_usb.c b/drivers/net/can/usb/kvaser_usb.c index 18cc529fb807..9b18d96ef526 100644 --- a/drivers/net/can/usb/kvaser_usb.c +++ b/drivers/net/can/usb/kvaser_usb.c @@ -137,6 +137,7 @@ static inline bool kvaser_is_usbcan(const struct usb_device_id *id) #define CMD_RESET_ERROR_COUNTER 49 #define CMD_TX_ACKNOWLEDGE 50 #define CMD_CAN_ERROR_EVENT 51 +#define CMD_FLUSH_QUEUE_REPLY 68 #define CMD_LEAF_USB_THROTTLE 77 #define CMD_LEAF_LOG_MESSAGE 106 @@ -1301,6 +1302,11 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev, goto warn; break; + case CMD_FLUSH_QUEUE_REPLY: + if (dev->family != KVASER_LEAF) + goto warn; + break; + default: warn: dev_warn(dev->udev->dev.parent, "Unhandled message (%d)\n", msg->id); @@ -1609,7 +1615,8 @@ static int kvaser_usb_close(struct net_device *netdev) if (err) netdev_warn(netdev, "Cannot flush queue, error %d\n", err); - if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel)) + err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel); + if (err) netdev_warn(netdev, "Cannot reset card, error %d\n", err); err = kvaser_usb_stop_chip(priv); diff --git a/drivers/net/dsa/mv88e6060.c b/drivers/net/dsa/mv88e6060.c index dce7fa57eb55..f123ed57630d 100644 --- a/drivers/net/dsa/mv88e6060.c +++ b/drivers/net/dsa/mv88e6060.c @@ -214,8 +214,14 @@ static int mv88e6060_setup(struct dsa_switch *ds) static int mv88e6060_set_addr(struct dsa_switch *ds, u8 *addr) { - /* Use the same MAC Address as FD Pause frames for all ports */ - REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, (addr[0] << 9) | addr[1]); + u16 val = addr[0] << 8 | addr[1]; + + /* The multicast bit is always transmitted as a zero, so the switch uses + * bit 8 for "DiffAddr", where 0 means all ports transmit the same SA. + */ + val &= 0xfeff; + + REG_WRITE(REG_GLOBAL, GLOBAL_MAC_01, val); REG_WRITE(REG_GLOBAL, GLOBAL_MAC_23, (addr[2] << 8) | addr[3]); REG_WRITE(REG_GLOBAL, GLOBAL_MAC_45, (addr[4] << 8) | addr[5]); diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index c6678aa9b4ef..d74c7335c512 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1100,6 +1100,10 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, }; int i, err; + /* DSA and CPU ports have to be members of multiple vlans */ + if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port)) + return 0; + if (!vid_begin) return -EOPNOTSUPP; @@ -3947,7 +3951,9 @@ static void mv88e6xxx_remove(struct mdio_device *mdiodev) if (chip->irq > 0) { if (chip->info->g2_irqs > 0) mv88e6xxx_g2_irq_free(chip); + mutex_lock(&chip->reg_lock); mv88e6xxx_g1_irq_free(chip); + mutex_unlock(&chip->reg_lock); } } diff --git a/drivers/net/ethernet/amazon/ena/ena_ethtool.c b/drivers/net/ethernet/amazon/ena/ena_ethtool.c index b1212debc2e1..967020fb26ee 100644 --- a/drivers/net/ethernet/amazon/ena/ena_ethtool.c +++ b/drivers/net/ethernet/amazon/ena/ena_ethtool.c @@ -742,8 +742,8 @@ static void ena_get_channels(struct net_device *netdev, { struct ena_adapter *adapter = netdev_priv(netdev); - channels->max_rx = ENA_MAX_NUM_IO_QUEUES; - channels->max_tx = ENA_MAX_NUM_IO_QUEUES; + channels->max_rx = adapter->num_queues; + channels->max_tx = adapter->num_queues; channels->max_other = 0; channels->max_combined = 0; channels->rx_count = adapter->num_queues; diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index f7dc22f65d9f..c6bd5e24005d 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -966,7 +966,7 @@ static inline void ena_rx_checksum(struct ena_ring *rx_ring, u64_stats_update_begin(&rx_ring->syncp); rx_ring->rx_stats.bad_csum++; u64_stats_update_end(&rx_ring->syncp); - netif_err(rx_ring->adapter, rx_err, rx_ring->netdev, + netif_dbg(rx_ring->adapter, rx_err, rx_ring->netdev, "RX IPv4 header checksum error\n"); return; } @@ -979,7 +979,7 @@ static inline void ena_rx_checksum(struct ena_ring *rx_ring, u64_stats_update_begin(&rx_ring->syncp); rx_ring->rx_stats.bad_csum++; u64_stats_update_end(&rx_ring->syncp); - netif_err(rx_ring->adapter, rx_err, rx_ring->netdev, + netif_dbg(rx_ring->adapter, rx_err, rx_ring->netdev, "RX L4 checksum error\n"); skb->ip_summed = CHECKSUM_NONE; return; @@ -3064,7 +3064,8 @@ static void ena_release_bars(struct ena_com_dev *ena_dev, struct pci_dev *pdev) if (ena_dev->mem_bar) devm_iounmap(&pdev->dev, ena_dev->mem_bar); - devm_iounmap(&pdev->dev, ena_dev->reg_bar); + if (ena_dev->reg_bar) + devm_iounmap(&pdev->dev, ena_dev->reg_bar); release_bars = pci_select_bars(pdev, IORESOURCE_MEM) & ENA_BAR_MASK; pci_release_selected_regions(pdev, release_bars); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h index 214986436ece..57e796870595 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_cfg.h @@ -22,8 +22,12 @@ #define AQ_CFG_FORCE_LEGACY_INT 0U -#define AQ_CFG_IS_INTERRUPT_MODERATION_DEF 1U -#define AQ_CFG_INTERRUPT_MODERATION_RATE_DEF 0xFFFFU +#define AQ_CFG_INTERRUPT_MODERATION_OFF 0 +#define AQ_CFG_INTERRUPT_MODERATION_ON 1 +#define AQ_CFG_INTERRUPT_MODERATION_AUTO 0xFFFFU + +#define AQ_CFG_INTERRUPT_MODERATION_USEC_MAX (0x1FF * 2) + #define AQ_CFG_IRQ_MASK 0x1FFU #define AQ_CFG_VECS_MAX 8U @@ -51,6 +55,10 @@ #define AQ_CFG_SKB_FRAGS_MAX 32U +/* Number of descriptors available in one ring to resume this ring queue + */ +#define AQ_CFG_RESTART_DESC_THRES (AQ_CFG_SKB_FRAGS_MAX * 2) + #define AQ_CFG_NAPI_WEIGHT 64U #define AQ_CFG_MULTICAST_ADDRESS_MAX 32U diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c index a761e91471df..d5e99b468870 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c @@ -56,10 +56,6 @@ aq_ethtool_set_link_ksettings(struct net_device *ndev, return aq_nic_set_link_ksettings(aq_nic, cmd); } -/* there "5U" is number of queue[#] stats lines (InPackets+...+InErrors) */ -static const unsigned int aq_ethtool_stat_queue_lines = 5U; -static const unsigned int aq_ethtool_stat_queue_chars = - 5U * ETH_GSTRING_LEN; static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = { "InPackets", "InUCast", @@ -83,56 +79,26 @@ static const char aq_ethtool_stat_names[][ETH_GSTRING_LEN] = { "InOctetsDma", "OutOctetsDma", "InDroppedDma", - "Queue[0] InPackets", - "Queue[0] OutPackets", - "Queue[0] InJumboPackets", - "Queue[0] InLroPackets", - "Queue[0] InErrors", - "Queue[1] InPackets", - "Queue[1] OutPackets", - "Queue[1] InJumboPackets", - "Queue[1] InLroPackets", - "Queue[1] InErrors", - "Queue[2] InPackets", - "Queue[2] OutPackets", - "Queue[2] InJumboPackets", - "Queue[2] InLroPackets", - "Queue[2] InErrors", - "Queue[3] InPackets", - "Queue[3] OutPackets", - "Queue[3] InJumboPackets", - "Queue[3] InLroPackets", - "Queue[3] InErrors", - "Queue[4] InPackets", - "Queue[4] OutPackets", - "Queue[4] InJumboPackets", - "Queue[4] InLroPackets", - "Queue[4] InErrors", - "Queue[5] InPackets", - "Queue[5] OutPackets", - "Queue[5] InJumboPackets", - "Queue[5] InLroPackets", - "Queue[5] InErrors", - "Queue[6] InPackets", - "Queue[6] OutPackets", - "Queue[6] InJumboPackets", - "Queue[6] InLroPackets", - "Queue[6] InErrors", - "Queue[7] InPackets", - "Queue[7] OutPackets", - "Queue[7] InJumboPackets", - "Queue[7] InLroPackets", - "Queue[7] InErrors", +}; + +static const char aq_ethtool_queue_stat_names[][ETH_GSTRING_LEN] = { + "Queue[%d] InPackets", + "Queue[%d] OutPackets", + "Queue[%d] Restarts", + "Queue[%d] InJumboPackets", + "Queue[%d] InLroPackets", + "Queue[%d] InErrors", }; static void aq_ethtool_stats(struct net_device *ndev, struct ethtool_stats *stats, u64 *data) { struct aq_nic_s *aq_nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); -/* ASSERT: Need add lines to aq_ethtool_stat_names if AQ_CFG_VECS_MAX > 8 */ - BUILD_BUG_ON(AQ_CFG_VECS_MAX > 8); - memset(data, 0, ARRAY_SIZE(aq_ethtool_stat_names) * sizeof(u64)); + memset(data, 0, (ARRAY_SIZE(aq_ethtool_stat_names) + + ARRAY_SIZE(aq_ethtool_queue_stat_names) * + cfg->vecs) * sizeof(u64)); aq_nic_get_stats(aq_nic, data); } @@ -154,8 +120,8 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev, strlcpy(drvinfo->bus_info, pdev ? pci_name(pdev) : "", sizeof(drvinfo->bus_info)); - drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) - - (AQ_CFG_VECS_MAX - cfg->vecs) * aq_ethtool_stat_queue_lines; + drvinfo->n_stats = ARRAY_SIZE(aq_ethtool_stat_names) + + cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); drvinfo->testinfo_len = 0; drvinfo->regdump_len = regs_count; drvinfo->eedump_len = 0; @@ -164,14 +130,25 @@ static void aq_ethtool_get_drvinfo(struct net_device *ndev, static void aq_ethtool_get_strings(struct net_device *ndev, u32 stringset, u8 *data) { + int i, si; struct aq_nic_s *aq_nic = netdev_priv(ndev); struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); - - if (stringset == ETH_SS_STATS) - memcpy(data, *aq_ethtool_stat_names, - sizeof(aq_ethtool_stat_names) - - (AQ_CFG_VECS_MAX - cfg->vecs) * - aq_ethtool_stat_queue_chars); + u8 *p = data; + + if (stringset == ETH_SS_STATS) { + memcpy(p, *aq_ethtool_stat_names, + sizeof(aq_ethtool_stat_names)); + p = p + sizeof(aq_ethtool_stat_names); + for (i = 0; i < cfg->vecs; i++) { + for (si = 0; + si < ARRAY_SIZE(aq_ethtool_queue_stat_names); + si++) { + snprintf(p, ETH_GSTRING_LEN, + aq_ethtool_queue_stat_names[si], i); + p += ETH_GSTRING_LEN; + } + } + } } static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) @@ -182,9 +159,8 @@ static int aq_ethtool_get_sset_count(struct net_device *ndev, int stringset) switch (stringset) { case ETH_SS_STATS: - ret = ARRAY_SIZE(aq_ethtool_stat_names) - - (AQ_CFG_VECS_MAX - cfg->vecs) * - aq_ethtool_stat_queue_lines; + ret = ARRAY_SIZE(aq_ethtool_stat_names) + + cfg->vecs * ARRAY_SIZE(aq_ethtool_queue_stat_names); break; default: ret = -EOPNOTSUPP; @@ -245,6 +221,69 @@ static int aq_ethtool_get_rxnfc(struct net_device *ndev, return err; } +int aq_ethtool_get_coalesce(struct net_device *ndev, + struct ethtool_coalesce *coal) +{ + struct aq_nic_s *aq_nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); + + if (cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON || + cfg->itr == AQ_CFG_INTERRUPT_MODERATION_AUTO) { + coal->rx_coalesce_usecs = cfg->rx_itr; + coal->tx_coalesce_usecs = cfg->tx_itr; + coal->rx_max_coalesced_frames = 0; + coal->tx_max_coalesced_frames = 0; + } else { + coal->rx_coalesce_usecs = 0; + coal->tx_coalesce_usecs = 0; + coal->rx_max_coalesced_frames = 1; + coal->tx_max_coalesced_frames = 1; + } + return 0; +} + +int aq_ethtool_set_coalesce(struct net_device *ndev, + struct ethtool_coalesce *coal) +{ + struct aq_nic_s *aq_nic = netdev_priv(ndev); + struct aq_nic_cfg_s *cfg = aq_nic_get_cfg(aq_nic); + + /* This is not yet supported + */ + if (coal->use_adaptive_rx_coalesce || coal->use_adaptive_tx_coalesce) + return -EOPNOTSUPP; + + /* Atlantic only supports timing based coalescing + */ + if (coal->rx_max_coalesced_frames > 1 || + coal->rx_coalesce_usecs_irq || + coal->rx_max_coalesced_frames_irq) + return -EOPNOTSUPP; + + if (coal->tx_max_coalesced_frames > 1 || + coal->tx_coalesce_usecs_irq || + coal->tx_max_coalesced_frames_irq) + return -EOPNOTSUPP; + + /* We do not support frame counting. Check this + */ + if (!(coal->rx_max_coalesced_frames == !coal->rx_coalesce_usecs)) + return -EOPNOTSUPP; + if (!(coal->tx_max_coalesced_frames == !coal->tx_coalesce_usecs)) + return -EOPNOTSUPP; + + if (coal->rx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX || + coal->tx_coalesce_usecs > AQ_CFG_INTERRUPT_MODERATION_USEC_MAX) + return -EINVAL; + + cfg->itr = AQ_CFG_INTERRUPT_MODERATION_ON; + + cfg->rx_itr = coal->rx_coalesce_usecs; + cfg->tx_itr = coal->tx_coalesce_usecs; + + return aq_nic_update_interrupt_moderation_settings(aq_nic); +} + const struct ethtool_ops aq_ethtool_ops = { .get_link = aq_ethtool_get_link, .get_regs_len = aq_ethtool_get_regs_len, @@ -259,4 +298,6 @@ const struct ethtool_ops aq_ethtool_ops = { .get_ethtool_stats = aq_ethtool_stats, .get_link_ksettings = aq_ethtool_get_link_ksettings, .set_link_ksettings = aq_ethtool_set_link_ksettings, + .get_coalesce = aq_ethtool_get_coalesce, + .set_coalesce = aq_ethtool_set_coalesce, }; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index bf9b3f020e10..0207927dc8a6 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -151,8 +151,7 @@ struct aq_hw_ops { [ETH_ALEN], u32 count); - int (*hw_interrupt_moderation_set)(struct aq_hw_s *self, - bool itr_enabled); + int (*hw_interrupt_moderation_set)(struct aq_hw_s *self); int (*hw_rss_set)(struct aq_hw_s *self, struct aq_rss_parameters *rss_params); @@ -163,6 +162,8 @@ struct aq_hw_ops { int (*hw_get_regs)(struct aq_hw_s *self, struct aq_hw_caps_s *aq_hw_caps, u32 *regs_buff); + int (*hw_update_stats)(struct aq_hw_s *self); + int (*hw_get_hw_stats)(struct aq_hw_s *self, u64 *data, unsigned int *p_count); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 6ac9e2602d6d..483e97691eea 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -16,6 +16,7 @@ #include "aq_pci_func.h" #include "aq_nic_internal.h" +#include <linux/moduleparam.h> #include <linux/netdevice.h> #include <linux/etherdevice.h> #include <linux/timer.h> @@ -24,6 +25,18 @@ #include <linux/tcp.h> #include <net/ip.h> +static unsigned int aq_itr = AQ_CFG_INTERRUPT_MODERATION_AUTO; +module_param_named(aq_itr, aq_itr, uint, 0644); +MODULE_PARM_DESC(aq_itr, "Interrupt throttling mode"); + +static unsigned int aq_itr_tx; +module_param_named(aq_itr_tx, aq_itr_tx, uint, 0644); +MODULE_PARM_DESC(aq_itr_tx, "TX interrupt throttle rate"); + +static unsigned int aq_itr_rx; +module_param_named(aq_itr_rx, aq_itr_rx, uint, 0644); +MODULE_PARM_DESC(aq_itr_rx, "RX interrupt throttle rate"); + static void aq_nic_rss_init(struct aq_nic_s *self, unsigned int num_rss_queues) { struct aq_nic_cfg_s *cfg = &self->aq_nic_cfg; @@ -61,9 +74,9 @@ static void aq_nic_cfg_init_defaults(struct aq_nic_s *self) cfg->is_polling = AQ_CFG_IS_POLLING_DEF; - cfg->is_interrupt_moderation = AQ_CFG_IS_INTERRUPT_MODERATION_DEF; - cfg->itr = cfg->is_interrupt_moderation ? - AQ_CFG_INTERRUPT_MODERATION_RATE_DEF : 0U; + cfg->itr = aq_itr; + cfg->tx_itr = aq_itr_tx; + cfg->rx_itr = aq_itr_rx; cfg->is_rss = AQ_CFG_IS_RSS_DEF; cfg->num_rss_queues = AQ_CFG_NUM_RSS_QUEUES_DEF; @@ -119,6 +132,37 @@ int aq_nic_cfg_start(struct aq_nic_s *self) return 0; } +static int aq_nic_update_link_status(struct aq_nic_s *self) +{ + int err = self->aq_hw_ops.hw_get_link_status(self->aq_hw); + + if (err) + return err; + + if (self->link_status.mbps != self->aq_hw->aq_link_status.mbps) { + pr_info("%s: link change old %d new %d\n", + AQ_CFG_DRV_NAME, self->link_status.mbps, + self->aq_hw->aq_link_status.mbps); + aq_nic_update_interrupt_moderation_settings(self); + } + + self->link_status = self->aq_hw->aq_link_status; + if (!netif_carrier_ok(self->ndev) && self->link_status.mbps) { + aq_utils_obj_set(&self->header.flags, + AQ_NIC_FLAG_STARTED); + aq_utils_obj_clear(&self->header.flags, + AQ_NIC_LINK_DOWN); + netif_carrier_on(self->ndev); + netif_tx_wake_all_queues(self->ndev); + } + if (netif_carrier_ok(self->ndev) && !self->link_status.mbps) { + netif_carrier_off(self->ndev); + netif_tx_disable(self->ndev); + aq_utils_obj_set(&self->header.flags, AQ_NIC_LINK_DOWN); + } + return 0; +} + static void aq_nic_service_timer_cb(unsigned long param) { struct aq_nic_s *self = (struct aq_nic_s *)param; @@ -131,25 +175,12 @@ static void aq_nic_service_timer_cb(unsigned long param) if (aq_utils_obj_test(&self->header.flags, AQ_NIC_FLAGS_IS_NOT_READY)) goto err_exit; - err = self->aq_hw_ops.hw_get_link_status(self->aq_hw); - if (err < 0) + err = aq_nic_update_link_status(self); + if (err) goto err_exit; - self->link_status = self->aq_hw->aq_link_status; - - self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw, - self->aq_nic_cfg.is_interrupt_moderation); - - if (self->link_status.mbps) { - aq_utils_obj_set(&self->header.flags, - AQ_NIC_FLAG_STARTED); - aq_utils_obj_clear(&self->header.flags, - AQ_NIC_LINK_DOWN); - netif_carrier_on(self->ndev); - } else { - netif_carrier_off(self->ndev); - aq_utils_obj_set(&self->header.flags, AQ_NIC_LINK_DOWN); - } + if (self->aq_hw_ops.hw_update_stats) + self->aq_hw_ops.hw_update_stats(self->aq_hw); memset(&stats_rx, 0U, sizeof(struct aq_ring_stats_rx_s)); memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); @@ -214,7 +245,6 @@ struct aq_nic_s *aq_nic_alloc_cold(const struct net_device_ops *ndev_ops, SET_NETDEV_DEV(ndev, dev); ndev->if_port = port; - ndev->min_mtu = ETH_MIN_MTU; self->ndev = ndev; self->aq_pci_func = aq_pci_func; @@ -241,7 +271,6 @@ err_exit: int aq_nic_ndev_register(struct aq_nic_s *self) { int err = 0; - unsigned int i = 0U; if (!self->ndev) { err = -EINVAL; @@ -263,8 +292,7 @@ int aq_nic_ndev_register(struct aq_nic_s *self) netif_carrier_off(self->ndev); - for (i = AQ_CFG_VECS_MAX; i--;) - aq_nic_ndev_queue_stop(self, i); + netif_tx_disable(self->ndev); err = register_netdev(self->ndev); if (err < 0) @@ -283,6 +311,7 @@ int aq_nic_ndev_init(struct aq_nic_s *self) self->ndev->features = aq_hw_caps->hw_features; self->ndev->priv_flags = aq_hw_caps->hw_priv_flags; self->ndev->mtu = aq_nic_cfg->mtu - ETH_HLEN; + self->ndev->max_mtu = self->aq_hw_caps.mtu - ETH_FCS_LEN - ETH_HLEN; return 0; } @@ -318,12 +347,9 @@ struct aq_nic_s *aq_nic_alloc_hot(struct net_device *ndev) err = -EINVAL; goto err_exit; } - if (netif_running(ndev)) { - unsigned int i; - - for (i = AQ_CFG_VECS_MAX; i--;) - netif_stop_subqueue(ndev, i); - } + if (netif_running(ndev)) + netif_tx_disable(ndev); + netif_carrier_off(self->ndev); for (self->aq_vecs = 0; self->aq_vecs < self->aq_nic_cfg.vecs; self->aq_vecs++) { @@ -383,16 +409,6 @@ err_exit: return err; } -void aq_nic_ndev_queue_start(struct aq_nic_s *self, unsigned int idx) -{ - netif_start_subqueue(self->ndev, idx); -} - -void aq_nic_ndev_queue_stop(struct aq_nic_s *self, unsigned int idx) -{ - netif_stop_subqueue(self->ndev, idx); -} - int aq_nic_start(struct aq_nic_s *self) { struct aq_vec_s *aq_vec = NULL; @@ -421,9 +437,8 @@ int aq_nic_start(struct aq_nic_s *self) if (err < 0) goto err_exit; - err = self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw, - self->aq_nic_cfg.is_interrupt_moderation); - if (err < 0) + err = aq_nic_update_interrupt_moderation_settings(self); + if (err) goto err_exit; setup_timer(&self->service_timer, &aq_nic_service_timer_cb, (unsigned long)self); @@ -451,10 +466,6 @@ int aq_nic_start(struct aq_nic_s *self) goto err_exit; } - for (i = 0U, aq_vec = self->aq_vec[0]; - self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) - aq_nic_ndev_queue_start(self, i); - err = netif_set_real_num_tx_queues(self->ndev, self->aq_vecs); if (err < 0) goto err_exit; @@ -463,6 +474,8 @@ int aq_nic_start(struct aq_nic_s *self) if (err < 0) goto err_exit; + netif_tx_start_all_queues(self->ndev); + err_exit: return err; } @@ -475,6 +488,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self, unsigned int nr_frags = skb_shinfo(skb)->nr_frags; unsigned int frag_count = 0U; unsigned int dx = ring->sw_tail; + struct aq_ring_buff_s *first = NULL; struct aq_ring_buff_s *dx_buff = &ring->buff_ring[dx]; if (unlikely(skb_is_gso(skb))) { @@ -485,6 +499,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self, dx_buff->len_l4 = tcp_hdrlen(skb); dx_buff->mss = skb_shinfo(skb)->gso_size; dx_buff->is_txc = 1U; + dx_buff->eop_index = 0xffffU; dx_buff->is_ipv6 = (ip_hdr(skb)->version == 6) ? 1U : 0U; @@ -504,6 +519,7 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self, if (unlikely(dma_mapping_error(aq_nic_get_dev(self), dx_buff->pa))) goto exit; + first = dx_buff; dx_buff->len_pkt = skb->len; dx_buff->is_sop = 1U; dx_buff->is_mapped = 1U; @@ -532,40 +548,46 @@ static unsigned int aq_nic_map_skb(struct aq_nic_s *self, for (; nr_frags--; ++frag_count) { unsigned int frag_len = 0U; + unsigned int buff_offset = 0U; + unsigned int buff_size = 0U; dma_addr_t frag_pa; skb_frag_t *frag = &skb_shinfo(skb)->frags[frag_count]; frag_len = skb_frag_size(frag); - frag_pa = skb_frag_dma_map(aq_nic_get_dev(self), frag, 0, - frag_len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(aq_nic_get_dev(self), frag_pa))) - goto mapping_error; + while (frag_len) { + if (frag_len > AQ_CFG_TX_FRAME_MAX) + buff_size = AQ_CFG_TX_FRAME_MAX; + else + buff_size = frag_len; + + frag_pa = skb_frag_dma_map(aq_nic_get_dev(self), + frag, + buff_offset, + buff_size, + DMA_TO_DEVICE); + + if (unlikely(dma_mapping_error(aq_nic_get_dev(self), + frag_pa))) + goto mapping_error; - while (frag_len > AQ_CFG_TX_FRAME_MAX) { dx = aq_ring_next_dx(ring, dx); dx_buff = &ring->buff_ring[dx]; dx_buff->flags = 0U; - dx_buff->len = AQ_CFG_TX_FRAME_MAX; + dx_buff->len = buff_size; dx_buff->pa = frag_pa; dx_buff->is_mapped = 1U; + dx_buff->eop_index = 0xffffU; + + frag_len -= buff_size; + buff_offset += buff_size; - frag_len -= AQ_CFG_TX_FRAME_MAX; - frag_pa += AQ_CFG_TX_FRAME_MAX; ++ret; } - - dx = aq_ring_next_dx(ring, dx); - dx_buff = &ring->buff_ring[dx]; - - dx_buff->flags = 0U; - dx_buff->len = frag_len; - dx_buff->pa = frag_pa; - dx_buff->is_mapped = 1U; - ++ret; } + first->eop_index = dx; dx_buff->is_eop = 1U; dx_buff->skb = skb; goto exit; @@ -602,7 +624,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) unsigned int vec = skb->queue_mapping % self->aq_nic_cfg.vecs; unsigned int tc = 0U; int err = NETDEV_TX_OK; - bool is_nic_in_bad_state; frags = skb_shinfo(skb)->nr_frags + 1; @@ -613,13 +634,10 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) goto err_exit; } - is_nic_in_bad_state = aq_utils_obj_test(&self->header.flags, - AQ_NIC_FLAGS_IS_NOT_TX_READY) || - (aq_ring_avail_dx(ring) < - AQ_CFG_SKB_FRAGS_MAX); + aq_ring_update_queue_state(ring); - if (is_nic_in_bad_state) { - aq_nic_ndev_queue_stop(self, ring->idx); + /* Above status update may stop the queue. Check this. */ + if (__netif_subqueue_stopped(self->ndev, ring->idx)) { err = NETDEV_TX_BUSY; goto err_exit; } @@ -631,9 +649,6 @@ int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb) ring, frags); if (err >= 0) { - if (aq_ring_avail_dx(ring) < AQ_CFG_SKB_FRAGS_MAX + 1) - aq_nic_ndev_queue_stop(self, ring->idx); - ++ring->stats.tx.packets; ring->stats.tx.bytes += skb->len; } @@ -645,6 +660,11 @@ err_exit: return err; } +int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self) +{ + return self->aq_hw_ops.hw_interrupt_moderation_set(self->aq_hw); +} + int aq_nic_set_packet_filter(struct aq_nic_s *self, unsigned int flags) { int err = 0; @@ -693,16 +713,9 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev) int aq_nic_set_mtu(struct aq_nic_s *self, int new_mtu) { - int err = 0; - - if (new_mtu > self->aq_hw_caps.mtu) { - err = -EINVAL; - goto err_exit; - } self->aq_nic_cfg.mtu = new_mtu; -err_exit: - return err; + return 0; } int aq_nic_set_mac(struct aq_nic_s *self, struct net_device *ndev) @@ -905,9 +918,8 @@ int aq_nic_stop(struct aq_nic_s *self) struct aq_vec_s *aq_vec = NULL; unsigned int i = 0U; - for (i = 0U, aq_vec = self->aq_vec[0]; - self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) - aq_nic_ndev_queue_stop(self, i); + netif_tx_disable(self->ndev); + netif_carrier_off(self->ndev); del_timer_sync(&self->service_timer); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 7fc2a5ecb2b7..4309983acdd6 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -40,6 +40,8 @@ struct aq_nic_cfg_s { u32 vecs; /* vecs==allocated irqs */ u32 irq_type; u32 itr; + u16 rx_itr; + u16 tx_itr; u32 num_rss_queues; u32 mtu; u32 ucp_0x364; @@ -49,7 +51,6 @@ struct aq_nic_cfg_s { u16 is_mc_list_enabled; u16 mc_list_count; bool is_autoneg; - bool is_interrupt_moderation; bool is_polling; bool is_rss; bool is_lro; @@ -83,8 +84,6 @@ struct net_device *aq_nic_get_ndev(struct aq_nic_s *self); int aq_nic_init(struct aq_nic_s *self); int aq_nic_cfg_start(struct aq_nic_s *self); int aq_nic_ndev_register(struct aq_nic_s *self); -void aq_nic_ndev_queue_start(struct aq_nic_s *self, unsigned int idx); -void aq_nic_ndev_queue_stop(struct aq_nic_s *self, unsigned int idx); void aq_nic_ndev_free(struct aq_nic_s *self); int aq_nic_start(struct aq_nic_s *self); int aq_nic_xmit(struct aq_nic_s *self, struct sk_buff *skb); @@ -106,5 +105,6 @@ int aq_nic_set_link_ksettings(struct aq_nic_s *self, struct aq_nic_cfg_s *aq_nic_get_cfg(struct aq_nic_s *self); u32 aq_nic_get_fw_version(struct aq_nic_s *self); int aq_nic_change_pm_state(struct aq_nic_s *self, pm_message_t *pm_msg); +int aq_nic_update_interrupt_moderation_settings(struct aq_nic_s *self); #endif /* AQ_NIC_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c index 4c6c882c6a1c..cadaa646c89f 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_pci_func.c @@ -85,6 +85,7 @@ int aq_pci_func_init(struct aq_pci_func_s *self) int err = 0; unsigned int bar = 0U; unsigned int port = 0U; + unsigned int numvecs = 0U; err = pci_enable_device(self->pdev); if (err < 0) @@ -142,10 +143,12 @@ int aq_pci_func_init(struct aq_pci_func_s *self) } } - /*enable interrupts */ + numvecs = min((u8)AQ_CFG_VECS_DEF, self->aq_hw_caps.msix_irqs); + numvecs = min(numvecs, num_online_cpus()); + + /* enable interrupts */ #if !AQ_CFG_FORCE_LEGACY_INT - err = pci_alloc_irq_vectors(self->pdev, self->aq_hw_caps.msix_irqs, - self->aq_hw_caps.msix_irqs, PCI_IRQ_MSIX); + err = pci_alloc_irq_vectors(self->pdev, numvecs, numvecs, PCI_IRQ_MSIX); if (err < 0) { err = pci_alloc_irq_vectors(self->pdev, 1, 1, @@ -153,7 +156,7 @@ int aq_pci_func_init(struct aq_pci_func_s *self) if (err < 0) goto err_exit; } -#endif +#endif /* AQ_CFG_FORCE_LEGACY_INT */ /* net device init */ for (port = 0; port < self->ports; ++port) { @@ -265,6 +268,9 @@ void aq_pci_func_free(struct aq_pci_func_s *self) aq_nic_ndev_free(self->port[port]); } + if (self->mmio) + iounmap(self->mmio); + kfree(self); err_exit:; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 4eee1996a825..0654e0c76bc2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -104,6 +104,38 @@ int aq_ring_init(struct aq_ring_s *self) return 0; } +static inline bool aq_ring_dx_in_range(unsigned int h, unsigned int i, + unsigned int t) +{ + return (h < t) ? ((h < i) && (i < t)) : ((h < i) || (i < t)); +} + +void aq_ring_update_queue_state(struct aq_ring_s *ring) +{ + if (aq_ring_avail_dx(ring) <= AQ_CFG_SKB_FRAGS_MAX) + aq_ring_queue_stop(ring); + else if (aq_ring_avail_dx(ring) > AQ_CFG_RESTART_DESC_THRES) + aq_ring_queue_wake(ring); +} + +void aq_ring_queue_wake(struct aq_ring_s *ring) +{ + struct net_device *ndev = aq_nic_get_ndev(ring->aq_nic); + + if (__netif_subqueue_stopped(ndev, ring->idx)) { + netif_wake_subqueue(ndev, ring->idx); + ring->stats.tx.queue_restarts++; + } +} + +void aq_ring_queue_stop(struct aq_ring_s *ring) +{ + struct net_device *ndev = aq_nic_get_ndev(ring->aq_nic); + + if (!__netif_subqueue_stopped(ndev, ring->idx)) + netif_stop_subqueue(ndev, ring->idx); +} + void aq_ring_tx_clean(struct aq_ring_s *self) { struct device *dev = aq_nic_get_dev(self->aq_nic); @@ -113,23 +145,28 @@ void aq_ring_tx_clean(struct aq_ring_s *self) struct aq_ring_buff_s *buff = &self->buff_ring[self->sw_head]; if (likely(buff->is_mapped)) { - if (unlikely(buff->is_sop)) + if (unlikely(buff->is_sop)) { + if (!buff->is_eop && + buff->eop_index != 0xffffU && + (!aq_ring_dx_in_range(self->sw_head, + buff->eop_index, + self->hw_head))) + break; + dma_unmap_single(dev, buff->pa, buff->len, DMA_TO_DEVICE); - else + } else { dma_unmap_page(dev, buff->pa, buff->len, DMA_TO_DEVICE); + } } if (unlikely(buff->is_eop)) dev_kfree_skb_any(buff->skb); - } -} -static inline unsigned int aq_ring_dx_in_range(unsigned int h, unsigned int i, - unsigned int t) -{ - return (h < t) ? ((h < i) && (i < t)) : ((h < i) || (i < t)); + buff->pa = 0U; + buff->eop_index = 0xffffU; + } } #define AQ_SKB_ALIGN SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h index 782176c5f4f8..5844078764bd 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.h @@ -65,7 +65,7 @@ struct __packed aq_ring_buff_s { }; union { struct { - u32 len:16; + u16 len; u32 is_ip_cso:1; u32 is_udp_cso:1; u32 is_tcp_cso:1; @@ -77,8 +77,10 @@ struct __packed aq_ring_buff_s { u32 is_cleaned:1; u32 is_error:1; u32 rsvd3:6; + u16 eop_index; + u16 rsvd4; }; - u32 flags; + u64 flags; }; }; @@ -94,6 +96,7 @@ struct aq_ring_stats_tx_s { u64 errors; u64 packets; u64 bytes; + u64 queue_restarts; }; union aq_ring_stats_s { @@ -147,6 +150,9 @@ struct aq_ring_s *aq_ring_rx_alloc(struct aq_ring_s *self, int aq_ring_init(struct aq_ring_s *self); void aq_ring_rx_deinit(struct aq_ring_s *self); void aq_ring_free(struct aq_ring_s *self); +void aq_ring_update_queue_state(struct aq_ring_s *ring); +void aq_ring_queue_wake(struct aq_ring_s *ring); +void aq_ring_queue_stop(struct aq_ring_s *ring); void aq_ring_tx_clean(struct aq_ring_s *self); int aq_ring_rx_clean(struct aq_ring_s *self, struct napi_struct *napi, diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c index ebf588004c46..5fecc9a099ef 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_vec.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_vec.c @@ -59,12 +59,7 @@ static int aq_vec_poll(struct napi_struct *napi, int budget) if (ring[AQ_VEC_TX_ID].sw_head != ring[AQ_VEC_TX_ID].hw_head) { aq_ring_tx_clean(&ring[AQ_VEC_TX_ID]); - - if (aq_ring_avail_dx(&ring[AQ_VEC_TX_ID]) > - AQ_CFG_SKB_FRAGS_MAX) { - aq_nic_ndev_queue_start(self->aq_nic, - ring[AQ_VEC_TX_ID].idx); - } + aq_ring_update_queue_state(&ring[AQ_VEC_TX_ID]); was_tx_cleaned = true; } @@ -364,6 +359,7 @@ void aq_vec_add_stats(struct aq_vec_s *self, stats_tx->packets += tx->packets; stats_tx->bytes += tx->bytes; stats_tx->errors += tx->errors; + stats_tx->queue_restarts += tx->queue_restarts; } } @@ -377,8 +373,11 @@ int aq_vec_get_sw_stats(struct aq_vec_s *self, u64 *data, unsigned int *p_count) memset(&stats_tx, 0U, sizeof(struct aq_ring_stats_tx_s)); aq_vec_add_stats(self, &stats_rx, &stats_tx); + /* This data should mimic aq_ethtool_queue_stat_names structure + */ data[count] += stats_rx.packets; data[++count] += stats_tx.packets; + data[++count] += stats_tx.queue_restarts; data[++count] += stats_rx.jumbo_packets; data[++count] += stats_rx.lro_packets; data[++count] += stats_rx.errors; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c index c5a02df7a48b..07b3c49a16a4 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c @@ -765,24 +765,23 @@ err_exit: return err; } -static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self, - bool itr_enabled) +static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self) { unsigned int i = 0U; + u32 itr_rx; - if (itr_enabled && self->aq_nic_cfg->itr) { - if (self->aq_nic_cfg->itr != 0xFFFFU) { + if (self->aq_nic_cfg->itr) { + if (self->aq_nic_cfg->itr != AQ_CFG_INTERRUPT_MODERATION_AUTO) { u32 itr_ = (self->aq_nic_cfg->itr >> 1); itr_ = min(AQ_CFG_IRQ_MASK, itr_); - PHAL_ATLANTIC_A0->itr_rx = 0x80000000U | - (itr_ << 0x10); + itr_rx = 0x80000000U | (itr_ << 0x10); } else { u32 n = 0xFFFFU & aq_hw_read_reg(self, 0x00002A00U); if (n < self->aq_link_status.mbps) { - PHAL_ATLANTIC_A0->itr_rx = 0U; + itr_rx = 0U; } else { static unsigned int hw_timers_tbl_[] = { 0x01CU, /* 10Gbit */ @@ -797,8 +796,7 @@ static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self, hw_atl_utils_mbps_2_speed_index( self->aq_link_status.mbps); - PHAL_ATLANTIC_A0->itr_rx = - 0x80000000U | + itr_rx = 0x80000000U | (hw_timers_tbl_[speed_index] << 0x10U); } @@ -806,11 +804,11 @@ static int hw_atl_a0_hw_interrupt_moderation_set(struct aq_hw_s *self, aq_hw_write_reg(self, 0x00002A00U, 0x8D000000U); } } else { - PHAL_ATLANTIC_A0->itr_rx = 0U; + itr_rx = 0U; } for (i = HW_ATL_A0_RINGS_MAX; i--;) - reg_irq_thr_set(self, PHAL_ATLANTIC_A0->itr_rx, i); + reg_irq_thr_set(self, itr_rx, i); return aq_hw_err_from_flags(self); } @@ -885,6 +883,7 @@ static struct aq_hw_ops hw_atl_ops_ = { .hw_rss_set = hw_atl_a0_hw_rss_set, .hw_rss_hash_set = hw_atl_a0_hw_rss_hash_set, .hw_get_regs = hw_atl_utils_hw_get_regs, + .hw_update_stats = hw_atl_utils_update_stats, .hw_get_hw_stats = hw_atl_utils_get_hw_stats, .hw_get_fw_version = hw_atl_utils_get_fw_version, }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 21784cc39dab..ec68c20efcbd 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -788,39 +788,45 @@ err_exit: return err; } -static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self, - bool itr_enabled) +static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self) { unsigned int i = 0U; + u32 itr_tx = 2U; + u32 itr_rx = 2U; - if (itr_enabled && self->aq_nic_cfg->itr) { + switch (self->aq_nic_cfg->itr) { + case AQ_CFG_INTERRUPT_MODERATION_ON: + case AQ_CFG_INTERRUPT_MODERATION_AUTO: tdm_tx_desc_wr_wb_irq_en_set(self, 0U); tdm_tdm_intr_moder_en_set(self, 1U); rdm_rx_desc_wr_wb_irq_en_set(self, 0U); rdm_rdm_intr_moder_en_set(self, 1U); - PHAL_ATLANTIC_B0->itr_tx = 2U; - PHAL_ATLANTIC_B0->itr_rx = 2U; + if (self->aq_nic_cfg->itr == AQ_CFG_INTERRUPT_MODERATION_ON) { + /* HW timers are in 2us units */ + int tx_max_timer = self->aq_nic_cfg->tx_itr / 2; + int tx_min_timer = tx_max_timer / 2; - if (self->aq_nic_cfg->itr != 0xFFFFU) { - unsigned int max_timer = self->aq_nic_cfg->itr / 2U; - unsigned int min_timer = self->aq_nic_cfg->itr / 32U; + int rx_max_timer = self->aq_nic_cfg->rx_itr / 2; + int rx_min_timer = rx_max_timer / 2; - max_timer = min(0x1FFU, max_timer); - min_timer = min(0xFFU, min_timer); + tx_max_timer = min(HW_ATL_INTR_MODER_MAX, tx_max_timer); + tx_min_timer = min(HW_ATL_INTR_MODER_MIN, tx_min_timer); + rx_max_timer = min(HW_ATL_INTR_MODER_MAX, rx_max_timer); + rx_min_timer = min(HW_ATL_INTR_MODER_MIN, rx_min_timer); - PHAL_ATLANTIC_B0->itr_tx |= min_timer << 0x8U; - PHAL_ATLANTIC_B0->itr_tx |= max_timer << 0x10U; - PHAL_ATLANTIC_B0->itr_rx |= min_timer << 0x8U; - PHAL_ATLANTIC_B0->itr_rx |= max_timer << 0x10U; + itr_tx |= tx_min_timer << 0x8U; + itr_tx |= tx_max_timer << 0x10U; + itr_rx |= rx_min_timer << 0x8U; + itr_rx |= rx_max_timer << 0x10U; } else { static unsigned int hw_atl_b0_timers_table_tx_[][2] = { - {0xffU, 0xffU}, /* 10Gbit */ - {0xffU, 0x1ffU}, /* 5Gbit */ - {0xffU, 0x1ffU}, /* 5Gbit 5GS */ - {0xffU, 0x1ffU}, /* 2.5Gbit */ - {0xffU, 0x1ffU}, /* 1Gbit */ - {0xffU, 0x1ffU}, /* 100Mbit */ + {0xfU, 0xffU}, /* 10Gbit */ + {0xfU, 0x1ffU}, /* 5Gbit */ + {0xfU, 0x1ffU}, /* 5Gbit 5GS */ + {0xfU, 0x1ffU}, /* 2.5Gbit */ + {0xfU, 0x1ffU}, /* 1Gbit */ + {0xfU, 0x1ffU}, /* 100Mbit */ }; static unsigned int hw_atl_b0_timers_table_rx_[][2] = { @@ -836,34 +842,36 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self, hw_atl_utils_mbps_2_speed_index( self->aq_link_status.mbps); - PHAL_ATLANTIC_B0->itr_tx |= - hw_atl_b0_timers_table_tx_[speed_index] - [0] << 0x8U; /* set min timer value */ - PHAL_ATLANTIC_B0->itr_tx |= - hw_atl_b0_timers_table_tx_[speed_index] - [1] << 0x10U; /* set max timer value */ - - PHAL_ATLANTIC_B0->itr_rx |= - hw_atl_b0_timers_table_rx_[speed_index] - [0] << 0x8U; /* set min timer value */ - PHAL_ATLANTIC_B0->itr_rx |= - hw_atl_b0_timers_table_rx_[speed_index] - [1] << 0x10U; /* set max timer value */ + /* Update user visible ITR settings */ + self->aq_nic_cfg->tx_itr = hw_atl_b0_timers_table_tx_ + [speed_index][1] * 2; + self->aq_nic_cfg->rx_itr = hw_atl_b0_timers_table_rx_ + [speed_index][1] * 2; + + itr_tx |= hw_atl_b0_timers_table_tx_ + [speed_index][0] << 0x8U; + itr_tx |= hw_atl_b0_timers_table_tx_ + [speed_index][1] << 0x10U; + + itr_rx |= hw_atl_b0_timers_table_rx_ + [speed_index][0] << 0x8U; + itr_rx |= hw_atl_b0_timers_table_rx_ + [speed_index][1] << 0x10U; } - } else { + break; + case AQ_CFG_INTERRUPT_MODERATION_OFF: tdm_tx_desc_wr_wb_irq_en_set(self, 1U); tdm_tdm_intr_moder_en_set(self, 0U); rdm_rx_desc_wr_wb_irq_en_set(self, 1U); rdm_rdm_intr_moder_en_set(self, 0U); - PHAL_ATLANTIC_B0->itr_tx = 0U; - PHAL_ATLANTIC_B0->itr_rx = 0U; + itr_tx = 0U; + itr_rx = 0U; + break; } for (i = HW_ATL_B0_RINGS_MAX; i--;) { - reg_tx_intr_moder_ctrl_set(self, - PHAL_ATLANTIC_B0->itr_tx, i); - reg_rx_intr_moder_ctrl_set(self, - PHAL_ATLANTIC_B0->itr_rx, i); + reg_tx_intr_moder_ctrl_set(self, itr_tx, i); + reg_rx_intr_moder_ctrl_set(self, itr_rx, i); } return aq_hw_err_from_flags(self); @@ -939,6 +947,7 @@ static struct aq_hw_ops hw_atl_ops_ = { .hw_rss_set = hw_atl_b0_hw_rss_set, .hw_rss_hash_set = hw_atl_b0_hw_rss_hash_set, .hw_get_regs = hw_atl_utils_hw_get_regs, + .hw_update_stats = hw_atl_utils_update_stats, .hw_get_hw_stats = hw_atl_utils_get_hw_stats, .hw_get_fw_version = hw_atl_utils_get_fw_version, }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h index f3957e930340..9aa2c6edfca2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0_internal.h @@ -16,7 +16,7 @@ #include "../aq_common.h" -#define HW_ATL_B0_MTU_JUMBO (16000U) +#define HW_ATL_B0_MTU_JUMBO 16352U #define HW_ATL_B0_MTU 1514U #define HW_ATL_B0_TX_RINGS 4U @@ -139,6 +139,9 @@ #define HW_ATL_B0_FW_VER_EXPECTED 0x01050006U +#define HW_ATL_INTR_MODER_MAX 0x1FF +#define HW_ATL_INTR_MODER_MIN 0xFF + /* Hardware tx descriptor */ struct __packed hw_atl_txd_s { u64 buf_addr; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c index 4f5ec9a0fbfb..1fe016fc4bc7 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.c @@ -255,6 +255,15 @@ err_exit: return err; } +int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self, + struct hw_aq_atl_utils_mbox_header *pmbox) +{ + return hw_atl_utils_fw_downld_dwords(self, + PHAL_ATLANTIC->mbox_addr, + (u32 *)(void *)pmbox, + sizeof(*pmbox) / sizeof(u32)); +} + void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self, struct hw_aq_atl_utils_mbox *pmbox) { @@ -267,9 +276,6 @@ void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self, if (err < 0) goto err_exit; - if (pmbox != &PHAL_ATLANTIC->mbox) - memcpy(pmbox, &PHAL_ATLANTIC->mbox, sizeof(*pmbox)); - if (IS_CHIP_FEATURE(REVISION_A0)) { unsigned int mtu = self->aq_nic_cfg ? self->aq_nic_cfg->mtu : 1514U; @@ -299,17 +305,17 @@ void hw_atl_utils_mpi_set(struct aq_hw_s *self, { int err = 0; u32 transaction_id = 0; + struct hw_aq_atl_utils_mbox_header mbox; if (state == MPI_RESET) { - hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox); + hw_atl_utils_mpi_read_mbox(self, &mbox); - transaction_id = PHAL_ATLANTIC->mbox.transaction_id; + transaction_id = mbox.transaction_id; AQ_HW_WAIT_FOR(transaction_id != - (hw_atl_utils_mpi_read_stats - (self, &PHAL_ATLANTIC->mbox), - PHAL_ATLANTIC->mbox.transaction_id), - 1000U, 100U); + (hw_atl_utils_mpi_read_mbox(self, &mbox), + mbox.transaction_id), + 1000U, 100U); if (err < 0) goto err_exit; } @@ -351,8 +357,7 @@ int hw_atl_utils_mpi_get_link_status(struct aq_hw_s *self) break; default: - link_status->mbps = 0U; - break; + return -EBUSY; } } @@ -493,16 +498,51 @@ int hw_atl_utils_hw_set_power(struct aq_hw_s *self, return 0; } +int hw_atl_utils_update_stats(struct aq_hw_s *self) +{ + struct hw_atl_s *hw_self = PHAL_ATLANTIC; + struct hw_aq_atl_utils_mbox mbox; + + if (!self->aq_link_status.mbps) + return 0; + + hw_atl_utils_mpi_read_stats(self, &mbox); + +#define AQ_SDELTA(_N_) (hw_self->curr_stats._N_ += \ + mbox.stats._N_ - hw_self->last_stats._N_) + + AQ_SDELTA(uprc); + AQ_SDELTA(mprc); + AQ_SDELTA(bprc); + AQ_SDELTA(erpt); + + AQ_SDELTA(uptc); + AQ_SDELTA(mptc); + AQ_SDELTA(bptc); + AQ_SDELTA(erpr); + + AQ_SDELTA(ubrc); + AQ_SDELTA(ubtc); + AQ_SDELTA(mbrc); + AQ_SDELTA(mbtc); + AQ_SDELTA(bbrc); + AQ_SDELTA(bbtc); + AQ_SDELTA(dpc); + +#undef AQ_SDELTA + + memcpy(&hw_self->last_stats, &mbox.stats, sizeof(mbox.stats)); + + return 0; +} + int hw_atl_utils_get_hw_stats(struct aq_hw_s *self, u64 *data, unsigned int *p_count) { - struct hw_atl_stats_s *stats = NULL; + struct hw_atl_s *hw_self = PHAL_ATLANTIC; + struct hw_atl_stats_s *stats = &hw_self->curr_stats; int i = 0; - hw_atl_utils_mpi_read_stats(self, &PHAL_ATLANTIC->mbox); - - stats = &PHAL_ATLANTIC->mbox.stats; - data[i] = stats->uprc + stats->mprc + stats->bprc; data[++i] = stats->uprc; data[++i] = stats->mprc; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h index e0360a6b2202..c99cc690e425 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils.h @@ -115,19 +115,22 @@ struct __packed hw_aq_atl_utils_fw_rpc { }; }; -struct __packed hw_aq_atl_utils_mbox { +struct __packed hw_aq_atl_utils_mbox_header { u32 version; u32 transaction_id; - int error; + u32 error; +}; + +struct __packed hw_aq_atl_utils_mbox { + struct hw_aq_atl_utils_mbox_header header; struct hw_atl_stats_s stats; }; struct __packed hw_atl_s { struct aq_hw_s base; - struct hw_aq_atl_utils_mbox mbox; + struct hw_atl_stats_s last_stats; + struct hw_atl_stats_s curr_stats; u64 speed; - u32 itr_tx; - u32 itr_rx; unsigned int chip_features; u32 fw_ver_actual; atomic_t dpc; @@ -170,6 +173,9 @@ enum hal_atl_utils_fw_state_e { void hw_atl_utils_hw_chip_features_init(struct aq_hw_s *self, u32 *p); +int hw_atl_utils_mpi_read_mbox(struct aq_hw_s *self, + struct hw_aq_atl_utils_mbox_header *pmbox); + void hw_atl_utils_mpi_read_stats(struct aq_hw_s *self, struct hw_aq_atl_utils_mbox *pmbox); @@ -199,6 +205,8 @@ int hw_atl_utils_hw_deinit(struct aq_hw_s *self); int hw_atl_utils_get_fw_version(struct aq_hw_s *self, u32 *fw_version); +int hw_atl_utils_update_stats(struct aq_hw_s *self); + int hw_atl_utils_get_hw_stats(struct aq_hw_s *self, u64 *data, unsigned int *p_count); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index aacec8bc19d5..dc5de275352a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -214,6 +214,8 @@ static const u16 bnxt_async_events_arr[] = { ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE, }; +static struct workqueue_struct *bnxt_pf_wq; + static bool bnxt_vf_pciid(enum board_idx idx) { return (idx == NETXTREME_C_VF || idx == NETXTREME_E_VF); @@ -1024,12 +1026,28 @@ static int bnxt_discard_rx(struct bnxt *bp, struct bnxt_napi *bnapi, return 0; } +static void bnxt_queue_sp_work(struct bnxt *bp) +{ + if (BNXT_PF(bp)) + queue_work(bnxt_pf_wq, &bp->sp_task); + else + schedule_work(&bp->sp_task); +} + +static void bnxt_cancel_sp_work(struct bnxt *bp) +{ + if (BNXT_PF(bp)) + flush_workqueue(bnxt_pf_wq); + else + cancel_work_sync(&bp->sp_task); +} + static void bnxt_sched_reset(struct bnxt *bp, struct bnxt_rx_ring_info *rxr) { if (!rxr->bnapi->in_reset) { rxr->bnapi->in_reset = true; set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event); - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); } rxr->rx_next_cons = 0xffff; } @@ -1717,7 +1735,7 @@ static int bnxt_async_event_process(struct bnxt *bp, default: goto async_event_process_exit; } - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); async_event_process_exit: bnxt_ulp_async_events(bp, cmpl); return 0; @@ -1751,7 +1769,7 @@ static int bnxt_hwrm_handler(struct bnxt *bp, struct tx_cmp *txcmp) set_bit(vf_id - bp->pf.first_vf_id, bp->pf.vf_event_bmap); set_bit(BNXT_HWRM_EXEC_FWD_REQ_SP_EVENT, &bp->sp_event); - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); break; case CMPL_BASE_TYPE_HWRM_ASYNC_EVENT: @@ -3448,6 +3466,12 @@ int _hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) return bnxt_hwrm_do_send_msg(bp, msg, msg_len, timeout, false); } +int _hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 msg_len, + int timeout) +{ + return bnxt_hwrm_do_send_msg(bp, msg, msg_len, timeout, true); +} + int hwrm_send_message(struct bnxt *bp, void *msg, u32 msg_len, int timeout) { int rc; @@ -6327,7 +6351,9 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) } if (link_re_init) { + mutex_lock(&bp->link_lock); rc = bnxt_update_phy_setting(bp); + mutex_unlock(&bp->link_lock); if (rc) netdev_warn(bp->dev, "failed to update phy settings\n"); } @@ -6647,7 +6673,7 @@ static void bnxt_set_rx_mode(struct net_device *dev) vnic->rx_mask = mask; set_bit(BNXT_RX_MASK_SP_EVENT, &bp->sp_event); - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); } } @@ -6920,7 +6946,7 @@ static void bnxt_tx_timeout(struct net_device *dev) netdev_err(bp->dev, "TX timeout detected, starting reset task!\n"); set_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event); - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); } #ifdef CONFIG_NET_POLL_CONTROLLER @@ -6952,7 +6978,7 @@ static void bnxt_timer(unsigned long data) if (bp->link_info.link_up && (bp->flags & BNXT_FLAG_PORT_STATS) && bp->stats_coal_ticks) { set_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event); - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); } bnxt_restart_timer: mod_timer(&bp->timer, jiffies + bp->current_interval); @@ -7025,30 +7051,28 @@ static void bnxt_sp_task(struct work_struct *work) if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event)) bnxt_hwrm_port_qstats(bp); - /* These functions below will clear BNXT_STATE_IN_SP_TASK. They - * must be the last functions to be called before exiting. - */ if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) { - int rc = 0; + int rc; + mutex_lock(&bp->link_lock); if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT, &bp->sp_event)) bnxt_hwrm_phy_qcaps(bp); - bnxt_rtnl_lock_sp(bp); - if (test_bit(BNXT_STATE_OPEN, &bp->state)) - rc = bnxt_update_link(bp, true); - bnxt_rtnl_unlock_sp(bp); + rc = bnxt_update_link(bp, true); + mutex_unlock(&bp->link_lock); if (rc) netdev_err(bp->dev, "SP task can't update link (rc: %x)\n", rc); } if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event)) { - bnxt_rtnl_lock_sp(bp); - if (test_bit(BNXT_STATE_OPEN, &bp->state)) - bnxt_get_port_module_status(bp); - bnxt_rtnl_unlock_sp(bp); + mutex_lock(&bp->link_lock); + bnxt_get_port_module_status(bp); + mutex_unlock(&bp->link_lock); } + /* These functions below will clear BNXT_STATE_IN_SP_TASK. They + * must be the last functions to be called before exiting. + */ if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event)) bnxt_reset(bp, false); @@ -7433,7 +7457,7 @@ static int bnxt_rx_flow_steer(struct net_device *dev, const struct sk_buff *skb, spin_unlock_bh(&bp->ntp_fltr_lock); set_bit(BNXT_RX_NTP_FLTR_SP_EVENT, &bp->sp_event); - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); return new_fltr->sw_id; @@ -7516,7 +7540,7 @@ static void bnxt_udp_tunnel_add(struct net_device *dev, if (bp->vxlan_port_cnt == 1) { bp->vxlan_port = ti->port; set_bit(BNXT_VXLAN_ADD_PORT_SP_EVENT, &bp->sp_event); - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); } break; case UDP_TUNNEL_TYPE_GENEVE: @@ -7533,7 +7557,7 @@ static void bnxt_udp_tunnel_add(struct net_device *dev, return; } - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); } static void bnxt_udp_tunnel_del(struct net_device *dev, @@ -7572,7 +7596,7 @@ static void bnxt_udp_tunnel_del(struct net_device *dev, return; } - schedule_work(&bp->sp_task); + bnxt_queue_sp_work(bp); } static int bnxt_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, @@ -7720,7 +7744,7 @@ static void bnxt_remove_one(struct pci_dev *pdev) pci_disable_pcie_error_reporting(pdev); unregister_netdev(dev); bnxt_shutdown_tc(bp); - cancel_work_sync(&bp->sp_task); + bnxt_cancel_sp_work(bp); bp->sp_event = 0; bnxt_clear_int_mode(bp); @@ -7748,6 +7772,7 @@ static int bnxt_probe_phy(struct bnxt *bp) rc); return rc; } + mutex_init(&bp->link_lock); rc = bnxt_update_link(bp, false); if (rc) { @@ -7946,7 +7971,7 @@ static void bnxt_parse_log_pcie_link(struct bnxt *bp) enum pcie_link_width width = PCIE_LNK_WIDTH_UNKNOWN; enum pci_bus_speed speed = PCI_SPEED_UNKNOWN; - if (pcie_get_minimum_link(bp->pdev, &speed, &width) || + if (pcie_get_minimum_link(pci_physfn(bp->pdev), &speed, &width) || speed == PCI_SPEED_UNKNOWN || width == PCIE_LNK_WIDTH_UNKNOWN) netdev_info(bp->dev, "Failed to determine PCIe Link Info\n"); else @@ -8138,8 +8163,17 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) else device_set_wakeup_capable(&pdev->dev, false); - if (BNXT_PF(bp)) + if (BNXT_PF(bp)) { + if (!bnxt_pf_wq) { + bnxt_pf_wq = + create_singlethread_workqueue("bnxt_pf_wq"); + if (!bnxt_pf_wq) { + dev_err(&pdev->dev, "Unable to create workqueue.\n"); + goto init_err_pci_clean; + } + } bnxt_init_tc(bp); + } rc = register_netdev(dev); if (rc) @@ -8375,4 +8409,17 @@ static struct pci_driver bnxt_pci_driver = { #endif }; -module_pci_driver(bnxt_pci_driver); +static int __init bnxt_init(void) +{ + return pci_register_driver(&bnxt_pci_driver); +} + +static void __exit bnxt_exit(void) +{ + pci_unregister_driver(&bnxt_pci_driver); + if (bnxt_pf_wq) + destroy_workqueue(bnxt_pf_wq); +} + +module_init(bnxt_init); +module_exit(bnxt_exit); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 7b888d4b2b55..c911e69ff25f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -1290,6 +1290,10 @@ struct bnxt { unsigned long *ntp_fltr_bmap; int ntp_fltr_count; + /* To protect link related settings during link changes and + * ethtool settings changes. + */ + struct mutex link_lock; struct bnxt_link_info link_info; struct ethtool_eee eee; u32 lpi_tmr_lo; @@ -1358,6 +1362,7 @@ void bnxt_set_ring_params(struct bnxt *); int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode); void bnxt_hwrm_cmd_hdr_init(struct bnxt *, void *, u16, u16, u16); int _hwrm_send_message(struct bnxt *, void *, u32, int); +int _hwrm_send_message_silent(struct bnxt *bp, void *msg, u32 len, int timeout); int hwrm_send_message(struct bnxt *, void *, u32, int); int hwrm_send_message_silent(struct bnxt *, void *, u32, int); int bnxt_hwrm_func_rgtr_async_events(struct bnxt *bp, unsigned long *bmap, diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c index aa1f3a2c7a78..fed37cd9ae1d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c @@ -50,7 +50,9 @@ static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets) bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PRI2COS_QCFG, -1, -1); req.flags = cpu_to_le32(QUEUE_PRI2COS_QCFG_REQ_FLAGS_IVLAN); - rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); if (!rc) { u8 *pri2cos = &resp->pri0_cos_queue_id; int i, j; @@ -66,6 +68,7 @@ static int bnxt_hwrm_queue_pri2cos_qcfg(struct bnxt *bp, struct ieee_ets *ets) } } } + mutex_unlock(&bp->hwrm_cmd_lock); return rc; } @@ -119,9 +122,13 @@ static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets) int rc, i; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_COS2BW_QCFG, -1, -1); - rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); - if (rc) + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) { + mutex_unlock(&bp->hwrm_cmd_lock); return rc; + } data = &resp->queue_id0 + offsetof(struct bnxt_cos2bw_cfg, queue_id); for (i = 0; i < bp->max_tc; i++, data += sizeof(cos2bw) - 4) { @@ -143,6 +150,7 @@ static int bnxt_hwrm_queue_cos2bw_qcfg(struct bnxt *bp, struct ieee_ets *ets) } } } + mutex_unlock(&bp->hwrm_cmd_lock); return 0; } @@ -240,12 +248,17 @@ static int bnxt_hwrm_queue_pfc_qcfg(struct bnxt *bp, struct ieee_pfc *pfc) int rc; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_QUEUE_PFCENABLE_QCFG, -1, -1); - rc = hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); - if (rc) + + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + if (rc) { + mutex_unlock(&bp->hwrm_cmd_lock); return rc; + } pri_mask = le32_to_cpu(resp->flags); pfc->pfc_en = pri_mask; + mutex_unlock(&bp->hwrm_cmd_lock); return 0; } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 8eff05a3e0e4..3cbe771b3352 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -1052,6 +1052,7 @@ static int bnxt_get_link_ksettings(struct net_device *dev, u32 ethtool_speed; ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported); + mutex_lock(&bp->link_lock); bnxt_fw_to_ethtool_support_spds(link_info, lk_ksettings); ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising); @@ -1099,6 +1100,7 @@ static int bnxt_get_link_ksettings(struct net_device *dev, base->port = PORT_FIBRE; } base->phy_address = link_info->phy_addr; + mutex_unlock(&bp->link_lock); return 0; } @@ -1190,6 +1192,7 @@ static int bnxt_set_link_ksettings(struct net_device *dev, if (!BNXT_SINGLE_PF(bp)) return -EOPNOTSUPP; + mutex_lock(&bp->link_lock); if (base->autoneg == AUTONEG_ENABLE) { BNXT_ETHTOOL_TO_FW_SPDS(fw_advertising, lk_ksettings, advertising); @@ -1234,6 +1237,7 @@ static int bnxt_set_link_ksettings(struct net_device *dev, rc = bnxt_hwrm_set_link_setting(bp, set_pause, false); set_setting_exit: + mutex_unlock(&bp->link_lock); return rc; } @@ -1805,7 +1809,8 @@ static int bnxt_find_nvram_item(struct net_device *dev, u16 type, u16 ordinal, req.dir_ordinal = cpu_to_le16(ordinal); req.dir_ext = cpu_to_le16(ext); req.opt_ordinal = NVM_FIND_DIR_ENTRY_REQ_OPT_ORDINAL_EQ; - rc = hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); + mutex_lock(&bp->hwrm_cmd_lock); + rc = _hwrm_send_message_silent(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); if (rc == 0) { if (index) *index = le16_to_cpu(output->dir_idx); @@ -1814,6 +1819,7 @@ static int bnxt_find_nvram_item(struct net_device *dev, u16 type, u16 ordinal, if (data_length) *data_length = le32_to_cpu(output->dir_data_length); } + mutex_unlock(&bp->hwrm_cmd_lock); return rc; } diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c index d37925a8a65b..5ee18660bc33 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_sriov.c @@ -502,6 +502,7 @@ static int bnxt_sriov_enable(struct bnxt *bp, int *num_vfs) int rc = 0, vfs_supported; int min_rx_rings, min_tx_rings, min_rss_ctxs; int tx_ok = 0, rx_ok = 0, rss_ok = 0; + int avail_cp, avail_stat; /* Check if we can enable requested num of vf's. At a mininum * we require 1 RX 1 TX rings for each VF. In this minimum conf @@ -509,6 +510,10 @@ static int bnxt_sriov_enable(struct bnxt *bp, int *num_vfs) */ vfs_supported = *num_vfs; + avail_cp = bp->pf.max_cp_rings - bp->cp_nr_rings; + avail_stat = bp->pf.max_stat_ctxs - bp->num_stat_ctxs; + avail_cp = min_t(int, avail_cp, avail_stat); + while (vfs_supported) { min_rx_rings = vfs_supported; min_tx_rings = vfs_supported; @@ -523,10 +528,12 @@ static int bnxt_sriov_enable(struct bnxt *bp, int *num_vfs) min_rx_rings) rx_ok = 1; } - if (bp->pf.max_vnics - bp->nr_vnics < min_rx_rings) + if (bp->pf.max_vnics - bp->nr_vnics < min_rx_rings || + avail_cp < min_rx_rings) rx_ok = 0; - if (bp->pf.max_tx_rings - bp->tx_nr_rings >= min_tx_rings) + if (bp->pf.max_tx_rings - bp->tx_nr_rings >= min_tx_rings && + avail_cp >= min_tx_rings) tx_ok = 1; if (bp->pf.max_rsscos_ctxs - bp->rsscos_nr_ctxs >= min_rss_ctxs) diff --git a/drivers/net/ethernet/broadcom/cnic.c b/drivers/net/ethernet/broadcom/cnic.c index cec94bbb2ea5..8bc126a156e8 100644 --- a/drivers/net/ethernet/broadcom/cnic.c +++ b/drivers/net/ethernet/broadcom/cnic.c @@ -1278,7 +1278,7 @@ static int cnic_alloc_bnx2x_resc(struct cnic_dev *dev) ret = cnic_alloc_dma(dev, kwq_16_dma, pages, 0); if (ret) - return -ENOMEM; + goto error; n = CNIC_PAGE_SIZE / CNIC_KWQ16_DATA_SIZE; for (i = 0, j = 0; i < cp->max_cid_space; i++) { diff --git a/drivers/net/ethernet/cavium/liquidio/lio_main.c b/drivers/net/ethernet/cavium/liquidio/lio_main.c index e7f54948173f..5b19826a7e16 100644 --- a/drivers/net/ethernet/cavium/liquidio/lio_main.c +++ b/drivers/net/ethernet/cavium/liquidio/lio_main.c @@ -1847,7 +1847,7 @@ static int liquidio_ptp_settime(struct ptp_clock_info *ptp, struct lio *lio = container_of(ptp, struct lio, ptp_info); struct octeon_device *oct = (struct octeon_device *)lio->oct_dev; - ns = timespec_to_ns(ts); + ns = timespec64_to_ns(ts); spin_lock_irqsave(&lio->ptp_lock, flags); lio_pci_writeq(oct, ns, CN6XXX_MIO_PTP_CLOCK_HI); diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 49b80da51ba7..805ab45e9b5a 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -565,8 +565,10 @@ static inline bool nicvf_xdp_rx(struct nicvf *nic, struct bpf_prog *prog, return true; default: bpf_warn_invalid_xdp_action(action); + /* fall through */ case XDP_ABORTED: trace_xdp_exception(nic->netdev, prog, action); + /* fall through */ case XDP_DROP: /* Check if it's a recycled page, if not * unmap the DMA mapping. diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index e0685e630afe..c1cdbfd83bdb 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2652,7 +2652,8 @@ static int hclge_rss_init_hw(struct hclge_dev *hdev) dev_err(&hdev->pdev->dev, "Configure rss tc size failed, invalid TC_SIZE = %d\n", rss_size); - return -EINVAL; + ret = -EINVAL; + goto err; } roundup_size = roundup_pow_of_two(rss_size); diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index cb8182f4fdfa..c66abd476023 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1093,11 +1093,12 @@ static int build_hdr_data(u8 hdr_field, struct sk_buff *skb, * places them in a descriptor array, scrq_arr */ -static void create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len, - union sub_crq *scrq_arr) +static int create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len, + union sub_crq *scrq_arr) { union sub_crq hdr_desc; int tmp_len = len; + int num_descs = 0; u8 *data, *cur; int tmp; @@ -1126,7 +1127,10 @@ static void create_hdr_descs(u8 hdr_field, u8 *hdr_data, int len, int *hdr_len, tmp_len -= tmp; *scrq_arr = hdr_desc; scrq_arr++; + num_descs++; } + + return num_descs; } /** @@ -1144,16 +1148,12 @@ static void build_hdr_descs_arr(struct ibmvnic_tx_buff *txbuff, int *num_entries, u8 hdr_field) { int hdr_len[3] = {0, 0, 0}; - int tot_len, len; + int tot_len; u8 *hdr_data = txbuff->hdr_data; tot_len = build_hdr_data(hdr_field, txbuff->skb, hdr_len, txbuff->hdr_data); - len = tot_len; - len -= 24; - if (len > 0) - num_entries += len % 29 ? len / 29 + 1 : len / 29; - create_hdr_descs(hdr_field, hdr_data, tot_len, hdr_len, + *num_entries += create_hdr_descs(hdr_field, hdr_data, tot_len, hdr_len, txbuff->indir_arr + 1); } diff --git a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c index ec8aa4562cc9..3b3983a1ffbb 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_ethtool.c +++ b/drivers/net/ethernet/intel/e1000/e1000_ethtool.c @@ -1824,11 +1824,12 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, { struct e1000_adapter *adapter = netdev_priv(netdev); int i; - char *p = NULL; const struct e1000_stats *stat = e1000_gstrings_stats; e1000_update_stats(adapter); - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { + for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++, stat++) { + char *p; + switch (stat->type) { case NETDEV_STATS: p = (char *)netdev + stat->stat_offset; @@ -1839,15 +1840,13 @@ static void e1000_get_ethtool_stats(struct net_device *netdev, default: WARN_ONCE(1, "Invalid E1000 stat type: %u index %d\n", stat->type, i); - break; + continue; } if (stat->sizeof_stat == sizeof(u64)) data[i] = *(u64 *)p; else data[i] = *(u32 *)p; - - stat++; } /* BUG_ON(i != E1000_STATS_LEN); */ } diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c index 98375e1e1185..1982f7917a8d 100644 --- a/drivers/net/ethernet/intel/e1000/e1000_main.c +++ b/drivers/net/ethernet/intel/e1000/e1000_main.c @@ -520,8 +520,6 @@ void e1000_down(struct e1000_adapter *adapter) struct net_device *netdev = adapter->netdev; u32 rctl, tctl; - netif_carrier_off(netdev); - /* disable receives in the hardware */ rctl = er32(RCTL); ew32(RCTL, rctl & ~E1000_RCTL_EN); @@ -537,6 +535,15 @@ void e1000_down(struct e1000_adapter *adapter) E1000_WRITE_FLUSH(); msleep(10); + /* Set the carrier off after transmits have been disabled in the + * hardware, to avoid race conditions with e1000_watchdog() (which + * may be running concurrently to us, checking for the carrier + * bit to decide whether it should enable transmits again). Such + * a race condition would result into transmission being disabled + * in the hardware until the next IFF_DOWN+IFF_UP cycle. + */ + netif_carrier_off(netdev); + napi_disable(&adapter->napi); e1000_irq_disable(adapter); diff --git a/drivers/net/ethernet/intel/i40e/i40e_nvm.c b/drivers/net/ethernet/intel/i40e/i40e_nvm.c index 57505b1df98d..d591b3e6bd7c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_nvm.c +++ b/drivers/net/ethernet/intel/i40e/i40e_nvm.c @@ -298,7 +298,7 @@ static i40e_status i40e_read_nvm_word_aq(struct i40e_hw *hw, u16 offset, } /** - * __i40e_read_nvm_word - Reads nvm word, assumes called does the locking + * __i40e_read_nvm_word - Reads nvm word, assumes caller does the locking * @hw: pointer to the HW structure * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF) * @data: word read from the Shadow RAM diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 1519dfb851d0..120c68f78951 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -1038,6 +1038,32 @@ reset_latency: } /** + * i40e_reuse_rx_page - page flip buffer and store it back on the ring + * @rx_ring: rx descriptor ring to store buffers on + * @old_buff: donor buffer to have page reused + * + * Synchronizes page for reuse by the adapter + **/ +static void i40e_reuse_rx_page(struct i40e_ring *rx_ring, + struct i40e_rx_buffer *old_buff) +{ + struct i40e_rx_buffer *new_buff; + u16 nta = rx_ring->next_to_alloc; + + new_buff = &rx_ring->rx_bi[nta]; + + /* update, and store next to alloc */ + nta++; + rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; + + /* transfer page from old buffer to new buffer */ + new_buff->dma = old_buff->dma; + new_buff->page = old_buff->page; + new_buff->page_offset = old_buff->page_offset; + new_buff->pagecnt_bias = old_buff->pagecnt_bias; +} + +/** * i40e_rx_is_programming_status - check for programming status descriptor * @qw: qword representing status_error_len in CPU ordering * @@ -1071,15 +1097,24 @@ static void i40e_clean_programming_status(struct i40e_ring *rx_ring, union i40e_rx_desc *rx_desc, u64 qw) { - u32 ntc = rx_ring->next_to_clean + 1; + struct i40e_rx_buffer *rx_buffer; + u32 ntc = rx_ring->next_to_clean; u8 id; /* fetch, update, and store next to clean */ + rx_buffer = &rx_ring->rx_bi[ntc++]; ntc = (ntc < rx_ring->count) ? ntc : 0; rx_ring->next_to_clean = ntc; prefetch(I40E_RX_DESC(rx_ring, ntc)); + /* place unused page back on the ring */ + i40e_reuse_rx_page(rx_ring, rx_buffer); + rx_ring->rx_stats.page_reuse_count++; + + /* clear contents of buffer_info */ + rx_buffer->page = NULL; + id = (qw & I40E_RX_PROG_STATUS_DESC_QW1_PROGID_MASK) >> I40E_RX_PROG_STATUS_DESC_QW1_PROGID_SHIFT; @@ -1639,32 +1674,6 @@ static bool i40e_cleanup_headers(struct i40e_ring *rx_ring, struct sk_buff *skb, } /** - * i40e_reuse_rx_page - page flip buffer and store it back on the ring - * @rx_ring: rx descriptor ring to store buffers on - * @old_buff: donor buffer to have page reused - * - * Synchronizes page for reuse by the adapter - **/ -static void i40e_reuse_rx_page(struct i40e_ring *rx_ring, - struct i40e_rx_buffer *old_buff) -{ - struct i40e_rx_buffer *new_buff; - u16 nta = rx_ring->next_to_alloc; - - new_buff = &rx_ring->rx_bi[nta]; - - /* update, and store next to alloc */ - nta++; - rx_ring->next_to_alloc = (nta < rx_ring->count) ? nta : 0; - - /* transfer page from old buffer to new buffer */ - new_buff->dma = old_buff->dma; - new_buff->page = old_buff->page; - new_buff->page_offset = old_buff->page_offset; - new_buff->pagecnt_bias = old_buff->pagecnt_bias; -} - -/** * i40e_page_is_reusable - check if any reuse is possible * @page: page struct to check * @@ -2093,6 +2102,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) if (unlikely(i40e_rx_is_programming_status(qword))) { i40e_clean_programming_status(rx_ring, rx_desc, qword); + cleaned_count++; continue; } size = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >> @@ -2260,7 +2270,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi, goto enable_int; } - if (ITR_IS_DYNAMIC(tx_itr_setting)) { + if (ITR_IS_DYNAMIC(rx_itr_setting)) { rx = i40e_set_new_dynamic_itr(&q_vector->rx); rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr); } diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index fd4a46b03cc8..ea69af267d63 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c @@ -5326,7 +5326,7 @@ dma_error: DMA_TO_DEVICE); dma_unmap_len_set(tx_buffer, len, 0); - if (i--) + if (i-- == 0) i += tx_ring->count; tx_buffer = &tx_ring->tx_buffer_info[i]; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c index 523f9d05a810..8a32eb7d47b9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82598.c @@ -175,31 +175,9 @@ static s32 ixgbe_init_phy_ops_82598(struct ixgbe_hw *hw) **/ static s32 ixgbe_start_hw_82598(struct ixgbe_hw *hw) { -#ifndef CONFIG_SPARC - u32 regval; - u32 i; -#endif s32 ret_val; ret_val = ixgbe_start_hw_generic(hw); - -#ifndef CONFIG_SPARC - /* Disable relaxed ordering */ - for (i = 0; ((i < hw->mac.max_tx_queues) && - (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { - regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL(i)); - regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL(i), regval); - } - - for (i = 0; ((i < hw->mac.max_rx_queues) && - (i < IXGBE_DCA_MAX_QUEUES_82598)); i++) { - regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); - regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | - IXGBE_DCA_RXCTRL_HEAD_WRO_EN); - IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); - } -#endif if (ret_val) return ret_val; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c index 2c19070d2a0b..6e6ab6f6875e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c @@ -366,25 +366,6 @@ s32 ixgbe_start_hw_gen2(struct ixgbe_hw *hw) } IXGBE_WRITE_FLUSH(hw); -#ifndef CONFIG_ARCH_WANT_RELAX_ORDER - /* Disable relaxed ordering */ - for (i = 0; i < hw->mac.max_tx_queues; i++) { - u32 regval; - - regval = IXGBE_READ_REG(hw, IXGBE_DCA_TXCTRL_82599(i)); - regval &= ~IXGBE_DCA_TXCTRL_DESC_WRO_EN; - IXGBE_WRITE_REG(hw, IXGBE_DCA_TXCTRL_82599(i), regval); - } - - for (i = 0; i < hw->mac.max_rx_queues; i++) { - u32 regval; - - regval = IXGBE_READ_REG(hw, IXGBE_DCA_RXCTRL(i)); - regval &= ~(IXGBE_DCA_RXCTRL_DATA_WRO_EN | - IXGBE_DCA_RXCTRL_HEAD_WRO_EN); - IXGBE_WRITE_REG(hw, IXGBE_DCA_RXCTRL(i), regval); - } -#endif return 0; } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 72c565712a5f..c3e7a8191128 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -1048,7 +1048,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev, { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_ring *temp_ring; - int i, err = 0; + int i, j, err = 0; u32 new_rx_count, new_tx_count; if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) @@ -1085,8 +1085,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev, } /* allocate temporary buffer to store rings in */ - i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues); - i = max_t(int, i, adapter->num_xdp_queues); + i = max_t(int, adapter->num_tx_queues + adapter->num_xdp_queues, + adapter->num_rx_queues); temp_ring = vmalloc(i * sizeof(struct ixgbe_ring)); if (!temp_ring) { @@ -1118,8 +1118,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev, } } - for (i = 0; i < adapter->num_xdp_queues; i++) { - memcpy(&temp_ring[i], adapter->xdp_ring[i], + for (j = 0; j < adapter->num_xdp_queues; j++, i++) { + memcpy(&temp_ring[i], adapter->xdp_ring[j], sizeof(struct ixgbe_ring)); temp_ring[i].count = new_tx_count; @@ -1139,10 +1139,10 @@ static int ixgbe_set_ringparam(struct net_device *netdev, memcpy(adapter->tx_ring[i], &temp_ring[i], sizeof(struct ixgbe_ring)); } - for (i = 0; i < adapter->num_xdp_queues; i++) { - ixgbe_free_tx_resources(adapter->xdp_ring[i]); + for (j = 0; j < adapter->num_xdp_queues; j++, i++) { + ixgbe_free_tx_resources(adapter->xdp_ring[j]); - memcpy(adapter->xdp_ring[i], &temp_ring[i], + memcpy(adapter->xdp_ring[j], &temp_ring[i], sizeof(struct ixgbe_ring)); } diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index d962368d08d0..6d5f31e94358 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4881,7 +4881,7 @@ static void ixgbe_clear_udp_tunnel_port(struct ixgbe_adapter *adapter, u32 mask) IXGBE_FLAG_GENEVE_OFFLOAD_CAPABLE))) return; - vxlanctrl = IXGBE_READ_REG(hw, IXGBE_VXLANCTRL) && ~mask; + vxlanctrl = IXGBE_READ_REG(hw, IXGBE_VXLANCTRL) & ~mask; IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, vxlanctrl); if (mask & IXGBE_VXLANCTRL_VXLAN_UDPPORT_MASK) @@ -8020,29 +8020,23 @@ static int ixgbe_tx_map(struct ixgbe_ring *tx_ring, return 0; dma_error: dev_err(tx_ring->dev, "TX DMA map failed\n"); - tx_buffer = &tx_ring->tx_buffer_info[i]; /* clear dma mappings for failed tx_buffer_info map */ - while (tx_buffer != first) { + for (;;) { + tx_buffer = &tx_ring->tx_buffer_info[i]; if (dma_unmap_len(tx_buffer, len)) dma_unmap_page(tx_ring->dev, dma_unmap_addr(tx_buffer, dma), dma_unmap_len(tx_buffer, len), DMA_TO_DEVICE); dma_unmap_len_set(tx_buffer, len, 0); - - if (i--) + if (tx_buffer == first) + break; + if (i == 0) i += tx_ring->count; - tx_buffer = &tx_ring->tx_buffer_info[i]; + i--; } - if (dma_unmap_len(tx_buffer, len)) - dma_unmap_single(tx_ring->dev, - dma_unmap_addr(tx_buffer, dma), - dma_unmap_len(tx_buffer, len), - DMA_TO_DEVICE); - dma_unmap_len_set(tx_buffer, len, 0); - dev_kfree_skb_any(first->skb); first->skb = NULL; @@ -8529,6 +8523,10 @@ static int ixgbe_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) return ixgbe_ptp_set_ts_config(adapter, req); case SIOCGHWTSTAMP: return ixgbe_ptp_get_ts_config(adapter, req); + case SIOCGMIIPHY: + if (!adapter->hw.phy.ops.read_reg) + return -EOPNOTSUPP; + /* fall through */ default: return mdio_mii_ioctl(&adapter->hw.phy.mdio, if_mii(req), cmd); } diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index dd0ee2691c86..a37af5813f33 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -333,7 +333,7 @@ #define MVPP2_GMAC_INBAND_AN_MASK BIT(0) #define MVPP2_GMAC_FLOW_CTRL_MASK GENMASK(2, 1) #define MVPP2_GMAC_PCS_ENABLE_MASK BIT(3) -#define MVPP2_GMAC_PORT_RGMII_MASK BIT(4) +#define MVPP2_GMAC_INTERNAL_CLK_MASK BIT(4) #define MVPP2_GMAC_DISABLE_PADDING BIT(5) #define MVPP2_GMAC_PORT_RESET_MASK BIT(6) #define MVPP2_GMAC_AUTONEG_CONFIG 0xc @@ -676,6 +676,7 @@ enum mvpp2_tag_type { #define MVPP2_PRS_RI_L3_MCAST BIT(15) #define MVPP2_PRS_RI_L3_BCAST (BIT(15) | BIT(16)) #define MVPP2_PRS_RI_IP_FRAG_MASK 0x20000 +#define MVPP2_PRS_RI_IP_FRAG_TRUE BIT(17) #define MVPP2_PRS_RI_UDF3_MASK 0x300000 #define MVPP2_PRS_RI_UDF3_RX_SPECIAL BIT(21) #define MVPP2_PRS_RI_L4_PROTO_MASK 0x1c00000 @@ -792,6 +793,7 @@ struct mvpp2 { struct clk *pp_clk; struct clk *gop_clk; struct clk *mg_clk; + struct clk *axi_clk; /* List of pointers to port structures */ struct mvpp2_port **port_list; @@ -1165,6 +1167,11 @@ struct mvpp2_bm_pool { u32 port_map; }; +#define IS_TSO_HEADER(txq_pcpu, addr) \ + ((addr) >= (txq_pcpu)->tso_headers_dma && \ + (addr) < (txq_pcpu)->tso_headers_dma + \ + (txq_pcpu)->size * TSO_HEADER_SIZE) + /* Queue modes */ #define MVPP2_QDIST_SINGLE_MODE 0 #define MVPP2_QDIST_MULTI_MODE 1 @@ -1532,7 +1539,7 @@ static bool mvpp2_prs_tcam_data_cmp(struct mvpp2_prs_entry *pe, int offs, int off = MVPP2_PRS_TCAM_DATA_BYTE(offs); u16 tcam_data; - tcam_data = (8 << pe->tcam.byte[off + 1]) | pe->tcam.byte[off]; + tcam_data = (pe->tcam.byte[off + 1] << 8) | pe->tcam.byte[off]; if (tcam_data != data) return false; return true; @@ -2315,7 +2322,7 @@ static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto, (proto != IPPROTO_IGMP)) return -EINVAL; - /* Fragmented packet */ + /* Not fragmented packet */ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID, MVPP2_PE_LAST_FREE_TID); if (tid < 0) @@ -2334,8 +2341,12 @@ static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto, MVPP2_PRS_SRAM_OP_SEL_UDF_ADD); mvpp2_prs_sram_ai_update(&pe, MVPP2_PRS_IPV4_DIP_AI_BIT, MVPP2_PRS_IPV4_DIP_AI_BIT); - mvpp2_prs_sram_ri_update(&pe, ri | MVPP2_PRS_RI_IP_FRAG_MASK, - ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK); + mvpp2_prs_sram_ri_update(&pe, ri, ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK); + + mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, + MVPP2_PRS_TCAM_PROTO_MASK_L); + mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, + MVPP2_PRS_TCAM_PROTO_MASK); mvpp2_prs_tcam_data_byte_set(&pe, 5, proto, MVPP2_PRS_TCAM_PROTO_MASK); mvpp2_prs_tcam_ai_update(&pe, 0, MVPP2_PRS_IPV4_DIP_AI_BIT); @@ -2346,7 +2357,7 @@ static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto, mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4); mvpp2_prs_hw_write(priv, &pe); - /* Not fragmented packet */ + /* Fragmented packet */ tid = mvpp2_prs_tcam_first_free(priv, MVPP2_PE_FIRST_FREE_TID, MVPP2_PE_LAST_FREE_TID); if (tid < 0) @@ -2358,8 +2369,11 @@ static int mvpp2_prs_ip4_proto(struct mvpp2 *priv, unsigned short proto, pe.sram.word[MVPP2_PRS_SRAM_RI_CTRL_WORD] = 0x0; mvpp2_prs_sram_ri_update(&pe, ri, ri_mask); - mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, MVPP2_PRS_TCAM_PROTO_MASK_L); - mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, MVPP2_PRS_TCAM_PROTO_MASK); + mvpp2_prs_sram_ri_update(&pe, ri | MVPP2_PRS_RI_IP_FRAG_TRUE, + ri_mask | MVPP2_PRS_RI_IP_FRAG_MASK); + + mvpp2_prs_tcam_data_byte_set(&pe, 2, 0x00, 0x0); + mvpp2_prs_tcam_data_byte_set(&pe, 3, 0x00, 0x0); /* Update shadow table and hw entry */ mvpp2_prs_shadow_set(priv, pe.index, MVPP2_PRS_LU_IP4); @@ -2600,8 +2614,8 @@ static void mvpp2_prs_mac_init(struct mvpp2 *priv) /* place holders only - no ports */ mvpp2_prs_mac_drop_all_set(priv, 0, false); mvpp2_prs_mac_promisc_set(priv, 0, false); - mvpp2_prs_mac_multi_set(priv, MVPP2_PE_MAC_MC_ALL, 0, false); - mvpp2_prs_mac_multi_set(priv, MVPP2_PE_MAC_MC_IP6, 0, false); + mvpp2_prs_mac_multi_set(priv, 0, MVPP2_PE_MAC_MC_ALL, false); + mvpp2_prs_mac_multi_set(priv, 0, MVPP2_PE_MAC_MC_IP6, false); } /* Set default entries for various types of dsa packets */ @@ -3382,7 +3396,7 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da, struct mvpp2_prs_entry *pe; int tid; - pe = kzalloc(sizeof(*pe), GFP_KERNEL); + pe = kzalloc(sizeof(*pe), GFP_ATOMIC); if (!pe) return NULL; mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC); @@ -3444,7 +3458,7 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port, if (tid < 0) return tid; - pe = kzalloc(sizeof(*pe), GFP_KERNEL); + pe = kzalloc(sizeof(*pe), GFP_ATOMIC); if (!pe) return -ENOMEM; mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC); @@ -4591,7 +4605,6 @@ static void mvpp2_port_mii_gmac_configure(struct mvpp2_port *port) val |= MVPP2_GMAC_INBAND_AN_MASK | MVPP2_GMAC_PCS_ENABLE_MASK; } else if (phy_interface_mode_is_rgmii(port->phy_interface)) { val &= ~MVPP2_GMAC_PCS_ENABLE_MASK; - val |= MVPP2_GMAC_PORT_RGMII_MASK; } writel(val, port->base + MVPP2_GMAC_CTRL_2_REG); @@ -5313,8 +5326,9 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port, struct mvpp2_txq_pcpu_buf *tx_buf = txq_pcpu->buffs + txq_pcpu->txq_get_index; - dma_unmap_single(port->dev->dev.parent, tx_buf->dma, - tx_buf->size, DMA_TO_DEVICE); + if (!IS_TSO_HEADER(txq_pcpu, tx_buf->dma)) + dma_unmap_single(port->dev->dev.parent, tx_buf->dma, + tx_buf->size, DMA_TO_DEVICE); if (tx_buf->skb) dev_kfree_skb_any(tx_buf->skb); @@ -5601,7 +5615,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port, txq_pcpu->tso_headers = dma_alloc_coherent(port->dev->dev.parent, - MVPP2_AGGR_TXQ_SIZE * TSO_HEADER_SIZE, + txq_pcpu->size * TSO_HEADER_SIZE, &txq_pcpu->tso_headers_dma, GFP_KERNEL); if (!txq_pcpu->tso_headers) @@ -5615,7 +5629,7 @@ cleanup: kfree(txq_pcpu->buffs); dma_free_coherent(port->dev->dev.parent, - MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE, + txq_pcpu->size * TSO_HEADER_SIZE, txq_pcpu->tso_headers, txq_pcpu->tso_headers_dma); } @@ -5639,7 +5653,7 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port, kfree(txq_pcpu->buffs); dma_free_coherent(port->dev->dev.parent, - MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE, + txq_pcpu->size * TSO_HEADER_SIZE, txq_pcpu->tso_headers, txq_pcpu->tso_headers_dma); } @@ -6204,12 +6218,15 @@ static inline void tx_desc_unmap_put(struct mvpp2_port *port, struct mvpp2_tx_queue *txq, struct mvpp2_tx_desc *desc) { + struct mvpp2_txq_pcpu *txq_pcpu = this_cpu_ptr(txq->pcpu); + dma_addr_t buf_dma_addr = mvpp2_txdesc_dma_addr_get(port, desc); size_t buf_sz = mvpp2_txdesc_size_get(port, desc); - dma_unmap_single(port->dev->dev.parent, buf_dma_addr, - buf_sz, DMA_TO_DEVICE); + if (!IS_TSO_HEADER(txq_pcpu, buf_dma_addr)) + dma_unmap_single(port->dev->dev.parent, buf_dma_addr, + buf_sz, DMA_TO_DEVICE); mvpp2_txq_desc_put(txq); } @@ -6482,7 +6499,7 @@ out: } /* Finalize TX processing */ - if (txq_pcpu->count >= txq->done_pkts_coal) + if (!port->has_tx_irqs && txq_pcpu->count >= txq->done_pkts_coal) mvpp2_txq_done(port, txq, txq_pcpu); /* Set the timer in case not all frags were processed */ @@ -7496,7 +7513,7 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv, /* Ports initialization */ static int mvpp2_port_probe(struct platform_device *pdev, struct device_node *port_node, - struct mvpp2 *priv) + struct mvpp2 *priv, int index) { struct device_node *phy_node; struct phy *comphy; @@ -7670,7 +7687,7 @@ static int mvpp2_port_probe(struct platform_device *pdev, } netdev_info(dev, "Using %s mac address %pM\n", mac_from, dev->dev_addr); - priv->port_list[id] = port; + priv->port_list[index] = port; return 0; err_free_port_pcpu: @@ -7963,6 +7980,18 @@ static int mvpp2_probe(struct platform_device *pdev) err = clk_prepare_enable(priv->mg_clk); if (err < 0) goto err_gop_clk; + + priv->axi_clk = devm_clk_get(&pdev->dev, "axi_clk"); + if (IS_ERR(priv->axi_clk)) { + err = PTR_ERR(priv->axi_clk); + if (err == -EPROBE_DEFER) + goto err_gop_clk; + priv->axi_clk = NULL; + } else { + err = clk_prepare_enable(priv->axi_clk); + if (err < 0) + goto err_gop_clk; + } } /* Get system's tclk rate */ @@ -8005,16 +8034,19 @@ static int mvpp2_probe(struct platform_device *pdev) } /* Initialize ports */ + i = 0; for_each_available_child_of_node(dn, port_node) { - err = mvpp2_port_probe(pdev, port_node, priv); + err = mvpp2_port_probe(pdev, port_node, priv, i); if (err < 0) goto err_mg_clk; + i++; } platform_set_drvdata(pdev, priv); return 0; err_mg_clk: + clk_disable_unprepare(priv->axi_clk); if (priv->hw_version == MVPP22) clk_disable_unprepare(priv->mg_clk); err_gop_clk: @@ -8052,6 +8084,7 @@ static int mvpp2_remove(struct platform_device *pdev) aggr_txq->descs_dma); } + clk_disable_unprepare(priv->axi_clk); clk_disable_unprepare(priv->mg_clk); clk_disable_unprepare(priv->pp_clk); clk_disable_unprepare(priv->gop_clk); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index ff60cf7342ca..fc281712869b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -77,35 +77,41 @@ static void add_delayed_event(struct mlx5_priv *priv, list_add_tail(&delayed_event->list, &priv->waiting_events_list); } -static void fire_delayed_event_locked(struct mlx5_device_context *dev_ctx, - struct mlx5_core_dev *dev, - struct mlx5_priv *priv) +static void delayed_event_release(struct mlx5_device_context *dev_ctx, + struct mlx5_priv *priv) { + struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv); struct mlx5_delayed_event *de; struct mlx5_delayed_event *n; + struct list_head temp; - /* stop delaying events */ - priv->is_accum_events = false; + INIT_LIST_HEAD(&temp); + + spin_lock_irq(&priv->ctx_lock); - /* fire all accumulated events before new event comes */ - list_for_each_entry_safe(de, n, &priv->waiting_events_list, list) { + priv->is_accum_events = false; + list_splice_init(&priv->waiting_events_list, &temp); + if (!dev_ctx->context) + goto out; + list_for_each_entry_safe(de, n, &priv->waiting_events_list, list) dev_ctx->intf->event(dev, dev_ctx->context, de->event, de->param); + +out: + spin_unlock_irq(&priv->ctx_lock); + + list_for_each_entry_safe(de, n, &temp, list) { list_del(&de->list); kfree(de); } } -static void cleanup_delayed_evets(struct mlx5_priv *priv) +/* accumulating events that can come after mlx5_ib calls to + * ib_register_device, till adding that interface to the events list. + */ +static void delayed_event_start(struct mlx5_priv *priv) { - struct mlx5_delayed_event *de; - struct mlx5_delayed_event *n; - spin_lock_irq(&priv->ctx_lock); - priv->is_accum_events = false; - list_for_each_entry_safe(de, n, &priv->waiting_events_list, list) { - list_del(&de->list); - kfree(de); - } + priv->is_accum_events = true; spin_unlock_irq(&priv->ctx_lock); } @@ -122,11 +128,8 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) return; dev_ctx->intf = intf; - /* accumulating events that can come after mlx5_ib calls to - * ib_register_device, till adding that interface to the events list. - */ - priv->is_accum_events = true; + delayed_event_start(priv); dev_ctx->context = intf->add(dev); set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state); @@ -137,8 +140,6 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) spin_lock_irq(&priv->ctx_lock); list_add_tail(&dev_ctx->list, &priv->ctx_list); - fire_delayed_event_locked(dev_ctx, dev, priv); - #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING if (dev_ctx->intf->pfault) { if (priv->pfault) { @@ -150,11 +151,12 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) } #endif spin_unlock_irq(&priv->ctx_lock); - } else { - kfree(dev_ctx); - /* delete all accumulated events */ - cleanup_delayed_evets(priv); } + + delayed_event_release(dev_ctx, priv); + + if (!dev_ctx->context) + kfree(dev_ctx); } static struct mlx5_device_context *mlx5_get_device(struct mlx5_interface *intf, @@ -205,17 +207,21 @@ static void mlx5_attach_interface(struct mlx5_interface *intf, struct mlx5_priv if (!dev_ctx) return; + delayed_event_start(priv); if (intf->attach) { if (test_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state)) - return; + goto out; intf->attach(dev, dev_ctx->context); set_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state); } else { if (test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state)) - return; + goto out; dev_ctx->context = intf->add(dev); set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state); } + +out: + delayed_event_release(dev_ctx, priv); } void mlx5_attach_device(struct mlx5_core_dev *dev) @@ -414,8 +420,14 @@ void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, if (priv->is_accum_events) add_delayed_event(priv, dev, event, param); + /* After mlx5_detach_device, the dev_ctx->intf is still set and dev_ctx is + * still in priv->ctx_list. In this case, only notify the dev_ctx if its + * ADDED or ATTACHED bit are set. + */ list_for_each_entry(dev_ctx, &priv->ctx_list, list) - if (dev_ctx->intf->event) + if (dev_ctx->intf->event && + (test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state) || + test_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state))) dev_ctx->intf->event(dev, dev_ctx->context, event, param); spin_unlock_irqrestore(&priv->ctx_lock, flags); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h index 1e3a6c3e4132..80eef4163f52 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h @@ -139,7 +139,7 @@ TRACE_EVENT(mlx5_fs_del_fg, {MLX5_FLOW_CONTEXT_ACTION_FWD_NEXT_PRIO, "NEXT_PRIO"} TRACE_EVENT(mlx5_fs_set_fte, - TP_PROTO(const struct fs_fte *fte, bool new_fte), + TP_PROTO(const struct fs_fte *fte, int new_fte), TP_ARGS(fte, new_fte), TP_STRUCT__entry( __field(const struct fs_fte *, fte) @@ -149,7 +149,7 @@ TRACE_EVENT(mlx5_fs_set_fte, __field(u32, action) __field(u32, flow_tag) __field(u8, mask_enable) - __field(bool, new_fte) + __field(int, new_fte) __array(u32, mask_outer, MLX5_ST_SZ_DW(fte_match_set_lyr_2_4)) __array(u32, mask_inner, MLX5_ST_SZ_DW(fte_match_set_lyr_2_4)) __array(u32, mask_misc, MLX5_ST_SZ_DW(fte_match_set_misc)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c index c1d384fca4dc..51c4cc00a186 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c @@ -41,6 +41,11 @@ #define MLX5E_CEE_STATE_UP 1 #define MLX5E_CEE_STATE_DOWN 0 +enum { + MLX5E_VENDOR_TC_GROUP_NUM = 7, + MLX5E_LOWEST_PRIO_GROUP = 0, +}; + /* If dcbx mode is non-host set the dcbx mode to host. */ static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv, @@ -85,6 +90,9 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, { struct mlx5e_priv *priv = netdev_priv(netdev); struct mlx5_core_dev *mdev = priv->mdev; + u8 tc_group[IEEE_8021QAZ_MAX_TCS]; + bool is_tc_group_6_exist = false; + bool is_zero_bw_ets_tc = false; int err = 0; int i; @@ -96,37 +104,64 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]); if (err) return err; - } - for (i = 0; i < ets->ets_cap; i++) { + err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]); + if (err) + return err; + err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]); if (err) return err; + + if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC && + tc_group[i] == (MLX5E_LOWEST_PRIO_GROUP + 1)) + is_zero_bw_ets_tc = true; + + if (tc_group[i] == (MLX5E_VENDOR_TC_GROUP_NUM - 1)) + is_tc_group_6_exist = true; + } + + /* Report 0% ets tc if exits*/ + if (is_zero_bw_ets_tc) { + for (i = 0; i < ets->ets_cap; i++) + if (tc_group[i] == MLX5E_LOWEST_PRIO_GROUP) + ets->tc_tx_bw[i] = 0; + } + + /* Update tc_tsa based on fw setting*/ + for (i = 0; i < ets->ets_cap; i++) { if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC) priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS; + else if (tc_group[i] == MLX5E_VENDOR_TC_GROUP_NUM && + !is_tc_group_6_exist) + priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR; } - memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa)); return err; } -enum { - MLX5E_VENDOR_TC_GROUP_NUM = 7, - MLX5E_ETS_TC_GROUP_NUM = 0, -}; - static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc) { bool any_tc_mapped_to_ets = false; + bool ets_zero_bw = false; int strict_group; int i; - for (i = 0; i <= max_tc; i++) - if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) + for (i = 0; i <= max_tc; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { any_tc_mapped_to_ets = true; + if (!ets->tc_tx_bw[i]) + ets_zero_bw = true; + } + } - strict_group = any_tc_mapped_to_ets ? 1 : 0; + /* strict group has higher priority than ets group */ + strict_group = MLX5E_LOWEST_PRIO_GROUP; + if (any_tc_mapped_to_ets) + strict_group++; + if (ets_zero_bw) + strict_group++; for (i = 0; i <= max_tc; i++) { switch (ets->tc_tsa[i]) { @@ -137,7 +172,9 @@ static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc) tc_group[i] = strict_group++; break; case IEEE_8021QAZ_TSA_ETS: - tc_group[i] = MLX5E_ETS_TC_GROUP_NUM; + tc_group[i] = MLX5E_LOWEST_PRIO_GROUP; + if (ets->tc_tx_bw[i] && ets_zero_bw) + tc_group[i] = MLX5E_LOWEST_PRIO_GROUP + 1; break; } } @@ -146,9 +183,23 @@ static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc) static void mlx5e_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw, u8 *tc_group, int max_tc) { + int bw_for_ets_zero_bw_tc = 0; + int last_ets_zero_bw_tc = -1; + int num_ets_zero_bw = 0; int i; for (i = 0; i <= max_tc; i++) { + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS && + !ets->tc_tx_bw[i]) { + num_ets_zero_bw++; + last_ets_zero_bw_tc = i; + } + } + + if (num_ets_zero_bw) + bw_for_ets_zero_bw_tc = MLX5E_MAX_BW_ALLOC / num_ets_zero_bw; + + for (i = 0; i <= max_tc; i++) { switch (ets->tc_tsa[i]) { case IEEE_8021QAZ_TSA_VENDOR: tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC; @@ -157,12 +208,26 @@ static void mlx5e_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw, tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC; break; case IEEE_8021QAZ_TSA_ETS: - tc_tx_bw[i] = ets->tc_tx_bw[i]; + tc_tx_bw[i] = ets->tc_tx_bw[i] ? + ets->tc_tx_bw[i] : + bw_for_ets_zero_bw_tc; break; } } + + /* Make sure the total bw for ets zero bw group is 100% */ + if (last_ets_zero_bw_tc != -1) + tc_tx_bw[last_ets_zero_bw_tc] += + MLX5E_MAX_BW_ALLOC % num_ets_zero_bw; } +/* If there are ETS BW 0, + * Set ETS group # to 1 for all ETS non zero BW tcs. Their sum must be 100%. + * Set group #0 to all the ETS BW 0 tcs and + * equally splits the 100% BW between them + * Report both group #0 and #1 as ETS type. + * All the tcs in group #0 will be reported with 0% BW. + */ int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets) { struct mlx5_core_dev *mdev = priv->mdev; @@ -188,7 +253,6 @@ int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets) return err; memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa)); - return err; } @@ -209,17 +273,9 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, } /* Validate Bandwidth Sum */ - for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { - if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) { - if (!ets->tc_tx_bw[i]) { - netdev_err(netdev, - "Failed to validate ETS: BW 0 is illegal\n"); - return -EINVAL; - } - + for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) + if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) bw_sum += ets->tc_tx_bw[i]; - } - } if (bw_sum != 0 && bw_sum != 100) { netdev_err(netdev, @@ -533,8 +589,7 @@ static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev, static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev, int pgid, u8 *bw_pct) { - struct mlx5e_priv *priv = netdev_priv(netdev); - struct mlx5_core_dev *mdev = priv->mdev; + struct ieee_ets ets; if (pgid >= CEE_DCBX_MAX_PGS) { netdev_err(netdev, @@ -542,8 +597,8 @@ static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev, return; } - if (mlx5_query_port_tc_bw_alloc(mdev, pgid, bw_pct)) - *bw_pct = 0; + mlx5e_dcbnl_ieee_getets(netdev, &ets); + *bw_pct = ets.tc_tx_bw[pgid]; } static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev, @@ -739,8 +794,6 @@ static void mlx5e_ets_init(struct mlx5e_priv *priv) ets.prio_tc[i] = i; } - memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa)); - /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */ ets.prio_tc[0] = 1; ets.prio_tc[1] = 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index f11fd07ac4dd..850cdc980ab5 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -291,7 +291,7 @@ void mlx5e_enable_vlan_filter(struct mlx5e_priv *priv) priv->fs.vlan.filter_disabled = false; if (priv->netdev->flags & IFF_PROMISC) return; - mlx5e_del_any_vid_rules(priv); + mlx5e_del_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0); } void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv) @@ -302,7 +302,7 @@ void mlx5e_disable_vlan_filter(struct mlx5e_priv *priv) priv->fs.vlan.filter_disabled = true; if (priv->netdev->flags & IFF_PROMISC) return; - mlx5e_add_any_vid_rules(priv); + mlx5e_add_vlan_rule(priv, MLX5E_VLAN_RULE_TYPE_ANY_CTAG_VID, 0); } int mlx5e_vlan_rx_add_vid(struct net_device *dev, __always_unused __be16 proto, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index dfc29720ab77..cc11bbbd0309 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -184,7 +184,6 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv) struct mlx5e_sw_stats temp, *s = &temp; struct mlx5e_rq_stats *rq_stats; struct mlx5e_sq_stats *sq_stats; - u64 tx_offload_none = 0; int i, j; memset(s, 0, sizeof(*s)); @@ -199,6 +198,7 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv) s->rx_lro_bytes += rq_stats->lro_bytes; s->rx_csum_none += rq_stats->csum_none; s->rx_csum_complete += rq_stats->csum_complete; + s->rx_csum_unnecessary += rq_stats->csum_unnecessary; s->rx_csum_unnecessary_inner += rq_stats->csum_unnecessary_inner; s->rx_xdp_drop += rq_stats->xdp_drop; s->rx_xdp_tx += rq_stats->xdp_tx; @@ -229,14 +229,11 @@ static void mlx5e_update_sw_counters(struct mlx5e_priv *priv) s->tx_queue_dropped += sq_stats->dropped; s->tx_xmit_more += sq_stats->xmit_more; s->tx_csum_partial_inner += sq_stats->csum_partial_inner; - tx_offload_none += sq_stats->csum_none; + s->tx_csum_none += sq_stats->csum_none; + s->tx_csum_partial += sq_stats->csum_partial; } } - /* Update calculated offload counters */ - s->tx_csum_partial = s->tx_packets - tx_offload_none - s->tx_csum_partial_inner; - s->rx_csum_unnecessary = s->rx_packets - s->rx_csum_none - s->rx_csum_complete; - s->link_down_events_phy = MLX5_GET(ppcnt_reg, priv->stats.pport.phy_counters, counter_set.phys_layer_cntrs.link_down_events); @@ -3333,8 +3330,8 @@ static int mlx5e_handle_feature(struct net_device *netdev, err = feature_handler(netdev, enable); if (err) { - netdev_err(netdev, "%s feature 0x%llx failed err %d\n", - enable ? "Enable" : "Disable", feature, err); + netdev_err(netdev, "%s feature %pNF failed, err %d\n", + enable ? "Enable" : "Disable", &feature, err); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index f1dd638384d3..15a1687483cc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -627,6 +627,7 @@ static inline void mlx5e_handle_csum(struct net_device *netdev, if (lro) { skb->ip_summed = CHECKSUM_UNNECESSARY; + rq->stats.csum_unnecessary++; return; } @@ -644,7 +645,9 @@ static inline void mlx5e_handle_csum(struct net_device *netdev, skb->csum_level = 1; skb->encapsulation = 1; rq->stats.csum_unnecessary_inner++; + return; } + rq->stats.csum_unnecessary++; return; } csum_none: diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 6d199ffb1c0b..f8637213afc0 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -68,6 +68,7 @@ struct mlx5e_sw_stats { u64 rx_xdp_drop; u64 rx_xdp_tx; u64 rx_xdp_tx_full; + u64 tx_csum_none; u64 tx_csum_partial; u64 tx_csum_partial_inner; u64 tx_queue_stopped; @@ -108,6 +109,7 @@ static const struct counter_desc sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_drop) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_xdp_tx_full) }, + { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_none) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_partial) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_csum_partial_inner) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_queue_stopped) }, @@ -339,6 +341,7 @@ struct mlx5e_rq_stats { u64 packets; u64 bytes; u64 csum_complete; + u64 csum_unnecessary; u64 csum_unnecessary_inner; u64 csum_none; u64 lro_packets; @@ -363,6 +366,7 @@ static const struct counter_desc rq_stats_desc[] = { { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, packets) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, bytes) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_complete) }, + { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_unnecessary) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_unnecessary_inner) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, csum_none) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, xdp_drop) }, @@ -392,6 +396,7 @@ struct mlx5e_sq_stats { u64 tso_bytes; u64 tso_inner_packets; u64 tso_inner_bytes; + u64 csum_partial; u64 csum_partial_inner; u64 nop; /* less likely accessed in data path */ @@ -408,6 +413,7 @@ static const struct counter_desc sq_stats_desc[] = { { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tso_bytes) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tso_inner_packets) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tso_inner_bytes) }, + { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_partial) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_partial_inner) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, nop) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, csum_none) }, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index da503e6411da..9ba1f72060aa 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -78,9 +78,11 @@ struct mlx5e_tc_flow { }; struct mlx5e_tc_flow_parse_attr { + struct ip_tunnel_info tun_info; struct mlx5_flow_spec spec; int num_mod_hdr_actions; void *mod_hdr_actions; + int mirred_ifindex; }; enum { @@ -322,6 +324,12 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv, static void mlx5e_detach_encap(struct mlx5e_priv *priv, struct mlx5e_tc_flow *flow); +static int mlx5e_attach_encap(struct mlx5e_priv *priv, + struct ip_tunnel_info *tun_info, + struct net_device *mirred_dev, + struct net_device **encap_dev, + struct mlx5e_tc_flow *flow); + static struct mlx5_flow_handle * mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, struct mlx5e_tc_flow_parse_attr *parse_attr, @@ -329,9 +337,27 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5_esw_flow_attr *attr = flow->esw_attr; - struct mlx5_flow_handle *rule; + struct net_device *out_dev, *encap_dev = NULL; + struct mlx5_flow_handle *rule = NULL; + struct mlx5e_rep_priv *rpriv; + struct mlx5e_priv *out_priv; int err; + if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) { + out_dev = __dev_get_by_index(dev_net(priv->netdev), + attr->parse_attr->mirred_ifindex); + err = mlx5e_attach_encap(priv, &parse_attr->tun_info, + out_dev, &encap_dev, flow); + if (err) { + rule = ERR_PTR(err); + if (err != -EAGAIN) + goto err_attach_encap; + } + out_priv = netdev_priv(encap_dev); + rpriv = out_priv->ppriv; + attr->out_rep = rpriv->rep; + } + err = mlx5_eswitch_add_vlan_action(esw, attr); if (err) { rule = ERR_PTR(err); @@ -347,10 +373,14 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv, } } - rule = mlx5_eswitch_add_offloaded_rule(esw, &parse_attr->spec, attr); - if (IS_ERR(rule)) - goto err_add_rule; - + /* we get here if (1) there's no error (rule being null) or when + * (2) there's an encap action and we're on -EAGAIN (no valid neigh) + */ + if (rule != ERR_PTR(-EAGAIN)) { + rule = mlx5_eswitch_add_offloaded_rule(esw, &parse_attr->spec, attr); + if (IS_ERR(rule)) + goto err_add_rule; + } return rule; err_add_rule: @@ -361,6 +391,7 @@ err_mod_hdr: err_add_vlan: if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) mlx5e_detach_encap(priv, flow); +err_attach_encap: return rule; } @@ -389,6 +420,8 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv, void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) { + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + struct mlx5_esw_flow_attr *esw_attr; struct mlx5e_tc_flow *flow; int err; @@ -404,10 +437,9 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, mlx5e_rep_queue_neigh_stats_work(priv); list_for_each_entry(flow, &e->flows, encap) { - flow->esw_attr->encap_id = e->encap_id; - flow->rule = mlx5e_tc_add_fdb_flow(priv, - flow->esw_attr->parse_attr, - flow); + esw_attr = flow->esw_attr; + esw_attr->encap_id = e->encap_id; + flow->rule = mlx5_eswitch_add_offloaded_rule(esw, &esw_attr->parse_attr->spec, esw_attr); if (IS_ERR(flow->rule)) { err = PTR_ERR(flow->rule); mlx5_core_warn(priv->mdev, "Failed to update cached encapsulation flow, %d\n", @@ -421,15 +453,13 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv, void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e) { + struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; struct mlx5e_tc_flow *flow; - struct mlx5_fc *counter; list_for_each_entry(flow, &e->flows, encap) { if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) { flow->flags &= ~MLX5E_TC_FLOW_OFFLOADED; - counter = mlx5_flow_rule_counter(flow->rule); - mlx5_del_flow_rules(flow->rule); - mlx5_fc_destroy(priv->mdev, counter); + mlx5_eswitch_del_offloaded_rule(esw, flow->rule, flow->esw_attr); } } @@ -1317,6 +1347,69 @@ static bool csum_offload_supported(struct mlx5e_priv *priv, u32 action, u32 upda return true; } +static bool modify_header_match_supported(struct mlx5_flow_spec *spec, + struct tcf_exts *exts) +{ + const struct tc_action *a; + bool modify_ip_header; + LIST_HEAD(actions); + u8 htype, ip_proto; + void *headers_v; + u16 ethertype; + int nkeys, i; + + headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers); + ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype); + + /* for non-IP we only re-write MACs, so we're okay */ + if (ethertype != ETH_P_IP && ethertype != ETH_P_IPV6) + goto out_ok; + + modify_ip_header = false; + tcf_exts_to_list(exts, &actions); + list_for_each_entry(a, &actions, list) { + if (!is_tcf_pedit(a)) + continue; + + nkeys = tcf_pedit_nkeys(a); + for (i = 0; i < nkeys; i++) { + htype = tcf_pedit_htype(a, i); + if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 || + htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP6) { + modify_ip_header = true; + break; + } + } + } + + ip_proto = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ip_protocol); + if (modify_ip_header && ip_proto != IPPROTO_TCP && ip_proto != IPPROTO_UDP) { + pr_info("can't offload re-write of ip proto %d\n", ip_proto); + return false; + } + +out_ok: + return true; +} + +static bool actions_match_supported(struct mlx5e_priv *priv, + struct tcf_exts *exts, + struct mlx5e_tc_flow_parse_attr *parse_attr, + struct mlx5e_tc_flow *flow) +{ + u32 actions; + + if (flow->flags & MLX5E_TC_FLOW_ESWITCH) + actions = flow->esw_attr->action; + else + actions = flow->nic_attr->action; + + if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR) + return modify_header_match_supported(&parse_attr->spec, exts); + + return true; +} + static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, struct mlx5e_tc_flow_parse_attr *parse_attr, struct mlx5e_tc_flow *flow) @@ -1378,6 +1471,9 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, return -EINVAL; } + if (!actions_match_supported(priv, exts, parse_attr, flow)) + return -EOPNOTSUPP; + return 0; } @@ -1564,7 +1660,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv, break; default: err = -EOPNOTSUPP; - goto out; + goto free_encap; } fl4.flowi4_tos = tun_key->tos; fl4.daddr = tun_key->u.ipv4.dst; @@ -1573,7 +1669,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv, err = mlx5e_route_lookup_ipv4(priv, mirred_dev, &out_dev, &fl4, &n, &ttl); if (err) - goto out; + goto free_encap; /* used by mlx5e_detach_encap to lookup a neigh hash table * entry in the neigh hash table when a user deletes a rule @@ -1590,7 +1686,7 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv, */ err = mlx5e_rep_encap_entry_attach(netdev_priv(out_dev), e); if (err) - goto out; + goto free_encap; read_lock_bh(&n->lock); nud_state = n->nud_state; @@ -1630,8 +1726,9 @@ static int mlx5e_create_encap_header_ipv4(struct mlx5e_priv *priv, destroy_neigh_entry: mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e); -out: +free_encap: kfree(encap_header); +out: if (n) neigh_release(n); return err; @@ -1668,7 +1765,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv, break; default: err = -EOPNOTSUPP; - goto out; + goto free_encap; } fl6.flowlabel = ip6_make_flowinfo(RT_TOS(tun_key->tos), tun_key->label); @@ -1678,7 +1775,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv, err = mlx5e_route_lookup_ipv6(priv, mirred_dev, &out_dev, &fl6, &n, &ttl); if (err) - goto out; + goto free_encap; /* used by mlx5e_detach_encap to lookup a neigh hash table * entry in the neigh hash table when a user deletes a rule @@ -1695,7 +1792,7 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv, */ err = mlx5e_rep_encap_entry_attach(netdev_priv(out_dev), e); if (err) - goto out; + goto free_encap; read_lock_bh(&n->lock); nud_state = n->nud_state; @@ -1736,8 +1833,9 @@ static int mlx5e_create_encap_header_ipv6(struct mlx5e_priv *priv, destroy_neigh_entry: mlx5e_rep_encap_entry_detach(netdev_priv(e->out_dev), e); -out: +free_encap: kfree(encap_header); +out: if (n) neigh_release(n); return err; @@ -1791,6 +1889,7 @@ vxlan_encap_offload_err: } } + /* must verify if encap is valid or not */ if (found) goto attach_flow; @@ -1817,6 +1916,8 @@ attach_flow: *encap_dev = e->out_dev; if (e->flags & MLX5_ENCAP_ENTRY_VALID) attr->encap_id = e->encap_id; + else + err = -EAGAIN; return err; @@ -1871,7 +1972,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, if (is_tcf_mirred_egress_redirect(a)) { int ifindex = tcf_mirred_ifindex(a); - struct net_device *out_dev, *encap_dev = NULL; + struct net_device *out_dev; struct mlx5e_priv *out_priv; out_dev = __dev_get_by_index(dev_net(priv->netdev), ifindex); @@ -1884,17 +1985,13 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, rpriv = out_priv->ppriv; attr->out_rep = rpriv->rep; } else if (encap) { - err = mlx5e_attach_encap(priv, info, - out_dev, &encap_dev, flow); - if (err && err != -EAGAIN) - return err; + parse_attr->mirred_ifindex = ifindex; + parse_attr->tun_info = *info; + attr->parse_attr = parse_attr; attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP | MLX5_FLOW_CONTEXT_ACTION_FWD_DEST | MLX5_FLOW_CONTEXT_ACTION_COUNT; - out_priv = netdev_priv(encap_dev); - rpriv = out_priv->ppriv; - attr->out_rep = rpriv->rep; - attr->parse_attr = parse_attr; + /* attr->out_rep is resolved when we handle encap */ } else { pr_err("devices %s %s not on same switch HW, can't offload forwarding\n", priv->netdev->name, out_dev->name); @@ -1934,6 +2031,10 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts, return -EINVAL; } + + if (!actions_match_supported(priv, exts, parse_attr, flow)) + return -EOPNOTSUPP; + return err; } @@ -1972,7 +2073,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, if (flow->flags & MLX5E_TC_FLOW_ESWITCH) { err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow); if (err < 0) - goto err_handle_encap_flow; + goto err_free; flow->rule = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow); } else { err = parse_tc_nic_actions(priv, f->exts, parse_attr, flow); @@ -1983,10 +2084,13 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, if (IS_ERR(flow->rule)) { err = PTR_ERR(flow->rule); - goto err_free; + if (err != -EAGAIN) + goto err_free; } - flow->flags |= MLX5E_TC_FLOW_OFFLOADED; + if (err != -EAGAIN) + flow->flags |= MLX5E_TC_FLOW_OFFLOADED; + err = rhashtable_insert_fast(&tc->ht, &flow->node, tc->ht_params); if (err) @@ -2000,16 +2104,6 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv, err_del_rule: mlx5e_tc_del_flow(priv, flow); -err_handle_encap_flow: - if (err == -EAGAIN) { - err = rhashtable_insert_fast(&tc->ht, &flow->node, - tc->ht_params); - if (err) - mlx5e_tc_del_flow(priv, flow); - else - return 0; - } - err_free: kvfree(parse_attr); kfree(flow); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c index fee43e40fa16..1d6925d4369a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tx.c @@ -193,6 +193,7 @@ mlx5e_txwqe_build_eseg_csum(struct mlx5e_txqsq *sq, struct sk_buff *skb, struct sq->stats.csum_partial_inner++; } else { eseg->cs_flags |= MLX5_ETH_WQE_L4_CSUM; + sq->stats.csum_partial++; } } else sq->stats.csum_none++; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.c index e37453d838db..c0fd2212e890 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.c @@ -71,11 +71,11 @@ int mlx5_fpga_access_reg(struct mlx5_core_dev *dev, u8 size, u64 addr, return 0; } -int mlx5_fpga_caps(struct mlx5_core_dev *dev, u32 *caps) +int mlx5_fpga_caps(struct mlx5_core_dev *dev) { u32 in[MLX5_ST_SZ_DW(fpga_cap)] = {0}; - return mlx5_core_access_reg(dev, in, sizeof(in), caps, + return mlx5_core_access_reg(dev, in, sizeof(in), dev->caps.fpga, MLX5_ST_SZ_BYTES(fpga_cap), MLX5_REG_FPGA_CAP, 0, 0); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.h index 94bdfd47c3f0..d05233c9b4f6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/cmd.h @@ -65,7 +65,7 @@ struct mlx5_fpga_qp_counters { u64 rx_total_drop; }; -int mlx5_fpga_caps(struct mlx5_core_dev *dev, u32 *caps); +int mlx5_fpga_caps(struct mlx5_core_dev *dev); int mlx5_fpga_query(struct mlx5_core_dev *dev, struct mlx5_fpga_query *query); int mlx5_fpga_ctrl_op(struct mlx5_core_dev *dev, u8 op); int mlx5_fpga_access_reg(struct mlx5_core_dev *dev, u8 size, u64 addr, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c index 9034e9960a76..dc8970346521 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/core.c @@ -139,8 +139,7 @@ int mlx5_fpga_device_start(struct mlx5_core_dev *mdev) if (err) goto out; - err = mlx5_fpga_caps(fdev->mdev, - fdev->mdev->caps.hca_cur[MLX5_CAP_FPGA]); + err = mlx5_fpga_caps(fdev->mdev); if (err) goto out; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index e0d0efd903bc..36ecc2b2e187 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -293,6 +293,9 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, } if (fte->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) { + int max_list_size = BIT(MLX5_CAP_FLOWTABLE_TYPE(dev, + log_max_flow_counter, + ft->type)); int list_size = 0; list_for_each_entry(dst, &fte->node.children, node.list) { @@ -305,12 +308,17 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev, in_dests += MLX5_ST_SZ_BYTES(dest_format_struct); list_size++; } + if (list_size > max_list_size) { + err = -EINVAL; + goto err_out; + } MLX5_SET(flow_context, in_flow_context, flow_counter_list_size, list_size); } err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); +err_out: kvfree(in); return err; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 5509a752f98e..48dd78975062 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -52,6 +52,7 @@ enum fs_flow_table_type { FS_FT_FDB = 0X4, FS_FT_SNIFFER_RX = 0X5, FS_FT_SNIFFER_TX = 0X6, + FS_FT_MAX_TYPE = FS_FT_SNIFFER_TX, }; enum fs_flow_table_op_mod { @@ -260,4 +261,14 @@ void mlx5_cleanup_fs(struct mlx5_core_dev *dev); #define fs_for_each_dst(pos, fte) \ fs_list_for_each_entry(pos, &(fte)->node.children) +#define MLX5_CAP_FLOWTABLE_TYPE(mdev, cap, type) ( \ + (type == FS_FT_NIC_RX) ? MLX5_CAP_FLOWTABLE_NIC_RX(mdev, cap) : \ + (type == FS_FT_ESW_EGRESS_ACL) ? MLX5_CAP_ESW_EGRESS_ACL(mdev, cap) : \ + (type == FS_FT_ESW_INGRESS_ACL) ? MLX5_CAP_ESW_INGRESS_ACL(mdev, cap) : \ + (type == FS_FT_FDB) ? MLX5_CAP_ESW_FLOWTABLE_FDB(mdev, cap) : \ + (type == FS_FT_SNIFFER_RX) ? MLX5_CAP_FLOWTABLE_SNIFFER_RX(mdev, cap) : \ + (type == FS_FT_SNIFFER_TX) ? MLX5_CAP_FLOWTABLE_SNIFFER_TX(mdev, cap) : \ + (BUILD_BUG_ON_ZERO(FS_FT_SNIFFER_TX != FS_FT_MAX_TYPE))\ + ) + #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/health.c b/drivers/net/ethernet/mellanox/mlx5/core/health.c index 8aea0a065e56..db86e1506c8b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/health.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/health.c @@ -356,10 +356,11 @@ void mlx5_drain_health_wq(struct mlx5_core_dev *dev) void mlx5_drain_health_recovery(struct mlx5_core_dev *dev) { struct mlx5_core_health *health = &dev->priv.health; + unsigned long flags; - spin_lock(&health->wq_lock); + spin_lock_irqsave(&health->wq_lock, flags); set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags); - spin_unlock(&health->wq_lock); + spin_unlock_irqrestore(&health->wq_lock, flags); cancel_delayed_work_sync(&dev->priv.health.recover_work); } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index 85298051a3e4..145e392ab849 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -572,12 +572,13 @@ void mlx5_rdma_netdev_free(struct net_device *netdev) { struct mlx5e_priv *priv = mlx5i_epriv(netdev); const struct mlx5e_profile *profile = priv->profile; + struct mlx5_core_dev *mdev = priv->mdev; mlx5e_detach_netdev(priv); profile->cleanup(priv); destroy_workqueue(priv->wq); free_netdev(netdev); - mlx5e_destroy_mdev_resources(priv->mdev); + mlx5e_destroy_mdev_resources(mdev); } EXPORT_SYMBOL(mlx5_rdma_netdev_free); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/port.c b/drivers/net/ethernet/mellanox/mlx5/core/port.c index 1975d4388d4f..e07061f565d6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/port.c @@ -677,6 +677,27 @@ int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, u8 *tc_group) } EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group); +int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev, + u8 tc, u8 *tc_group) +{ + u32 out[MLX5_ST_SZ_DW(qetc_reg)]; + void *ets_tcn_conf; + int err; + + err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out)); + if (err) + return err; + + ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out, + tc_configuration[tc]); + + *tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf, + group); + + return 0; +} +EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group); + int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *tc_bw) { u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {0}; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c index 6c48e9959b65..2a8b529ce6dd 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c @@ -109,7 +109,7 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) mlx5_core_warn(dev, "failed to restore VF %d settings, err %d\n", vf, err); - continue; + continue; } } mlx5_core_dbg(dev, "successfully enabled VF* %d\n", vf); diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index 9d5e7cf288be..f3315bc874ad 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -96,6 +96,7 @@ struct mlxsw_core { const struct mlxsw_bus *bus; void *bus_priv; const struct mlxsw_bus_info *bus_info; + struct workqueue_struct *emad_wq; struct list_head rx_listener_list; struct list_head event_listener_list; struct { @@ -465,7 +466,7 @@ static void mlxsw_emad_trans_timeout_schedule(struct mlxsw_reg_trans *trans) { unsigned long timeout = msecs_to_jiffies(MLXSW_EMAD_TIMEOUT_MS); - mlxsw_core_schedule_dw(&trans->timeout_dw, timeout); + queue_delayed_work(trans->core->emad_wq, &trans->timeout_dw, timeout); } static int mlxsw_emad_transmit(struct mlxsw_core *mlxsw_core, @@ -587,12 +588,18 @@ static const struct mlxsw_listener mlxsw_emad_rx_listener = static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) { + struct workqueue_struct *emad_wq; u64 tid; int err; if (!(mlxsw_core->bus->features & MLXSW_BUS_F_TXRX)) return 0; + emad_wq = alloc_workqueue("mlxsw_core_emad", WQ_MEM_RECLAIM, 0); + if (!emad_wq) + return -ENOMEM; + mlxsw_core->emad_wq = emad_wq; + /* Set the upper 32 bits of the transaction ID field to a random * number. This allows us to discard EMADs addressed to other * devices. @@ -619,6 +626,7 @@ static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) err_emad_trap_set: mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener, mlxsw_core); + destroy_workqueue(mlxsw_core->emad_wq); return err; } @@ -631,6 +639,7 @@ static void mlxsw_emad_fini(struct mlxsw_core *mlxsw_core) mlxsw_core->emad.use_emad = false; mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener, mlxsw_core); + destroy_workqueue(mlxsw_core->emad_wq); } static struct sk_buff *mlxsw_emad_alloc(const struct mlxsw_core *mlxsw_core, diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index cc27c5de5a1d..4afc8486eb9a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -6401,6 +6401,36 @@ static inline void mlxsw_reg_mgpc_pack(char *payload, u32 counter_index, mlxsw_reg_mgpc_opcode_set(payload, opcode); } +/* TIGCR - Tunneling IPinIP General Configuration Register + * ------------------------------------------------------- + * The TIGCR register is used for setting up the IPinIP Tunnel configuration. + */ +#define MLXSW_REG_TIGCR_ID 0xA801 +#define MLXSW_REG_TIGCR_LEN 0x10 + +MLXSW_REG_DEFINE(tigcr, MLXSW_REG_TIGCR_ID, MLXSW_REG_TIGCR_LEN); + +/* reg_tigcr_ipip_ttlc + * For IPinIP Tunnel encapsulation: whether to copy the ttl from the packet + * header. + * Access: RW + */ +MLXSW_ITEM32(reg, tigcr, ttlc, 0x04, 8, 1); + +/* reg_tigcr_ipip_ttl_uc + * The TTL for IPinIP Tunnel encapsulation of unicast packets if + * reg_tigcr_ipip_ttlc is unset. + * Access: RW + */ +MLXSW_ITEM32(reg, tigcr, ttl_uc, 0x04, 0, 8); + +static inline void mlxsw_reg_tigcr_pack(char *payload, bool ttlc, u8 ttl_uc) +{ + MLXSW_REG_ZERO(tigcr, payload); + mlxsw_reg_tigcr_ttlc_set(payload, ttlc); + mlxsw_reg_tigcr_ttl_uc_set(payload, ttl_uc); +} + /* SBPR - Shared Buffer Pools Register * ----------------------------------- * The SBPR configures and retrieves the shared buffer pools and configuration. @@ -6881,6 +6911,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mcc), MLXSW_REG(mcda), MLXSW_REG(mgpc), + MLXSW_REG(tigcr), MLXSW_REG(sbpr), MLXSW_REG(sbcm), MLXSW_REG(sbpm), diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c index 2cfb3f5d092d..5189022a1c8c 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c @@ -2723,6 +2723,7 @@ static void mlxsw_sp_nexthop_type_fini(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_nexthop_rif_fini(nh); break; case MLXSW_SP_NEXTHOP_TYPE_IPIP: + mlxsw_sp_nexthop_rif_fini(nh); mlxsw_sp_nexthop_ipip_fini(mlxsw_sp, nh); break; } @@ -2742,7 +2743,11 @@ static int mlxsw_sp_nexthop4_type_init(struct mlxsw_sp *mlxsw_sp, router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev, MLXSW_SP_L3_PROTO_IPV4)) { nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP; - return mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev); + err = mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev); + if (err) + return err; + mlxsw_sp_nexthop_rif_init(nh, &nh->ipip_entry->ol_lb->common); + return 0; } nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH; @@ -3500,20 +3505,6 @@ static int mlxsw_sp_fib_lpm_tree_link(struct mlxsw_sp *mlxsw_sp, static void mlxsw_sp_fib_lpm_tree_unlink(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fib *fib) { - struct mlxsw_sp_prefix_usage req_prefix_usage = {{ 0 } }; - struct mlxsw_sp_lpm_tree *lpm_tree; - - /* Aggregate prefix lengths across all virtual routers to make - * sure we only have used prefix lengths in the LPM tree. - */ - mlxsw_sp_vrs_prefixes(mlxsw_sp, fib->proto, &req_prefix_usage); - lpm_tree = mlxsw_sp_lpm_tree_get(mlxsw_sp, &req_prefix_usage, - fib->proto); - if (IS_ERR(lpm_tree)) - goto err_tree_get; - mlxsw_sp_vrs_lpm_tree_replace(mlxsw_sp, fib, lpm_tree); - -err_tree_get: if (!mlxsw_sp_prefix_usage_none(&fib->prefix_usage)) return; mlxsw_sp_vr_lpm_tree_unbind(mlxsw_sp, fib); @@ -4009,7 +4000,11 @@ static int mlxsw_sp_nexthop6_type_init(struct mlxsw_sp *mlxsw_sp, router->ipip_ops_arr[ipipt]->can_offload(mlxsw_sp, dev, MLXSW_SP_L3_PROTO_IPV6)) { nh->type = MLXSW_SP_NEXTHOP_TYPE_IPIP; - return mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev); + err = mlxsw_sp_nexthop_ipip_init(mlxsw_sp, ipipt, nh, dev); + if (err) + return err; + mlxsw_sp_nexthop_rif_init(nh, &nh->ipip_entry->ol_lb->common); + return 0; } nh->type = MLXSW_SP_NEXTHOP_TYPE_ETH; @@ -5068,6 +5063,7 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, vr = mlxsw_sp_vr_get(mlxsw_sp, tb_id ? : RT_TABLE_MAIN); if (IS_ERR(vr)) return ERR_CAST(vr); + vr->rif_count++; err = mlxsw_sp_rif_index_alloc(mlxsw_sp, &rif_index); if (err) @@ -5099,7 +5095,6 @@ mlxsw_sp_rif_create(struct mlxsw_sp *mlxsw_sp, mlxsw_sp_rif_counters_alloc(rif); mlxsw_sp->router->rifs[rif_index] = rif; - vr->rif_count++; return rif; @@ -5110,6 +5105,7 @@ err_fid_get: kfree(rif); err_rif_alloc: err_rif_index_alloc: + vr->rif_count--; mlxsw_sp_vr_put(vr); return ERR_PTR(err); } @@ -5124,7 +5120,6 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) mlxsw_sp_router_rif_gone_sync(mlxsw_sp, rif); vr = &mlxsw_sp->router->vrs[rif->vr_id]; - vr->rif_count--; mlxsw_sp->router->rifs[rif->rif_index] = NULL; mlxsw_sp_rif_counters_free(rif); ops->deconfigure(rif); @@ -5132,6 +5127,7 @@ void mlxsw_sp_rif_destroy(struct mlxsw_sp_rif *rif) /* Loopback RIFs are not associated with a FID. */ mlxsw_sp_fid_put(fid); kfree(rif); + vr->rif_count--; mlxsw_sp_vr_put(vr); } @@ -5900,11 +5896,20 @@ static void mlxsw_sp_rifs_fini(struct mlxsw_sp *mlxsw_sp) kfree(mlxsw_sp->router->rifs); } +static int +mlxsw_sp_ipip_config_tigcr(struct mlxsw_sp *mlxsw_sp) +{ + char tigcr_pl[MLXSW_REG_TIGCR_LEN]; + + mlxsw_reg_tigcr_pack(tigcr_pl, true, 0); + return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tigcr), tigcr_pl); +} + static int mlxsw_sp_ipips_init(struct mlxsw_sp *mlxsw_sp) { mlxsw_sp->router->ipip_ops_arr = mlxsw_sp_ipip_ops_arr; INIT_LIST_HEAD(&mlxsw_sp->router->ipip_list); - return 0; + return mlxsw_sp_ipip_config_tigcr(mlxsw_sp); } static void mlxsw_sp_ipips_fini(struct mlxsw_sp *mlxsw_sp) diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c index db9750695dc7..8ea9320014ee 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/action.c +++ b/drivers/net/ethernet/netronome/nfp/flower/action.c @@ -110,6 +110,8 @@ nfp_fl_output(struct nfp_fl_output *output, const struct tc_action *action, */ if (!switchdev_port_same_parent_id(in_dev, out_dev)) return -EOPNOTSUPP; + if (!nfp_netdev_is_nfp_repr(out_dev)) + return -EOPNOTSUPP; output->port = cpu_to_be32(nfp_repr_get_port_id(out_dev)); if (!output->port) diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c index 1c0187f0af51..e118b5f23996 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c @@ -1180,10 +1180,14 @@ static void *nfp_net_rx_alloc_one(struct nfp_net_dp *dp, dma_addr_t *dma_addr) { void *frag; - if (!dp->xdp_prog) + if (!dp->xdp_prog) { frag = netdev_alloc_frag(dp->fl_bufsz); - else - frag = page_address(alloc_page(GFP_KERNEL | __GFP_COLD)); + } else { + struct page *page; + + page = alloc_page(GFP_KERNEL | __GFP_COLD); + frag = page ? page_address(page) : NULL; + } if (!frag) { nn_dp_warn(dp, "Failed to alloc receive page frag\n"); return NULL; @@ -1203,10 +1207,14 @@ static void *nfp_net_napi_alloc_one(struct nfp_net_dp *dp, dma_addr_t *dma_addr) { void *frag; - if (!dp->xdp_prog) + if (!dp->xdp_prog) { frag = napi_alloc_frag(dp->fl_bufsz); - else - frag = page_address(alloc_page(GFP_ATOMIC | __GFP_COLD)); + } else { + struct page *page; + + page = alloc_page(GFP_ATOMIC | __GFP_COLD); + frag = page ? page_address(page) : NULL; + } if (!frag) { nn_dp_warn(dp, "Failed to alloc receive page frag\n"); return NULL; diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c index 07969f06df10..dc016dfec64d 100644 --- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c +++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c @@ -464,7 +464,7 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data) do { start = u64_stats_fetch_begin(&nn->r_vecs[i].rx_sync); - *data++ = nn->r_vecs[i].rx_pkts; + data[0] = nn->r_vecs[i].rx_pkts; tmp[0] = nn->r_vecs[i].hw_csum_rx_ok; tmp[1] = nn->r_vecs[i].hw_csum_rx_inner_ok; tmp[2] = nn->r_vecs[i].hw_csum_rx_error; @@ -472,14 +472,16 @@ static u64 *nfp_vnic_get_sw_stats(struct net_device *netdev, u64 *data) do { start = u64_stats_fetch_begin(&nn->r_vecs[i].tx_sync); - *data++ = nn->r_vecs[i].tx_pkts; - *data++ = nn->r_vecs[i].tx_busy; + data[1] = nn->r_vecs[i].tx_pkts; + data[2] = nn->r_vecs[i].tx_busy; tmp[3] = nn->r_vecs[i].hw_csum_tx; tmp[4] = nn->r_vecs[i].hw_csum_tx_inner; tmp[5] = nn->r_vecs[i].tx_gather; tmp[6] = nn->r_vecs[i].tx_lso; } while (u64_stats_fetch_retry(&nn->r_vecs[i].tx_sync, start)); + data += 3; + for (j = 0; j < NN_ET_RVEC_GATHER_STATS; j++) gathered_stats[j] += tmp[j]; } diff --git a/drivers/net/ethernet/qualcomm/emac/emac-mac.c b/drivers/net/ethernet/qualcomm/emac/emac-mac.c index 0ea3ca09c689..3ed9033e56db 100644 --- a/drivers/net/ethernet/qualcomm/emac/emac-mac.c +++ b/drivers/net/ethernet/qualcomm/emac/emac-mac.c @@ -898,7 +898,8 @@ static void emac_mac_rx_descs_refill(struct emac_adapter *adpt, curr_rxbuf->dma_addr = dma_map_single(adpt->netdev->dev.parent, skb->data, - curr_rxbuf->length, DMA_FROM_DEVICE); + adpt->rxbuf_size, DMA_FROM_DEVICE); + ret = dma_mapping_error(adpt->netdev->dev.parent, curr_rxbuf->dma_addr); if (ret) { diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c index 98f22551eb45..1e33aea59f50 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_config.c @@ -51,10 +51,7 @@ struct rmnet_walk_data { static int rmnet_is_real_dev_registered(const struct net_device *real_dev) { - rx_handler_func_t *rx_handler; - - rx_handler = rcu_dereference(real_dev->rx_handler); - return (rx_handler == rmnet_rx_handler); + return rcu_access_pointer(real_dev->rx_handler) == rmnet_rx_handler; } /* Needs rtnl lock */ diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index e03fcf914690..a3c949ea7d1a 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -8491,8 +8491,6 @@ static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) rtl8168_driver_start(tp); } - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - if (pci_dev_run_wake(pdev)) pm_runtime_put_noidle(&pdev->dev); diff --git a/drivers/net/ethernet/rocker/rocker_tlv.h b/drivers/net/ethernet/rocker/rocker_tlv.h index a63ef82e7c72..dfae3c9d57c6 100644 --- a/drivers/net/ethernet/rocker/rocker_tlv.h +++ b/drivers/net/ethernet/rocker/rocker_tlv.h @@ -139,40 +139,52 @@ rocker_tlv_start(struct rocker_desc_info *desc_info) int rocker_tlv_put(struct rocker_desc_info *desc_info, int attrtype, int attrlen, const void *data); -static inline int rocker_tlv_put_u8(struct rocker_desc_info *desc_info, - int attrtype, u8 value) +static inline int +rocker_tlv_put_u8(struct rocker_desc_info *desc_info, int attrtype, u8 value) { - return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &value); + u8 tmp = value; /* work around GCC PR81715 */ + + return rocker_tlv_put(desc_info, attrtype, sizeof(u8), &tmp); } -static inline int rocker_tlv_put_u16(struct rocker_desc_info *desc_info, - int attrtype, u16 value) +static inline int +rocker_tlv_put_u16(struct rocker_desc_info *desc_info, int attrtype, u16 value) { - return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &value); + u16 tmp = value; + + return rocker_tlv_put(desc_info, attrtype, sizeof(u16), &tmp); } -static inline int rocker_tlv_put_be16(struct rocker_desc_info *desc_info, - int attrtype, __be16 value) +static inline int +rocker_tlv_put_be16(struct rocker_desc_info *desc_info, int attrtype, __be16 value) { - return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &value); + __be16 tmp = value; + + return rocker_tlv_put(desc_info, attrtype, sizeof(__be16), &tmp); } -static inline int rocker_tlv_put_u32(struct rocker_desc_info *desc_info, - int attrtype, u32 value) +static inline int +rocker_tlv_put_u32(struct rocker_desc_info *desc_info, int attrtype, u32 value) { - return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &value); + u32 tmp = value; + + return rocker_tlv_put(desc_info, attrtype, sizeof(u32), &tmp); } -static inline int rocker_tlv_put_be32(struct rocker_desc_info *desc_info, - int attrtype, __be32 value) +static inline int +rocker_tlv_put_be32(struct rocker_desc_info *desc_info, int attrtype, __be32 value) { - return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &value); + __be32 tmp = value; + + return rocker_tlv_put(desc_info, attrtype, sizeof(__be32), &tmp); } -static inline int rocker_tlv_put_u64(struct rocker_desc_info *desc_info, - int attrtype, u64 value) +static inline int +rocker_tlv_put_u64(struct rocker_desc_info *desc_info, int attrtype, u64 value) { - return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &value); + u64 tmp = value; + + return rocker_tlv_put(desc_info, attrtype, sizeof(u64), &tmp); } static inline struct rocker_tlv * diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c index dd6a2f9791cc..3256e5cbad27 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c @@ -74,7 +74,7 @@ static int dwc_eth_dwmac_config_dt(struct platform_device *pdev, plat_dat->axi->axi_wr_osr_lmt--; } - if (of_property_read_u32(np, "read,read-requests", + if (of_property_read_u32(np, "snps,read-requests", &plat_dat->axi->axi_rd_osr_lmt)) { /** * Since the register has a reset value of 1, if property @@ -511,6 +511,7 @@ static struct platform_driver dwc_eth_dwmac_driver = { .remove = dwc_eth_dwmac_remove, .driver = { .name = "dwc-eth-dwmac", + .pm = &stmmac_pltfr_pm_ops, .of_match_table = dwc_eth_dwmac_match, }, }; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c index 99823f54696a..13133b30b575 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c @@ -83,6 +83,117 @@ struct rk_priv_data { (((tx) ? soc##_GMAC_TXCLK_DLY_ENABLE : soc##_GMAC_TXCLK_DLY_DISABLE) | \ ((rx) ? soc##_GMAC_RXCLK_DLY_ENABLE : soc##_GMAC_RXCLK_DLY_DISABLE)) +#define RK3128_GRF_MAC_CON0 0x0168 +#define RK3128_GRF_MAC_CON1 0x016c + +/* RK3128_GRF_MAC_CON0 */ +#define RK3128_GMAC_TXCLK_DLY_ENABLE GRF_BIT(14) +#define RK3128_GMAC_TXCLK_DLY_DISABLE GRF_CLR_BIT(14) +#define RK3128_GMAC_RXCLK_DLY_ENABLE GRF_BIT(15) +#define RK3128_GMAC_RXCLK_DLY_DISABLE GRF_CLR_BIT(15) +#define RK3128_GMAC_CLK_RX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 7) +#define RK3128_GMAC_CLK_TX_DL_CFG(val) HIWORD_UPDATE(val, 0x7F, 0) + +/* RK3128_GRF_MAC_CON1 */ +#define RK3128_GMAC_PHY_INTF_SEL_RGMII \ + (GRF_BIT(6) | GRF_CLR_BIT(7) | GRF_CLR_BIT(8)) +#define RK3128_GMAC_PHY_INTF_SEL_RMII \ + (GRF_CLR_BIT(6) | GRF_CLR_BIT(7) | GRF_BIT(8)) +#define RK3128_GMAC_FLOW_CTRL GRF_BIT(9) +#define RK3128_GMAC_FLOW_CTRL_CLR GRF_CLR_BIT(9) +#define RK3128_GMAC_SPEED_10M GRF_CLR_BIT(10) +#define RK3128_GMAC_SPEED_100M GRF_BIT(10) +#define RK3128_GMAC_RMII_CLK_25M GRF_BIT(11) +#define RK3128_GMAC_RMII_CLK_2_5M GRF_CLR_BIT(11) +#define RK3128_GMAC_CLK_125M (GRF_CLR_BIT(12) | GRF_CLR_BIT(13)) +#define RK3128_GMAC_CLK_25M (GRF_BIT(12) | GRF_BIT(13)) +#define RK3128_GMAC_CLK_2_5M (GRF_CLR_BIT(12) | GRF_BIT(13)) +#define RK3128_GMAC_RMII_MODE GRF_BIT(14) +#define RK3128_GMAC_RMII_MODE_CLR GRF_CLR_BIT(14) + +static void rk3128_set_to_rgmii(struct rk_priv_data *bsp_priv, + int tx_delay, int rx_delay) +{ + struct device *dev = &bsp_priv->pdev->dev; + + if (IS_ERR(bsp_priv->grf)) { + dev_err(dev, "Missing rockchip,grf property\n"); + return; + } + + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, + RK3128_GMAC_PHY_INTF_SEL_RGMII | + RK3128_GMAC_RMII_MODE_CLR); + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON0, + DELAY_ENABLE(RK3128, tx_delay, rx_delay) | + RK3128_GMAC_CLK_RX_DL_CFG(rx_delay) | + RK3128_GMAC_CLK_TX_DL_CFG(tx_delay)); +} + +static void rk3128_set_to_rmii(struct rk_priv_data *bsp_priv) +{ + struct device *dev = &bsp_priv->pdev->dev; + + if (IS_ERR(bsp_priv->grf)) { + dev_err(dev, "Missing rockchip,grf property\n"); + return; + } + + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, + RK3128_GMAC_PHY_INTF_SEL_RMII | RK3128_GMAC_RMII_MODE); +} + +static void rk3128_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed) +{ + struct device *dev = &bsp_priv->pdev->dev; + + if (IS_ERR(bsp_priv->grf)) { + dev_err(dev, "Missing rockchip,grf property\n"); + return; + } + + if (speed == 10) + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, + RK3128_GMAC_CLK_2_5M); + else if (speed == 100) + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, + RK3128_GMAC_CLK_25M); + else if (speed == 1000) + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, + RK3128_GMAC_CLK_125M); + else + dev_err(dev, "unknown speed value for RGMII! speed=%d", speed); +} + +static void rk3128_set_rmii_speed(struct rk_priv_data *bsp_priv, int speed) +{ + struct device *dev = &bsp_priv->pdev->dev; + + if (IS_ERR(bsp_priv->grf)) { + dev_err(dev, "Missing rockchip,grf property\n"); + return; + } + + if (speed == 10) { + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, + RK3128_GMAC_RMII_CLK_2_5M | + RK3128_GMAC_SPEED_10M); + } else if (speed == 100) { + regmap_write(bsp_priv->grf, RK3128_GRF_MAC_CON1, + RK3128_GMAC_RMII_CLK_25M | + RK3128_GMAC_SPEED_100M); + } else { + dev_err(dev, "unknown speed value for RMII! speed=%d", speed); + } +} + +static const struct rk_gmac_ops rk3128_ops = { + .set_to_rgmii = rk3128_set_to_rgmii, + .set_to_rmii = rk3128_set_to_rmii, + .set_rgmii_speed = rk3128_set_rgmii_speed, + .set_rmii_speed = rk3128_set_rmii_speed, +}; + #define RK3228_GRF_MAC_CON0 0x0900 #define RK3228_GRF_MAC_CON1 0x0904 @@ -1313,6 +1424,7 @@ static int rk_gmac_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(rk_gmac_pm_ops, rk_gmac_suspend, rk_gmac_resume); static const struct of_device_id rk_gmac_dwmac_match[] = { + { .compatible = "rockchip,rk3128-gmac", .data = &rk3128_ops }, { .compatible = "rockchip,rk3228-gmac", .data = &rk3228_ops }, { .compatible = "rockchip,rk3288-gmac", .data = &rk3288_ops }, { .compatible = "rockchip,rk3328-gmac", .data = &rk3328_ops }, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c index c4407e8e39a3..2f7d7ec59962 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c @@ -296,6 +296,7 @@ static void dwmac4_pmt(struct mac_device_info *hw, unsigned long mode) { void __iomem *ioaddr = hw->pcsr; unsigned int pmt = 0; + u32 config; if (mode & WAKE_MAGIC) { pr_debug("GMAC: WOL Magic frame\n"); @@ -306,6 +307,12 @@ static void dwmac4_pmt(struct mac_device_info *hw, unsigned long mode) pmt |= power_down | global_unicast | wake_up_frame_en; } + if (pmt) { + /* The receiver must be enabled for WOL before powering down */ + config = readl(ioaddr + GMAC_CONFIG); + config |= GMAC_CONFIG_RE; + writel(config, ioaddr + GMAC_CONFIG); + } writel(pmt, ioaddr + GMAC_PMT); } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c index e0ef02f9503b..4b286e27c4ca 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.c @@ -275,7 +275,7 @@ static int dwmac4_wrback_get_rx_timestamp_status(void *desc, u32 ats) goto exit; i++; - } while ((ret == 1) || (i < 10)); + } while ((ret == 1) && (i < 10)); if (i == 10) ret = -EBUSY; diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c index 67af0bdd7f10..7516ca210855 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac_lib.c @@ -34,7 +34,7 @@ int dwmac_dma_reset(void __iomem *ioaddr) err = readl_poll_timeout(ioaddr + DMA_BUS_MODE, value, !(value & DMA_BUS_MODE_SFT_RESET), - 100000, 10000); + 10000, 100000); if (err) return -EBUSY; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 1763e48c84e2..16bd50929084 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -473,19 +473,18 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p, struct dma_desc *np, struct sk_buff *skb) { struct skb_shared_hwtstamps *shhwtstamp = NULL; + struct dma_desc *desc = p; u64 ns; if (!priv->hwts_rx_en) return; + /* For GMAC4, the valid timestamp is from CTX next desc. */ + if (priv->plat->has_gmac4) + desc = np; /* Check if timestamp is available */ - if (priv->hw->desc->get_rx_timestamp_status(p, priv->adv_ts)) { - /* For GMAC4, the valid timestamp is from CTX next desc. */ - if (priv->plat->has_gmac4) - ns = priv->hw->desc->get_timestamp(np, priv->adv_ts); - else - ns = priv->hw->desc->get_timestamp(p, priv->adv_ts); - + if (priv->hw->desc->get_rx_timestamp_status(desc, priv->adv_ts)) { + ns = priv->hw->desc->get_timestamp(desc, priv->adv_ts); netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns); shhwtstamp = skb_hwtstamps(skb); memset(shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps)); @@ -1800,12 +1799,13 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue) { struct stmmac_tx_queue *tx_q = &priv->tx_queue[queue]; unsigned int bytes_compl = 0, pkts_compl = 0; - unsigned int entry = tx_q->dirty_tx; + unsigned int entry; netif_tx_lock(priv->dev); priv->xstats.tx_clean++; + entry = tx_q->dirty_tx; while (entry != tx_q->cur_tx) { struct sk_buff *skb = tx_q->tx_skbuff[entry]; struct dma_desc *p; @@ -3333,6 +3333,7 @@ static int stmmac_rx(struct stmmac_priv *priv, int limit, u32 queue) * them in stmmac_rx_refill() function so that * device can reuse it. */ + dev_kfree_skb_any(rx_q->rx_skbuff[entry]); rx_q->rx_skbuff[entry] = NULL; dma_unmap_single(priv->device, rx_q->rx_skbuff_dma[entry], diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index 8a280b48e3a9..6383695004a5 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -150,6 +150,13 @@ static void stmmac_mtl_setup(struct platform_device *pdev, plat->rx_queues_to_use = 1; plat->tx_queues_to_use = 1; + /* First Queue must always be in DCB mode. As MTL_QUEUE_DCB = 1 we need + * to always set this, otherwise Queue will be classified as AVB + * (because MTL_QUEUE_AVB = 0). + */ + plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB; + plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB; + rx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-rx-config", 0); if (!rx_node) return; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index f6404074b7b0..ed51018a813e 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -113,13 +113,7 @@ static void tunnel_id_to_vni(__be64 tun_id, __u8 *vni) static bool eq_tun_id_and_vni(u8 *tun_id, u8 *vni) { -#ifdef __BIG_ENDIAN - return (vni[0] == tun_id[2]) && - (vni[1] == tun_id[1]) && - (vni[2] == tun_id[0]); -#else return !memcmp(vni, &tun_id[5], 3); -#endif } static sa_family_t geneve_get_sk_family(struct geneve_sock *gs) diff --git a/drivers/net/ipvlan/ipvtap.c b/drivers/net/ipvlan/ipvtap.c index 5dea2063dbc8..0bcc07f346c3 100644 --- a/drivers/net/ipvlan/ipvtap.c +++ b/drivers/net/ipvlan/ipvtap.c @@ -197,8 +197,8 @@ static int ipvtap_init(void) { int err; - err = tap_create_cdev(&ipvtap_cdev, &ipvtap_major, "ipvtap"); - + err = tap_create_cdev(&ipvtap_cdev, &ipvtap_major, "ipvtap", + THIS_MODULE); if (err) goto out1; diff --git a/drivers/net/macsec.c b/drivers/net/macsec.c index 98e4deaa3a6a..5ab1b8849c30 100644 --- a/drivers/net/macsec.c +++ b/drivers/net/macsec.c @@ -742,6 +742,7 @@ static struct sk_buff *macsec_encrypt(struct sk_buff *skb, sg_init_table(sg, ret); ret = skb_to_sgvec(skb, sg, 0, skb->len); if (unlikely(ret < 0)) { + aead_request_free(req); macsec_txsa_put(tx_sa); kfree_skb(skb); return ERR_PTR(ret); @@ -954,6 +955,7 @@ static struct sk_buff *macsec_decrypt(struct sk_buff *skb, sg_init_table(sg, ret); ret = skb_to_sgvec(skb, sg, 0, skb->len); if (unlikely(ret < 0)) { + aead_request_free(req); kfree_skb(skb); return ERR_PTR(ret); } diff --git a/drivers/net/macvtap.c b/drivers/net/macvtap.c index c2d0ea2fb019..cba5cb3b849a 100644 --- a/drivers/net/macvtap.c +++ b/drivers/net/macvtap.c @@ -204,8 +204,8 @@ static int macvtap_init(void) { int err; - err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap"); - + err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap", + THIS_MODULE); if (err) goto out1; diff --git a/drivers/net/ppp/ppp_generic.c b/drivers/net/ppp/ppp_generic.c index a404552555d4..e365866600ba 100644 --- a/drivers/net/ppp/ppp_generic.c +++ b/drivers/net/ppp/ppp_generic.c @@ -120,7 +120,7 @@ struct ppp { int n_channels; /* how many channels are attached 54 */ spinlock_t rlock; /* lock for receive side 58 */ spinlock_t wlock; /* lock for transmit side 5c */ - int *xmit_recursion __percpu; /* xmit recursion detect */ + int __percpu *xmit_recursion; /* xmit recursion detect */ int mru; /* max receive unit 60 */ unsigned int flags; /* control bits 64 */ unsigned int xstate; /* transmit state bits 68 */ @@ -1339,7 +1339,17 @@ ppp_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats64) static int ppp_dev_init(struct net_device *dev) { + struct ppp *ppp; + netdev_lockdep_set_classes(dev); + + ppp = netdev_priv(dev); + /* Let the netdevice take a reference on the ppp file. This ensures + * that ppp_destroy_interface() won't run before the device gets + * unregistered. + */ + atomic_inc(&ppp->file.refcnt); + return 0; } @@ -1362,6 +1372,15 @@ static void ppp_dev_uninit(struct net_device *dev) wake_up_interruptible(&ppp->file.rwait); } +static void ppp_dev_priv_destructor(struct net_device *dev) +{ + struct ppp *ppp; + + ppp = netdev_priv(dev); + if (atomic_dec_and_test(&ppp->file.refcnt)) + ppp_destroy_interface(ppp); +} + static const struct net_device_ops ppp_netdev_ops = { .ndo_init = ppp_dev_init, .ndo_uninit = ppp_dev_uninit, @@ -1387,6 +1406,7 @@ static void ppp_setup(struct net_device *dev) dev->tx_queue_len = 3; dev->type = ARPHRD_PPP; dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST; + dev->priv_destructor = ppp_dev_priv_destructor; netif_keep_dst(dev); } diff --git a/drivers/net/tap.c b/drivers/net/tap.c index 21b71ae947fd..1b10fcc6a58d 100644 --- a/drivers/net/tap.c +++ b/drivers/net/tap.c @@ -517,6 +517,10 @@ static int tap_open(struct inode *inode, struct file *file) &tap_proto, 0); if (!q) goto err; + if (skb_array_init(&q->skb_array, tap->dev->tx_queue_len, GFP_KERNEL)) { + sk_free(&q->sk); + goto err; + } RCU_INIT_POINTER(q->sock.wq, &q->wq); init_waitqueue_head(&q->wq.wait); @@ -540,22 +544,18 @@ static int tap_open(struct inode *inode, struct file *file) if ((tap->dev->features & NETIF_F_HIGHDMA) && (tap->dev->features & NETIF_F_SG)) sock_set_flag(&q->sk, SOCK_ZEROCOPY); - err = -ENOMEM; - if (skb_array_init(&q->skb_array, tap->dev->tx_queue_len, GFP_KERNEL)) - goto err_array; - err = tap_set_queue(tap, file, q); - if (err) - goto err_queue; + if (err) { + /* tap_sock_destruct() will take care of freeing skb_array */ + goto err_put; + } dev_put(tap->dev); rtnl_unlock(); return err; -err_queue: - skb_array_cleanup(&q->skb_array); -err_array: +err_put: sock_put(&q->sk); err: if (tap) @@ -1249,8 +1249,8 @@ static int tap_list_add(dev_t major, const char *device_name) return 0; } -int tap_create_cdev(struct cdev *tap_cdev, - dev_t *tap_major, const char *device_name) +int tap_create_cdev(struct cdev *tap_cdev, dev_t *tap_major, + const char *device_name, struct module *module) { int err; @@ -1259,6 +1259,7 @@ int tap_create_cdev(struct cdev *tap_cdev, goto out1; cdev_init(tap_cdev, &tap_fops); + tap_cdev->owner = module; err = cdev_add(tap_cdev, *tap_major, TAP_NUM_DEVS); if (err) goto out2; diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 3c9985f29950..5550f56cb895 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1286,6 +1286,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun, buflen += SKB_DATA_ALIGN(len + pad); rcu_read_unlock(); + alloc_frag->offset = ALIGN((u64)alloc_frag->offset, SMP_CACHE_BYTES); if (unlikely(!skb_page_frag_refill(buflen, alloc_frag, GFP_KERNEL))) return ERR_PTR(-ENOMEM); @@ -1496,11 +1497,13 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, switch (tun->flags & TUN_TYPE_MASK) { case IFF_TUN: if (tun->flags & IFF_NO_PI) { - switch (skb->data[0] & 0xf0) { - case 0x40: + u8 ip_version = skb->len ? (skb->data[0] >> 4) : 0; + + switch (ip_version) { + case 4: pi.proto = htons(ETH_P_IP); break; - case 0x60: + case 6: pi.proto = htons(ETH_P_IPV6); break; default: @@ -2025,6 +2028,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) if (!dev) return -ENOMEM; + err = dev_get_valid_name(net, dev, name); + if (err < 0) + goto err_free_dev; dev_net_set(dev, net); dev->rtnl_link_ops = &tun_link_ops; diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 8ab281b478f2..3e7a3ac3a362 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -54,11 +54,19 @@ static int is_wireless_rndis(struct usb_interface_descriptor *desc) desc->bInterfaceProtocol == 3); } +static int is_novatel_rndis(struct usb_interface_descriptor *desc) +{ + return (desc->bInterfaceClass == USB_CLASS_MISC && + desc->bInterfaceSubClass == 4 && + desc->bInterfaceProtocol == 1); +} + #else #define is_rndis(desc) 0 #define is_activesync(desc) 0 #define is_wireless_rndis(desc) 0 +#define is_novatel_rndis(desc) 0 #endif @@ -150,7 +158,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf) */ rndis = (is_rndis(&intf->cur_altsetting->desc) || is_activesync(&intf->cur_altsetting->desc) || - is_wireless_rndis(&intf->cur_altsetting->desc)); + is_wireless_rndis(&intf->cur_altsetting->desc) || + is_novatel_rndis(&intf->cur_altsetting->desc)); memset(info, 0, sizeof(*info)); info->control = intf; @@ -547,9 +556,12 @@ static const struct driver_info wwan_info = { #define REALTEK_VENDOR_ID 0x0bda #define SAMSUNG_VENDOR_ID 0x04e8 #define LENOVO_VENDOR_ID 0x17ef +#define LINKSYS_VENDOR_ID 0x13b1 #define NVIDIA_VENDOR_ID 0x0955 #define HP_VENDOR_ID 0x03f0 #define MICROSOFT_VENDOR_ID 0x045e +#define UBLOX_VENDOR_ID 0x1546 +#define TPLINK_VENDOR_ID 0x2357 static const struct usb_device_id products[] = { /* BLACKLIST !! @@ -737,6 +749,15 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, +#if IS_ENABLED(CONFIG_USB_RTL8152) +/* Linksys USB3GIGV1 Ethernet Adapter */ +{ + USB_DEVICE_AND_INTERFACE_INFO(LINKSYS_VENDOR_ID, 0x0041, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, +#endif + /* ThinkPad USB-C Dock (based on Realtek RTL8153) */ { USB_DEVICE_AND_INTERFACE_INFO(LENOVO_VENDOR_ID, 0x3062, USB_CLASS_COMM, @@ -793,6 +814,13 @@ static const struct usb_device_id products[] = { .driver_info = 0, }, + /* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */ +{ + USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* WHITELIST!!! * * CDC Ether uses two interfaces, not necessarily consecutive. @@ -844,12 +872,30 @@ static const struct usb_device_id products[] = { USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (kernel_ulong_t)&wwan_info, }, { + /* Huawei ME906 and ME909 */ + USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x15c1, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_info, +}, { /* ZTE modules */ USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long)&zte_cdc_info, }, { + /* U-blox TOBY-L2 */ + USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1143, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_info, +}, { + /* U-blox SARA-U2 */ + USB_DEVICE_AND_INTERFACE_INFO(UBLOX_VENDOR_ID, 0x1104, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, + USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_info, +}, { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), .driver_info = (unsigned long) &cdc_info, diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index ceb78e2ea4f0..d51d9abf7986 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -613,7 +613,9 @@ enum rtl8152_flags { #define VENDOR_ID_MICROSOFT 0x045e #define VENDOR_ID_SAMSUNG 0x04e8 #define VENDOR_ID_LENOVO 0x17ef +#define VENDOR_ID_LINKSYS 0x13b1 #define VENDOR_ID_NVIDIA 0x0955 +#define VENDOR_ID_TPLINK 0x2357 #define MCU_TYPE_PLA 0x0100 #define MCU_TYPE_USB 0x0000 @@ -5316,7 +5318,9 @@ static const struct usb_device_id rtl8152_table[] = { {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7205)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x720c)}, {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO, 0x7214)}, + {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)}, {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA, 0x09ff)}, + {REALTEK_USB_DEVICE(VENDOR_ID_TPLINK, 0x0601)}, {} }; diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index a151f267aebb..b807c91abe1d 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -632,6 +632,10 @@ static const struct usb_device_id products [] = { /* RNDIS for tethering */ USB_INTERFACE_INFO(USB_CLASS_WIRELESS_CONTROLLER, 1, 3), .driver_info = (unsigned long) &rndis_info, +}, { + /* Novatel Verizon USB730L */ + USB_INTERFACE_INFO(USB_CLASS_MISC, 4, 1), + .driver_info = (unsigned long) &rndis_info, }, { }, // END }; diff --git a/drivers/net/wimax/i2400m/fw.c b/drivers/net/wimax/i2400m/fw.c index c9c711dcd0e6..a89b5685e68b 100644 --- a/drivers/net/wimax/i2400m/fw.c +++ b/drivers/net/wimax/i2400m/fw.c @@ -652,7 +652,7 @@ static int i2400m_download_chunk(struct i2400m *i2400m, const void *chunk, struct device *dev = i2400m_dev(i2400m); struct { struct i2400m_bootrom_header cmd; - u8 cmd_payload[chunk_len]; + u8 cmd_payload[]; } __packed *buf; struct i2400m_bootrom_header ack; diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index bc1633945a56..195dafb98131 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3396,9 +3396,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev) MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table); -#ifdef CONFIG_PM - -static int ath10k_pci_pm_suspend(struct device *dev) +static __maybe_unused int ath10k_pci_pm_suspend(struct device *dev) { struct ath10k *ar = dev_get_drvdata(dev); int ret; @@ -3414,7 +3412,7 @@ static int ath10k_pci_pm_suspend(struct device *dev) return ret; } -static int ath10k_pci_pm_resume(struct device *dev) +static __maybe_unused int ath10k_pci_pm_resume(struct device *dev) { struct ath10k *ar = dev_get_drvdata(dev); int ret; @@ -3433,7 +3431,6 @@ static int ath10k_pci_pm_resume(struct device *dev) static SIMPLE_DEV_PM_OPS(ath10k_pci_pm_ops, ath10k_pci_pm_suspend, ath10k_pci_pm_resume); -#endif static struct pci_driver ath10k_pci_driver = { .name = "ath10k_pci", diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index aaed4ab503ad..4157c90ad973 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -980,7 +980,7 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, eth_broadcast_addr(params_le->bssid); params_le->bss_type = DOT11_BSSTYPE_ANY; - params_le->scan_type = 0; + params_le->scan_type = BRCMF_SCANTYPE_ACTIVE; params_le->channel_num = 0; params_le->nprobes = cpu_to_le32(-1); params_le->active_time = cpu_to_le32(-1); @@ -988,12 +988,9 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, params_le->home_time = cpu_to_le32(-1); memset(¶ms_le->ssid_le, 0, sizeof(params_le->ssid_le)); - /* if request is null exit so it will be all channel broadcast scan */ - if (!request) - return; - n_ssids = request->n_ssids; n_channels = request->n_channels; + /* Copy channel array if applicable */ brcmf_dbg(SCAN, "### List of channelspecs to scan ### %d\n", n_channels); @@ -1030,16 +1027,8 @@ static void brcmf_escan_prep(struct brcmf_cfg80211_info *cfg, ptr += sizeof(ssid_le); } } else { - brcmf_dbg(SCAN, "Broadcast scan %p\n", request->ssids); - if ((request->ssids) && request->ssids->ssid_len) { - brcmf_dbg(SCAN, "SSID %s len=%d\n", - params_le->ssid_le.SSID, - request->ssids->ssid_len); - params_le->ssid_le.SSID_len = - cpu_to_le32(request->ssids->ssid_len); - memcpy(¶ms_le->ssid_le.SSID, request->ssids->ssid, - request->ssids->ssid_len); - } + brcmf_dbg(SCAN, "Performing passive scan\n"); + params_le->scan_type = BRCMF_SCANTYPE_PASSIVE; } /* Adding mask to channel numbers */ params_le->channel_num = @@ -3162,6 +3151,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, struct brcmf_cfg80211_info *cfg = ifp->drvr->config; s32 status; struct brcmf_escan_result_le *escan_result_le; + u32 escan_buflen; struct brcmf_bss_info_le *bss_info_le; struct brcmf_bss_info_le *bss = NULL; u32 bi_length; @@ -3181,11 +3171,23 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, if (status == BRCMF_E_STATUS_PARTIAL) { brcmf_dbg(SCAN, "ESCAN Partial result\n"); + if (e->datalen < sizeof(*escan_result_le)) { + brcmf_err("invalid event data length\n"); + goto exit; + } escan_result_le = (struct brcmf_escan_result_le *) data; if (!escan_result_le) { brcmf_err("Invalid escan result (NULL pointer)\n"); goto exit; } + escan_buflen = le32_to_cpu(escan_result_le->buflen); + if (escan_buflen > BRCMF_ESCAN_BUF_SIZE || + escan_buflen > e->datalen || + escan_buflen < sizeof(*escan_result_le)) { + brcmf_err("Invalid escan buffer length: %d\n", + escan_buflen); + goto exit; + } if (le16_to_cpu(escan_result_le->bss_count) != 1) { brcmf_err("Invalid bss_count %d: ignoring\n", escan_result_le->bss_count); @@ -3202,9 +3204,8 @@ brcmf_cfg80211_escan_handler(struct brcmf_if *ifp, } bi_length = le32_to_cpu(bss_info_le->length); - if (bi_length != (le32_to_cpu(escan_result_le->buflen) - - WL_ESCAN_RESULTS_FIXED_SIZE)) { - brcmf_err("Invalid bss_info length %d: ignoring\n", + if (bi_length != escan_buflen - WL_ESCAN_RESULTS_FIXED_SIZE) { + brcmf_err("Ignoring invalid bss_info length: %d\n", bi_length); goto exit; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c index 4eb1e1ce9ace..ef72baf6dd96 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c @@ -429,7 +429,8 @@ void brcmf_fweh_process_event(struct brcmf_pub *drvr, if (code != BRCMF_E_IF && !fweh->evt_handler[code]) return; - if (datalen > BRCMF_DCMD_MAXLEN) + if (datalen > BRCMF_DCMD_MAXLEN || + datalen + sizeof(*event_packet) > packet_len) return; if (in_interrupt()) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h index 8391989b1882..e0d22fedb2b4 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h @@ -45,6 +45,11 @@ #define BRCMF_SCAN_PARAMS_COUNT_MASK 0x0000ffff #define BRCMF_SCAN_PARAMS_NSSID_SHIFT 16 +/* scan type definitions */ +#define BRCMF_SCANTYPE_DEFAULT 0xFF +#define BRCMF_SCANTYPE_ACTIVE 0 +#define BRCMF_SCANTYPE_PASSIVE 1 + #define BRCMF_WSEC_MAX_PSK_LEN 32 #define BRCMF_WSEC_PASSPHRASE BIT(0) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c index b3aab2fe96eb..ef685465f80a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c @@ -14764,8 +14764,8 @@ static void wlc_phy_ipa_restore_tx_digi_filts_nphy(struct brcms_phy *pi) } static void -wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, u8 *events, u8 *dlys, - u8 len) +wlc_phy_set_rfseq_nphy(struct brcms_phy *pi, u8 cmd, const u8 *events, + const u8 *dlys, u8 len) { u32 t1_offset, t2_offset; u8 ctr; @@ -15240,16 +15240,16 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(struct brcms_phy *pi) static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) { u16 currband; - s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; - s8 *lna1_gain_db = NULL; - s8 *lna1_gain_db_2 = NULL; - s8 *lna2_gain_db = NULL; - s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; - s8 *tia_gain_db; - s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; - s8 *tia_gainbits; - u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; - u16 *rfseq_init_gain; + static const s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 }; + const s8 *lna1_gain_db = NULL; + const s8 *lna1_gain_db_2 = NULL; + const s8 *lna2_gain_db = NULL; + static const s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 }; + const s8 *tia_gain_db; + static const s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 }; + const s8 *tia_gainbits; + static const u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f }; + const u16 *rfseq_init_gain; u16 init_gaincode; u16 clip1hi_gaincode; u16 clip1md_gaincode = 0; @@ -15310,10 +15310,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) if ((freq <= 5080) || (freq == 5825)) { - s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; - s8 lna1A_gain_db_2_rev7[] = { - 11, 17, 22, 25}; - s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; + static const s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 }; + static const s8 lna1A_gain_db_2_rev7[] = { 11, 17, 22, 25}; + static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; crsminu_th = 0x3e; lna1_gain_db = lna1A_gain_db_rev7; @@ -15321,10 +15320,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) lna2_gain_db = lna2A_gain_db_rev7; } else if ((freq >= 5500) && (freq <= 5700)) { - s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; - s8 lna1A_gain_db_2_rev7[] = { - 12, 18, 22, 26}; - s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; + static const s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 }; + static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26}; + static const s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 }; crsminu_th = 0x45; clip1md_gaincode_B = 0x14; @@ -15335,10 +15333,9 @@ static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(struct brcms_phy *pi) lna2_gain_db = lna2A_gain_db_rev7; } else { - s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; - s8 lna1A_gain_db_2_rev7[] = { - 12, 18, 22, 26}; - s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; + static const s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 }; + static const s8 lna1A_gain_db_2_rev7[] = { 12, 18, 22, 26}; + static const s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 }; crsminu_th = 0x41; lna1_gain_db = lna1A_gain_db_rev7; @@ -15450,65 +15447,65 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) NPHY_RFSEQ_CMD_CLR_HIQ_DIS, NPHY_RFSEQ_CMD_SET_HPF_BW }; - u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; - s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; - s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; - s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; - s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; - s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; - s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; - s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; - s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; - s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; - s8 *lna1_gain_db = NULL; - s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; - s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; - s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; - s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; - s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; - s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; - s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; - s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; - s8 *lna2_gain_db = NULL; - s8 tiaG_gain_db[] = { + static const u8 rfseq_updategainu_dlys[] = { 10, 30, 1 }; + static const s8 lna1G_gain_db[] = { 7, 11, 16, 23 }; + static const s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 }; + static const s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 }; + static const s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 }; + static const s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 }; + static const s8 lna1A_gain_db[] = { 7, 11, 17, 23 }; + static const s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 }; + static const s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 }; + static const s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 }; + const s8 *lna1_gain_db = NULL; + static const s8 lna2G_gain_db[] = { -5, 6, 10, 14 }; + static const s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 }; + static const s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 }; + static const s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 }; + static const s8 lna2A_gain_db[] = { -6, 2, 6, 10 }; + static const s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 }; + static const s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 }; + static const s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 }; + const s8 *lna2_gain_db = NULL; + static const s8 tiaG_gain_db[] = { 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A }; - s8 tiaA_gain_db[] = { + static const s8 tiaA_gain_db[] = { 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 }; - s8 tiaA_gain_db_rev4[] = { + static const s8 tiaA_gain_db_rev4[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - s8 tiaA_gain_db_rev5[] = { + static const s8 tiaA_gain_db_rev5[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - s8 tiaA_gain_db_rev6[] = { + static const s8 tiaA_gain_db_rev6[] = { 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d }; - s8 *tia_gain_db; - s8 tiaG_gainbits[] = { + const s8 *tia_gain_db; + static const s8 tiaG_gainbits[] = { 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 }; - s8 tiaA_gainbits[] = { + static const s8 tiaA_gainbits[] = { 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 }; - s8 tiaA_gainbits_rev4[] = { + static const s8 tiaA_gainbits_rev4[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - s8 tiaA_gainbits_rev5[] = { + static const s8 tiaA_gainbits_rev5[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - s8 tiaA_gainbits_rev6[] = { + static const s8 tiaA_gainbits_rev6[] = { 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - s8 *tia_gainbits; - s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; - s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; - u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; - u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; - u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; - u16 rfseqG_init_gain_rev5_elna[] = { + const s8 *tia_gainbits; + static const s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 }; + static const s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 }; + static const u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f }; + static const u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f }; + static const u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f }; + static const u16 rfseqG_init_gain_rev5_elna[] = { 0x013f, 0x013f, 0x013f, 0x013f }; - u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; - u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; - u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; - u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; - u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; - u16 rfseqA_init_gain_rev4_elna[] = { + static const u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f }; + static const u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f }; + static const u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f }; + static const u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f }; + static const u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f }; + static const u16 rfseqA_init_gain_rev4_elna[] = { 0x314f, 0x314f, 0x314f, 0x314f }; - u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; - u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; - u16 *rfseq_init_gain; + static const u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f }; + static const u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f }; + const u16 *rfseq_init_gain; u16 initG_gaincode = 0x627e; u16 initG_gaincode_rev4 = 0x527e; u16 initG_gaincode_rev5 = 0x427e; @@ -15538,10 +15535,10 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) u16 clip1mdA_gaincode_rev6 = 0x2084; u16 clip1md_gaincode = 0; u16 clip1loG_gaincode = 0x0074; - u16 clip1loG_gaincode_rev5[] = { + static const u16 clip1loG_gaincode_rev5[] = { 0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c }; - u16 clip1loG_gaincode_rev6[] = { + static const u16 clip1loG_gaincode_rev6[] = { 0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e }; u16 clip1loG_gaincode_rev6_224B0 = 0x1074; @@ -16066,7 +16063,7 @@ static void wlc_phy_workarounds_nphy_gainctrl(struct brcms_phy *pi) static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) { - u8 rfseq_rx2tx_events[] = { + static const u8 rfseq_rx2tx_events[] = { NPHY_RFSEQ_CMD_NOP, NPHY_RFSEQ_CMD_RXG_FBW, NPHY_RFSEQ_CMD_TR_SWITCH, @@ -16076,7 +16073,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_RFSEQ_CMD_EXT_PA }; u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 }; - u8 rfseq_tx2rx_events[] = { + static const u8 rfseq_tx2rx_events[] = { NPHY_RFSEQ_CMD_NOP, NPHY_RFSEQ_CMD_EXT_PA, NPHY_RFSEQ_CMD_TX_GAIN, @@ -16085,8 +16082,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_RFSEQ_CMD_RXG_FBW, NPHY_RFSEQ_CMD_CLR_HIQ_DIS }; - u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; - u8 rfseq_tx2rx_events_rev3[] = { + static const u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 }; + static const u8 rfseq_tx2rx_events_rev3[] = { NPHY_REV3_RFSEQ_CMD_EXT_PA, NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_TX_GAIN, @@ -16096,7 +16093,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS, NPHY_REV3_RFSEQ_CMD_END }; - u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; + static const u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 }; u8 rfseq_rx2tx_events_rev3[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW, @@ -16110,7 +16107,7 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) }; u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 }; - u8 rfseq_rx2tx_events_rev3_ipa[] = { + static const u8 rfseq_rx2tx_events_rev3_ipa[] = { NPHY_REV3_RFSEQ_CMD_NOP, NPHY_REV3_RFSEQ_CMD_RXG_FBW, NPHY_REV3_RFSEQ_CMD_TR_SWITCH, @@ -16121,15 +16118,15 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) NPHY_REV3_RFSEQ_CMD_INT_PA_PU, NPHY_REV3_RFSEQ_CMD_END }; - u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; - u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; + static const u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 }; + static const u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f }; s16 alpha0, alpha1, alpha2; s16 beta0, beta1, beta2; u32 leg_data_weights, ht_data_weights, nss1_data_weights, stbc_data_weights; u8 chan_freq_range = 0; - u16 dac_control = 0x0002; + static const u16 dac_control = 0x0002; u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 }; u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 }; u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 }; @@ -16139,8 +16136,8 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 }; u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 }; u16 *aux_adc_gain; - u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; - u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; + static const u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 }; + static const u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 }; s32 min_nvar_val = 0x18d; s32 min_nvar_offset_6mbps = 20; u8 pdetrange; @@ -16151,9 +16148,9 @@ static void wlc_phy_workarounds_nphy(struct brcms_phy *pi) u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77; u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77; u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77; - u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; - u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; - u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; + static const u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 }; + static const u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; + static const u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 }; u16 ipalvlshift_3p3_war_en = 0; u16 rccal_bcap_val, rccal_scap_val; u16 rccal_tx20_11b_bcap = 0; @@ -24291,13 +24288,13 @@ static void wlc_phy_update_txcal_ladder_nphy(struct brcms_phy *pi, u16 core) u16 bbmult; u16 tblentry; - struct nphy_txiqcal_ladder ladder_lo[] = { + static const struct nphy_txiqcal_ladder ladder_lo[] = { {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, {25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5}, {25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7} }; - struct nphy_txiqcal_ladder ladder_iq[] = { + static const struct nphy_txiqcal_ladder ladder_iq[] = { {3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0}, {25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1}, {100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7} @@ -25773,67 +25770,67 @@ wlc_phy_cal_txiqlo_nphy(struct brcms_phy *pi, struct nphy_txgains target_gain, u16 cal_gain[2]; struct nphy_iqcal_params cal_params[2]; u32 tbl_len; - void *tbl_ptr; + const void *tbl_ptr; bool ladder_updated[2]; u8 mphase_cal_lastphase = 0; int bcmerror = 0; bool phyhang_avoid_state = false; - u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { + static const u16 tbl_tx_iqlo_cal_loft_ladder_20[] = { 0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901, 0x1902, 0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607, 0x6407 }; - u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { + static const u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = { 0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400, 0x3200, 0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406, 0x6407 }; - u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { + static const u16 tbl_tx_iqlo_cal_loft_ladder_40[] = { 0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201, 0x1202, 0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207, 0x4707 }; - u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { + static const u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = { 0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900, 0x2300, 0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706, 0x4707 }; - u16 tbl_tx_iqlo_cal_startcoefs[] = { + static const u16 tbl_tx_iqlo_cal_startcoefs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; - u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { + static const u16 tbl_tx_iqlo_cal_cmds_fullcal[] = { 0x8123, 0x8264, 0x8086, 0x8245, 0x8056, 0x9123, 0x9264, 0x9086, 0x9245, 0x9056 }; - u16 tbl_tx_iqlo_cal_cmds_recal[] = { + static const u16 tbl_tx_iqlo_cal_cmds_recal[] = { 0x8101, 0x8253, 0x8053, 0x8234, 0x8034, 0x9101, 0x9253, 0x9053, 0x9234, 0x9034 }; - u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { + static const u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; - u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { + static const u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = { 0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234, 0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234 }; - u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { + static const u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = { 0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223, 0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223 }; diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c index 45e2efc70d19..ce741beec1fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/7000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/7000.c @@ -309,6 +309,7 @@ const struct iwl_cfg iwl3168_2ac_cfg = { .nvm_calib_ver = IWL3168_TX_POWER_VERSION, .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, .dccm_len = IWL7265_DCCM_LEN, + .nvm_type = IWL_NVM_SDP, }; const struct iwl_cfg iwl7265_2ac_cfg = { diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c index 2e6c52664cee..c2a5936ccede 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/8000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/8000.c @@ -164,7 +164,7 @@ static const struct iwl_tt_params iwl8000_tt_params = { .default_nvm_file_C_step = DEFAULT_NVM_FILE_FAMILY_8000C, \ .thermal_params = &iwl8000_tt_params, \ .apmg_not_supported = true, \ - .ext_nvm = true, \ + .nvm_type = IWL_NVM_EXT, \ .dbgc_supported = true #define IWL_DEVICE_8000 \ diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c index 2babe0a1f18b..e8b5ff42f5a8 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/9000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/9000.c @@ -148,7 +148,7 @@ static const struct iwl_tt_params iwl9000_tt_params = { .vht_mu_mimo_supported = true, \ .mac_addr_from_csr = true, \ .rf_id = true, \ - .ext_nvm = true, \ + .nvm_type = IWL_NVM_EXT, \ .dbgc_supported = true const struct iwl_cfg iwl9160_2ac_cfg = { diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/a000.c b/drivers/net/wireless/intel/iwlwifi/cfg/a000.c index 76ba1f8bc72f..a440140ed8dd 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/a000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/a000.c @@ -133,7 +133,7 @@ static const struct iwl_ht_params iwl_a000_ht_params = { .use_tfh = true, \ .rf_id = true, \ .gen2 = true, \ - .ext_nvm = true, \ + .nvm_type = IWL_NVM_EXT, \ .dbgc_supported = true const struct iwl_cfg iwla000_2ac_cfg_hr = { diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h index 00bc7a25dece..3fd07bc80f54 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/nvm-reg.h @@ -108,6 +108,7 @@ enum iwl_nvm_access_target { * @NVM_SECTION_TYPE_REGULATORY: regulatory section * @NVM_SECTION_TYPE_CALIBRATION: calibration section * @NVM_SECTION_TYPE_PRODUCTION: production section + * @NVM_SECTION_TYPE_REGULATORY_SDP: regulatory section used by 3168 series * @NVM_SECTION_TYPE_MAC_OVERRIDE: MAC override section * @NVM_SECTION_TYPE_PHY_SKU: PHY SKU section * @NVM_MAX_NUM_SECTIONS: number of sections @@ -117,6 +118,7 @@ enum iwl_nvm_section_type { NVM_SECTION_TYPE_REGULATORY = 3, NVM_SECTION_TYPE_CALIBRATION = 4, NVM_SECTION_TYPE_PRODUCTION = 5, + NVM_SECTION_TYPE_REGULATORY_SDP = 8, NVM_SECTION_TYPE_MAC_OVERRIDE = 11, NVM_SECTION_TYPE_PHY_SKU = 12, NVM_MAX_NUM_SECTIONS = 13, diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 6afc7a799892..f5dd7d83cd0a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1086,7 +1086,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work) if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { /* stop recording */ - iwl_set_bits_prph(fwrt->trans, MON_BUFF_SAMPLE_CTL, 0x100); + iwl_fw_dbg_stop_recording(fwrt); iwl_fw_error_dump(fwrt); @@ -1104,10 +1104,7 @@ void iwl_fw_error_dump_wk(struct work_struct *work) u32 in_sample = iwl_read_prph(fwrt->trans, DBGC_IN_SAMPLE); u32 out_ctrl = iwl_read_prph(fwrt->trans, DBGC_OUT_CTRL); - /* stop recording */ - iwl_write_prph(fwrt->trans, DBGC_IN_SAMPLE, 0); - udelay(100); - iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, 0); + iwl_fw_dbg_stop_recording(fwrt); /* wait before we collect the data till the DBGC stop */ udelay(500); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h index 0f810ea89d31..9c889a32fe24 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.h @@ -68,6 +68,8 @@ #include <linux/workqueue.h> #include <net/cfg80211.h> #include "runtime.h" +#include "iwl-prph.h" +#include "iwl-io.h" #include "file.h" #include "error-dump.h" @@ -194,8 +196,21 @@ _iwl_fw_dbg_trigger_simple_stop(struct iwl_fw_runtime *fwrt, iwl_fw_dbg_get_trigger((fwrt)->fw,\ (trig))) +static inline void iwl_fw_dbg_stop_recording(struct iwl_fw_runtime *fwrt) +{ + if (fwrt->trans->cfg->device_family == IWL_DEVICE_FAMILY_7000) { + iwl_set_bits_prph(fwrt->trans, MON_BUFF_SAMPLE_CTL, 0x100); + } else { + iwl_write_prph(fwrt->trans, DBGC_IN_SAMPLE, 0); + udelay(100); + iwl_write_prph(fwrt->trans, DBGC_OUT_CTRL, 0); + } +} + static inline void iwl_fw_dump_conf_clear(struct iwl_fw_runtime *fwrt) { + iwl_fw_dbg_stop_recording(fwrt); + fwrt->dump.conf = FW_DBG_INVALID; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 3e057b539d5b..71cb1ecde0f7 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -108,6 +108,18 @@ enum iwl_led_mode { IWL_LED_DISABLE, }; +/** + * enum iwl_nvm_type - nvm formats + * @IWL_NVM: the regular format + * @IWL_NVM_EXT: extended NVM format + * @IWL_NVM_SDP: NVM format used by 3168 series + */ +enum iwl_nvm_type { + IWL_NVM, + IWL_NVM_EXT, + IWL_NVM_SDP, +}; + /* * This is the threshold value of plcp error rate per 100mSecs. It is * used to set and check for the validity of plcp_delta. @@ -320,7 +332,7 @@ struct iwl_pwr_tx_backoff { * @integrated: discrete or integrated * @gen2: a000 and on transport operation * @cdb: CDB support - * @ext_nvm: extended NVM format + * @nvm_type: see &enum iwl_nvm_type * * We enable the driver to be backward compatible wrt. hardware features. * API differences in uCode shouldn't be handled here but through TLVs @@ -342,6 +354,7 @@ struct iwl_cfg { const struct iwl_tt_params *thermal_params; enum iwl_device_family device_family; enum iwl_led_mode led_mode; + enum iwl_nvm_type nvm_type; u32 max_data_size; u32 max_inst_size; netdev_features_t features; @@ -369,7 +382,6 @@ struct iwl_cfg { use_tfh:1, gen2:1, cdb:1, - ext_nvm:1, dbgc_supported:1; u8 valid_tx_ant; u8 valid_rx_ant; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index 3014beef4873..c3a5d8ccc95e 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -77,7 +77,7 @@ #include "iwl-csr.h" /* NVM offsets (in words) definitions */ -enum wkp_nvm_offsets { +enum nvm_offsets { /* NVM HW-Section offset (in words) definitions */ SUBSYSTEM_ID = 0x0A, HW_ADDR = 0x15, @@ -92,7 +92,10 @@ enum wkp_nvm_offsets { /* NVM calibration section offset (in words) definitions */ NVM_CALIB_SECTION = 0x2B8, - XTAL_CALIB = 0x316 - NVM_CALIB_SECTION + XTAL_CALIB = 0x316 - NVM_CALIB_SECTION, + + /* NVM REGULATORY -Section offset (in words) definitions */ + NVM_CHANNELS_SDP = 0, }; enum ext_nvm_offsets { @@ -206,8 +209,36 @@ enum iwl_nvm_channel_flags { NVM_CHANNEL_DC_HIGH = BIT(12), }; +static inline void iwl_nvm_print_channel_flags(struct device *dev, u32 level, + int chan, u16 flags) +{ #define CHECK_AND_PRINT_I(x) \ - ((ch_flags & NVM_CHANNEL_##x) ? # x " " : "") + ((flags & NVM_CHANNEL_##x) ? " " #x : "") + + if (!(flags & NVM_CHANNEL_VALID)) { + IWL_DEBUG_DEV(dev, level, "Ch. %d: 0x%x: No traffic\n", + chan, flags); + return; + } + + /* Note: already can print up to 101 characters, 110 is the limit! */ + IWL_DEBUG_DEV(dev, level, + "Ch. %d: 0x%x:%s%s%s%s%s%s%s%s%s%s%s%s\n", + chan, flags, + CHECK_AND_PRINT_I(VALID), + CHECK_AND_PRINT_I(IBSS), + CHECK_AND_PRINT_I(ACTIVE), + CHECK_AND_PRINT_I(RADAR), + CHECK_AND_PRINT_I(INDOOR_ONLY), + CHECK_AND_PRINT_I(GO_CONCURRENT), + CHECK_AND_PRINT_I(UNIFORM), + CHECK_AND_PRINT_I(20MHZ), + CHECK_AND_PRINT_I(40MHZ), + CHECK_AND_PRINT_I(80MHZ), + CHECK_AND_PRINT_I(160MHZ), + CHECK_AND_PRINT_I(DC_HIGH)); +#undef CHECK_AND_PRINT_I +} static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, u16 nvm_flags, const struct iwl_cfg *cfg) @@ -215,7 +246,7 @@ static u32 iwl_get_channel_flags(u8 ch_num, int ch_idx, bool is_5ghz, u32 flags = IEEE80211_CHAN_NO_HT40; u32 last_5ghz_ht = LAST_5GHZ_HT; - if (cfg->ext_nvm) + if (cfg->nvm_type == IWL_NVM_EXT) last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000; if (!is_5ghz && (nvm_flags & NVM_CHANNEL_40MHZ)) { @@ -268,7 +299,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, int num_of_ch, num_2ghz_channels; const u8 *nvm_chan; - if (!cfg->ext_nvm) { + if (cfg->nvm_type != IWL_NVM_EXT) { num_of_ch = IWL_NUM_CHANNELS; nvm_chan = &iwl_nvm_channels[0]; num_2ghz_channels = NUM_2GHZ_CHANNELS; @@ -302,12 +333,8 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, * supported, hence we still want to add them to * the list of supported channels to cfg80211. */ - IWL_DEBUG_EEPROM(dev, - "Ch. %d Flags %x [%sGHz] - No traffic\n", - nvm_chan[ch_idx], - ch_flags, - (ch_idx >= num_2ghz_channels) ? - "5.2" : "2.4"); + iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM, + nvm_chan[ch_idx], ch_flags); continue; } @@ -337,27 +364,10 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, else channel->flags = 0; - IWL_DEBUG_EEPROM(dev, - "Ch. %d [%sGHz] flags 0x%x %s%s%s%s%s%s%s%s%s%s%s%s(%ddBm): Ad-Hoc %ssupported\n", - channel->hw_value, - is_5ghz ? "5.2" : "2.4", - ch_flags, - CHECK_AND_PRINT_I(VALID), - CHECK_AND_PRINT_I(IBSS), - CHECK_AND_PRINT_I(ACTIVE), - CHECK_AND_PRINT_I(RADAR), - CHECK_AND_PRINT_I(INDOOR_ONLY), - CHECK_AND_PRINT_I(GO_CONCURRENT), - CHECK_AND_PRINT_I(UNIFORM), - CHECK_AND_PRINT_I(20MHZ), - CHECK_AND_PRINT_I(40MHZ), - CHECK_AND_PRINT_I(80MHZ), - CHECK_AND_PRINT_I(160MHZ), - CHECK_AND_PRINT_I(DC_HIGH), - channel->max_power, - ((ch_flags & NVM_CHANNEL_IBSS) && - !(ch_flags & NVM_CHANNEL_RADAR)) - ? "" : "not "); + iwl_nvm_print_channel_flags(dev, IWL_DL_EEPROM, + channel->hw_value, ch_flags); + IWL_DEBUG_EEPROM(dev, "Ch. %d: %ddBm\n", + channel->hw_value, channel->max_power); } return n_channels; @@ -484,7 +494,7 @@ IWL_EXPORT_SYMBOL(iwl_init_sbands); static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw, const __le16 *phy_sku) { - if (!cfg->ext_nvm) + if (cfg->nvm_type != IWL_NVM_EXT) return le16_to_cpup(nvm_sw + SKU); return le32_to_cpup((__le32 *)(phy_sku + SKU_FAMILY_8000)); @@ -492,7 +502,7 @@ static int iwl_get_sku(const struct iwl_cfg *cfg, const __le16 *nvm_sw, static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw) { - if (!cfg->ext_nvm) + if (cfg->nvm_type != IWL_NVM_EXT) return le16_to_cpup(nvm_sw + NVM_VERSION); else return le32_to_cpup((__le32 *)(nvm_sw + @@ -502,7 +512,7 @@ static int iwl_get_nvm_version(const struct iwl_cfg *cfg, const __le16 *nvm_sw) static int iwl_get_radio_cfg(const struct iwl_cfg *cfg, const __le16 *nvm_sw, const __le16 *phy_sku) { - if (!cfg->ext_nvm) + if (cfg->nvm_type != IWL_NVM_EXT) return le16_to_cpup(nvm_sw + RADIO_CFG); return le32_to_cpup((__le32 *)(phy_sku + RADIO_CFG_FAMILY_EXT_NVM)); @@ -513,7 +523,7 @@ static int iwl_get_n_hw_addrs(const struct iwl_cfg *cfg, const __le16 *nvm_sw) { int n_hw_addr; - if (!cfg->ext_nvm) + if (cfg->nvm_type != IWL_NVM_EXT) return le16_to_cpup(nvm_sw + N_HW_ADDRS); n_hw_addr = le32_to_cpup((__le32 *)(nvm_sw + N_HW_ADDRS_FAMILY_8000)); @@ -525,7 +535,7 @@ static void iwl_set_radio_cfg(const struct iwl_cfg *cfg, struct iwl_nvm_data *data, u32 radio_cfg) { - if (!cfg->ext_nvm) { + if (cfg->nvm_type != IWL_NVM_EXT) { data->radio_cfg_type = NVM_RF_CFG_TYPE_MSK(radio_cfg); data->radio_cfg_step = NVM_RF_CFG_STEP_MSK(radio_cfg); data->radio_cfg_dash = NVM_RF_CFG_DASH_MSK(radio_cfg); @@ -634,7 +644,7 @@ static int iwl_set_hw_address(struct iwl_trans *trans, { if (cfg->mac_addr_from_csr) { iwl_set_hw_address_from_csr(trans, data); - } else if (!cfg->ext_nvm) { + } else if (cfg->nvm_type != IWL_NVM_EXT) { const u8 *hw_addr = (const u8 *)(nvm_hw + HW_ADDR); /* The byte order is little endian 16 bit, meaning 214365 */ @@ -706,7 +716,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, u16 lar_config; const __le16 *ch_section; - if (!cfg->ext_nvm) + if (cfg->nvm_type != IWL_NVM_EXT) data = kzalloc(sizeof(*data) + sizeof(struct ieee80211_channel) * IWL_NUM_CHANNELS, @@ -740,7 +750,7 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, data->n_hw_addrs = iwl_get_n_hw_addrs(cfg, nvm_sw); - if (!cfg->ext_nvm) { + if (cfg->nvm_type != IWL_NVM_EXT) { /* Checking for required sections */ if (!nvm_calib) { IWL_ERR(trans, @@ -748,11 +758,15 @@ iwl_parse_nvm_data(struct iwl_trans *trans, const struct iwl_cfg *cfg, kfree(data); return NULL; } + + ch_section = cfg->nvm_type == IWL_NVM_SDP ? + ®ulatory[NVM_CHANNELS_SDP] : + &nvm_sw[NVM_CHANNELS]; + /* in family 8000 Xtal calibration values moved to OTP */ data->xtal_calib[0] = *(nvm_calib + XTAL_CALIB); data->xtal_calib[1] = *(nvm_calib + XTAL_CALIB + 1); lar_enabled = true; - ch_section = &nvm_sw[NVM_CHANNELS]; } else { u16 lar_offset = data->nvm_version < 0xE39 ? NVM_LAR_OFFSET_OLD : @@ -786,7 +800,7 @@ static u32 iwl_nvm_get_regdom_bw_flags(const u8 *nvm_chan, u32 flags = NL80211_RRF_NO_HT40; u32 last_5ghz_ht = LAST_5GHZ_HT; - if (cfg->ext_nvm) + if (cfg->nvm_type == IWL_NVM_EXT) last_5ghz_ht = LAST_5GHZ_HT_FAMILY_8000; if (ch_idx < NUM_2GHZ_CHANNELS && @@ -834,7 +848,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, int ch_idx; u16 ch_flags; u32 reg_rule_flags, prev_reg_rule_flags = 0; - const u8 *nvm_chan = cfg->ext_nvm ? + const u8 *nvm_chan = cfg->nvm_type == IWL_NVM_EXT ? iwl_ext_nvm_channels : iwl_nvm_channels; struct ieee80211_regdomain *regd; int size_of_regd; @@ -843,7 +857,7 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, int center_freq, prev_center_freq = 0; int valid_rules = 0; bool new_rule; - int max_num_ch = cfg->ext_nvm ? + int max_num_ch = cfg->nvm_type == IWL_NVM_EXT ? IWL_NUM_CHANNELS_EXT : IWL_NUM_CHANNELS; if (WARN_ON_ONCE(num_of_ch > NL80211_MAX_SUPP_REG_RULES)) @@ -873,12 +887,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, new_rule = false; if (!(ch_flags & NVM_CHANNEL_VALID)) { - IWL_DEBUG_DEV(dev, IWL_DL_LAR, - "Ch. %d Flags %x [%sGHz] - No traffic\n", - nvm_chan[ch_idx], - ch_flags, - (ch_idx >= NUM_2GHZ_CHANNELS) ? - "5.2" : "2.4"); + iwl_nvm_print_channel_flags(dev, IWL_DL_LAR, + nvm_chan[ch_idx], ch_flags); continue; } @@ -914,31 +924,8 @@ iwl_parse_nvm_mcc_info(struct device *dev, const struct iwl_cfg *cfg, prev_center_freq = center_freq; prev_reg_rule_flags = reg_rule_flags; - IWL_DEBUG_DEV(dev, IWL_DL_LAR, - "Ch. %d [%sGHz] %s%s%s%s%s%s%s%s%s%s%s%s(0x%02x)\n", - center_freq, - band == NL80211_BAND_5GHZ ? "5.2" : "2.4", - CHECK_AND_PRINT_I(VALID), - CHECK_AND_PRINT_I(IBSS), - CHECK_AND_PRINT_I(ACTIVE), - CHECK_AND_PRINT_I(RADAR), - CHECK_AND_PRINT_I(INDOOR_ONLY), - CHECK_AND_PRINT_I(GO_CONCURRENT), - CHECK_AND_PRINT_I(UNIFORM), - CHECK_AND_PRINT_I(20MHZ), - CHECK_AND_PRINT_I(40MHZ), - CHECK_AND_PRINT_I(80MHZ), - CHECK_AND_PRINT_I(160MHZ), - CHECK_AND_PRINT_I(DC_HIGH), - ch_flags); - IWL_DEBUG_DEV(dev, IWL_DL_LAR, - "Ch. %d [%sGHz] reg_flags 0x%x: %s\n", - center_freq, - band == NL80211_BAND_5GHZ ? "5.2" : "2.4", - reg_rule_flags, - ((ch_flags & NVM_CHANNEL_ACTIVE) && - !(ch_flags & NVM_CHANNEL_RADAR)) - ? "Ad-Hoc" : ""); + iwl_nvm_print_channel_flags(dev, IWL_DL_LAR, + nvm_chan[ch_idx], ch_flags); } regd->n_reg_rules = valid_rules; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 5de19ea10575..b205a7bfb828 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -2167,7 +2167,7 @@ out: * 1. We are not using a unified image * 2. We are using a unified image but had an error while exiting D3 */ - set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); + set_bit(IWL_MVM_STATUS_HW_RESTART_REQUESTED, &mvm->status); set_bit(IWL_MVM_STATUS_D3_RECONFIG, &mvm->status); /* * When switching images we return 1, which causes mac80211 diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 15f2d826bb4b..a9ac872226fd 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -1077,6 +1077,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) mvm->vif_count = 0; mvm->rx_ba_sessions = 0; mvm->fwrt.dump.conf = FW_DBG_INVALID; + mvm->monitor_on = false; /* keep statistics ticking */ iwl_mvm_accu_radio_stats(mvm); @@ -1437,6 +1438,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, mvm->p2p_device_vif = vif; } + if (vif->type == NL80211_IFTYPE_MONITOR) + mvm->monitor_on = true; + iwl_mvm_vif_dbgfs_register(mvm, vif); goto out_unlock; @@ -1526,6 +1530,9 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, iwl_mvm_power_update_mac(mvm); iwl_mvm_mac_ctxt_remove(mvm, vif); + if (vif->type == NL80211_IFTYPE_MONITOR) + mvm->monitor_on = false; + out_release: mutex_unlock(&mvm->mutex); } @@ -1546,6 +1553,11 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, struct iwl_mvm_mc_iter_data *data = _data; struct iwl_mvm *mvm = data->mvm; struct iwl_mcast_filter_cmd *cmd = mvm->mcast_filter_cmd; + struct iwl_host_cmd hcmd = { + .id = MCAST_FILTER_CMD, + .flags = CMD_ASYNC, + .dataflags[0] = IWL_HCMD_DFL_NOCOPY, + }; int ret, len; /* if we don't have free ports, mcast frames will be dropped */ @@ -1560,7 +1572,10 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac, memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN); len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4); - ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd); + hcmd.len[0] = len; + hcmd.data[0] = cmd; + + ret = iwl_mvm_send_cmd(mvm, &hcmd); if (ret) IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret); } @@ -1635,6 +1650,12 @@ static void iwl_mvm_configure_filter(struct ieee80211_hw *hw, if (!cmd) goto out; + if (changed_flags & FIF_ALLMULTI) + cmd->pass_all = !!(*total_flags & FIF_ALLMULTI); + + if (cmd->pass_all) + cmd->count = 0; + iwl_mvm_recalc_multicast(mvm); out: mutex_unlock(&mvm->mutex); @@ -2563,7 +2584,7 @@ static void iwl_mvm_purge_deferred_tx_frames(struct iwl_mvm *mvm, * queues, so we should never get a second deferred * frame for the RA/TID. */ - iwl_mvm_start_mac_queues(mvm, info->hw_queue); + iwl_mvm_start_mac_queues(mvm, BIT(info->hw_queue)); ieee80211_free_txskb(mvm->hw, skb); } } @@ -3975,6 +3996,43 @@ out_unlock: return ret; } +static void iwl_mvm_flush_no_vif(struct iwl_mvm *mvm, u32 queues, bool drop) +{ + if (drop) { + if (iwl_mvm_has_new_tx_api(mvm)) + /* TODO new tx api */ + WARN_ONCE(1, + "Need to implement flush TX queue\n"); + else + iwl_mvm_flush_tx_path(mvm, + iwl_mvm_flushable_queues(mvm) & queues, + 0); + } else { + if (iwl_mvm_has_new_tx_api(mvm)) { + struct ieee80211_sta *sta; + int i; + + mutex_lock(&mvm->mutex); + + for (i = 0; i < ARRAY_SIZE(mvm->fw_id_to_mac_id); i++) { + sta = rcu_dereference_protected( + mvm->fw_id_to_mac_id[i], + lockdep_is_held(&mvm->mutex)); + if (IS_ERR_OR_NULL(sta)) + continue; + + iwl_mvm_wait_sta_queues_empty(mvm, + iwl_mvm_sta_from_mac80211(sta)); + } + + mutex_unlock(&mvm->mutex); + } else { + iwl_trans_wait_tx_queues_empty(mvm->trans, + queues); + } + } +} + static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u32 queues, bool drop) { @@ -3985,7 +4043,12 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, int i; u32 msk = 0; - if (!vif || vif->type != NL80211_IFTYPE_STATION) + if (!vif) { + iwl_mvm_flush_no_vif(mvm, queues, drop); + return; + } + + if (vif->type != NL80211_IFTYPE_STATION) return; /* Make sure we're done with the deferred traffic before flushing */ diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 83303bac0e4b..949e63418299 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -1015,6 +1015,9 @@ struct iwl_mvm { bool drop_bcn_ap_mode; struct delayed_work cs_tx_unblock_dwork; + + /* does a monitor vif exist (only one can exist hence bool) */ + bool monitor_on; #ifdef CONFIG_ACPI struct iwl_mvm_sar_profile sar_profiles[IWL_MVM_SAR_PROFILE_NUM]; struct iwl_mvm_geo_profile geo_profiles[IWL_NUM_GEO_PROFILES]; @@ -1159,7 +1162,7 @@ static inline bool iwl_mvm_is_lar_supported(struct iwl_mvm *mvm) * Enable LAR only if it is supported by the FW (TLV) && * enabled in the NVM */ - if (mvm->cfg->ext_nvm) + if (mvm->cfg->nvm_type == IWL_NVM_EXT) return nvm_lar && tlv_lar; else return tlv_lar; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index 422aa6be9932..fb25b6f29323 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -295,18 +295,24 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) const __be16 *hw; const __le16 *sw, *calib, *regulatory, *mac_override, *phy_sku; bool lar_enabled; + int regulatory_type; /* Checking for required sections */ - if (!mvm->trans->cfg->ext_nvm) { + if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) { if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || !mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data) { IWL_ERR(mvm, "Can't parse empty OTP/NVM sections\n"); return NULL; } } else { + if (mvm->trans->cfg->nvm_type == IWL_NVM_SDP) + regulatory_type = NVM_SECTION_TYPE_REGULATORY_SDP; + else + regulatory_type = NVM_SECTION_TYPE_REGULATORY; + /* SW and REGULATORY sections are mandatory */ if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data || - !mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) { + !mvm->nvm_sections[regulatory_type].data) { IWL_ERR(mvm, "Can't parse empty family 8000 OTP/NVM sections\n"); return NULL; @@ -330,11 +336,14 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm) hw = (const __be16 *)sections[mvm->cfg->nvm_hw_section_num].data; sw = (const __le16 *)sections[NVM_SECTION_TYPE_SW].data; calib = (const __le16 *)sections[NVM_SECTION_TYPE_CALIBRATION].data; - regulatory = (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data; mac_override = (const __le16 *)sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data; phy_sku = (const __le16 *)sections[NVM_SECTION_TYPE_PHY_SKU].data; + regulatory = mvm->trans->cfg->nvm_type == IWL_NVM_SDP ? + (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY_SDP].data : + (const __le16 *)sections[NVM_SECTION_TYPE_REGULATORY].data; + lar_enabled = !iwlwifi_mod_params.lar_disable && fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_LAR_SUPPORT); @@ -394,7 +403,7 @@ int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from external NVM\n"); /* Maximal size depends on NVM version */ - if (!mvm->trans->cfg->ext_nvm) + if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) max_section_size = IWL_MAX_NVM_SECTION_SIZE; else max_section_size = IWL_MAX_EXT_NVM_SECTION_SIZE; @@ -465,7 +474,7 @@ int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm) break; } - if (!mvm->trans->cfg->ext_nvm) { + if (mvm->trans->cfg->nvm_type != IWL_NVM_EXT) { section_size = 2 * NVM_WORD1_LEN(le16_to_cpu(file_sec->word1)); section_id = NVM_WORD2_ID(le16_to_cpu(file_sec->word2)); @@ -740,7 +749,7 @@ int iwl_mvm_init_mcc(struct iwl_mvm *mvm) struct ieee80211_regdomain *regd; char mcc[3]; - if (mvm->cfg->ext_nvm) { + if (mvm->cfg->nvm_type == IWL_NVM_EXT) { tlv_lar = fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_LAR_SUPPORT); nvm_lar = mvm->nvm_data->lar_enabled; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c index ba7bd049d3d4..0fe723ca844e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs.c @@ -661,7 +661,8 @@ static void rs_tl_turn_on_agg(struct iwl_mvm *mvm, struct iwl_mvm_sta *mvmsta, (lq_sta->tx_agg_tid_en & BIT(tid)) && (tid_data->tx_count_last >= IWL_MVM_RS_AGG_START_THRESHOLD)) { IWL_DEBUG_RATE(mvm, "try to aggregate tid %d\n", tid); - rs_tl_turn_on_agg_for_tid(mvm, lq_sta, tid, sta); + if (rs_tl_turn_on_agg_for_tid(mvm, lq_sta, tid, sta) == 0) + tid_data->state = IWL_AGG_QUEUED; } } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c index 184c749766f2..2d14a58cbdd7 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rx.c @@ -244,7 +244,9 @@ static u32 iwl_mvm_set_mac80211_rx_flag(struct iwl_mvm *mvm, return 0; default: - IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status); + /* Expected in monitor (not having the keys) */ + if (!mvm->monitor_on) + IWL_ERR(mvm, "Unhandled alg: 0x%x\n", rx_pkt_status); } return 0; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index 67ffd9774712..248699c2c4bf 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -277,7 +277,9 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr, stats->flag |= RX_FLAG_DECRYPTED; return 0; default: - IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status); + /* Expected in monitor (not having the keys) */ + if (!mvm->monitor_on) + IWL_ERR(mvm, "Unhandled alg: 0x%x\n", status); } return 0; @@ -672,11 +674,12 @@ static bool iwl_mvm_reorder(struct iwl_mvm *mvm, * If there was a significant jump in the nssn - adjust. * If the SN is smaller than the NSSN it might need to first go into * the reorder buffer, in which case we just release up to it and the - * rest of the function will take of storing it and releasing up to the - * nssn + * rest of the function will take care of storing it and releasing up to + * the nssn */ if (!iwl_mvm_is_sn_less(nssn, buffer->head_sn + buffer->buf_size, - buffer->buf_size)) { + buffer->buf_size) || + !ieee80211_sn_less(sn, buffer->head_sn + buffer->buf_size)) { u16 min_sn = ieee80211_sn_less(sn, nssn) ? sn : nssn; iwl_mvm_release_frames(mvm, sta, napi, buffer, min_sn); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c index 50983615dce6..774122fed454 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/scan.c @@ -555,7 +555,7 @@ static int iwl_mvm_lmac_scan_abort(struct iwl_mvm *mvm) struct iwl_host_cmd cmd = { .id = SCAN_OFFLOAD_ABORT_CMD, }; - u32 status; + u32 status = CAN_ABORT_STATUS; ret = iwl_mvm_send_cmd_status(mvm, &cmd, &status); if (ret) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 411a2055dc45..c4a343534c5e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1285,7 +1285,7 @@ static int iwl_mvm_add_int_sta_common(struct iwl_mvm *mvm, { struct iwl_mvm_add_sta_cmd cmd; int ret; - u32 status; + u32 status = ADD_STA_SUCCESS; lockdep_assert_held(&mvm->mutex); @@ -2385,8 +2385,10 @@ int iwl_mvm_sta_tx_agg_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, if (WARN_ON_ONCE(tid >= IWL_MAX_TID_COUNT)) return -EINVAL; - if (mvmsta->tid_data[tid].state != IWL_AGG_OFF) { - IWL_ERR(mvm, "Start AGG when state is not IWL_AGG_OFF %d!\n", + if (mvmsta->tid_data[tid].state != IWL_AGG_QUEUED && + mvmsta->tid_data[tid].state != IWL_AGG_OFF) { + IWL_ERR(mvm, + "Start AGG when state is not IWL_AGG_QUEUED or IWL_AGG_OFF %d!\n", mvmsta->tid_data[tid].state); return -ENXIO; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h index d13893806513..aedabe101cf0 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.h @@ -281,6 +281,7 @@ struct iwl_mvm_vif; * These states relate to a specific RA / TID. * * @IWL_AGG_OFF: aggregation is not used + * @IWL_AGG_QUEUED: aggregation start work has been queued * @IWL_AGG_STARTING: aggregation are starting (between start and oper) * @IWL_AGG_ON: aggregation session is up * @IWL_EMPTYING_HW_QUEUE_ADDBA: establishing a BA session - waiting for the @@ -290,6 +291,7 @@ struct iwl_mvm_vif; */ enum iwl_mvm_agg_state { IWL_AGG_OFF = 0, + IWL_AGG_QUEUED, IWL_AGG_STARTING, IWL_AGG_ON, IWL_EMPTYING_HW_QUEUE_ADDBA, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c index 8876c2abc440..1232f63278eb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tt.c @@ -529,6 +529,7 @@ int iwl_mvm_ctdp_command(struct iwl_mvm *mvm, u32 op, u32 state) lockdep_assert_held(&mvm->mutex); + status = 0; ret = iwl_mvm_send_cmd_pdu_status(mvm, WIDE_ID(PHY_OPS_GROUP, CTDP_CONFIG_CMD), sizeof(cmd), &cmd, &status); @@ -630,7 +631,7 @@ static int iwl_mvm_tzone_get_temp(struct thermal_zone_device *device, if (!iwl_mvm_firmware_running(mvm) || mvm->fwrt.cur_fw_img != IWL_UCODE_REGULAR) { - ret = -EIO; + ret = -ENODATA; goto out; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index 172b5e63d3fb..6f2e2af23219 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -564,8 +564,8 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, case NL80211_IFTYPE_AP: case NL80211_IFTYPE_ADHOC: /* - * Handle legacy hostapd as well, where station will be added - * only just before sending the association response. + * Non-bufferable frames use the broadcast station, thus they + * use the probe queue. * Also take care of the case where we send a deauth to a * station that we don't have, or similarly an association * response (with non-success status) for a station we can't @@ -573,9 +573,9 @@ static int iwl_mvm_get_ctrl_vif_queue(struct iwl_mvm *mvm, * Also, disassociate frames might happen, particular with * reason 7 ("Class 3 frame received from nonassociated STA"). */ - if (ieee80211_is_probe_resp(fc) || ieee80211_is_auth(fc) || - ieee80211_is_deauth(fc) || ieee80211_is_assoc_resp(fc) || - ieee80211_is_disassoc(fc)) + if (ieee80211_is_mgmt(fc) && + (!ieee80211_is_bufferable_mmpdu(fc) || + ieee80211_is_deauth(fc) || ieee80211_is_disassoc(fc))) return mvm->probe_queue; if (info->hw_queue == info->control.vif->cab_queue) return mvmvif->cab_queue; diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c index 856fa6e8327e..a450bc6bc774 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c @@ -115,6 +115,8 @@ int qtnf_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) vif = qtnf_netdev_get_priv(wdev->netdev); + qtnf_scan_done(vif->mac, true); + if (qtnf_cmd_send_del_intf(vif)) pr_err("VIF%u.%u: failed to delete VIF\n", vif->mac->macid, vif->vifid); @@ -335,6 +337,8 @@ static int qtnf_stop_ap(struct wiphy *wiphy, struct net_device *dev) struct qtnf_vif *vif = qtnf_netdev_get_priv(dev); int ret; + qtnf_scan_done(vif->mac, true); + ret = qtnf_cmd_send_stop_ap(vif); if (ret) { pr_err("VIF%u.%u: failed to stop AP operation in FW\n", @@ -570,8 +574,6 @@ qtnf_del_station(struct wiphy *wiphy, struct net_device *dev, !qtnf_sta_list_lookup(&vif->sta_list, params->mac)) return 0; - qtnf_scan_done(vif->mac, true); - ret = qtnf_cmd_send_del_sta(vif, params); if (ret) pr_err("VIF%u.%u: failed to delete STA %pM\n", @@ -1134,8 +1136,9 @@ void qtnf_virtual_intf_cleanup(struct net_device *ndev) } vif->sta_state = QTNF_STA_DISCONNECTED; - qtnf_scan_done(mac, true); } + + qtnf_scan_done(mac, true); } void qtnf_cfg80211_vif_reset(struct qtnf_vif *vif) diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h index 6a4af52522b8..66db26613b1f 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h +++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.h @@ -34,6 +34,9 @@ static inline void qtnf_scan_done(struct qtnf_wmac *mac, bool aborted) .aborted = aborted, }; + if (timer_pending(&mac->scan_timeout)) + del_timer_sync(&mac->scan_timeout); + mutex_lock(&mac->mac_lock); if (mac->scan_req) { diff --git a/drivers/net/wireless/quantenna/qtnfmac/event.c b/drivers/net/wireless/quantenna/qtnfmac/event.c index 0fc2814eafad..43d2e7fd6e02 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/event.c +++ b/drivers/net/wireless/quantenna/qtnfmac/event.c @@ -345,8 +345,6 @@ qtnf_event_handle_scan_complete(struct qtnf_wmac *mac, return -EINVAL; } - if (timer_pending(&mac->scan_timeout)) - del_timer_sync(&mac->scan_timeout); qtnf_scan_done(mac, le32_to_cpu(status->flags) & QLINK_SCAN_ABORTED); return 0; diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c index 502e72b7cdcc..69131965a298 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c +++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie.c @@ -661,14 +661,18 @@ static int qtnf_pcie_data_tx(struct qtnf_bus *bus, struct sk_buff *skb) struct qtnf_pcie_bus_priv *priv = (void *)get_bus_priv(bus); dma_addr_t txbd_paddr, skb_paddr; struct qtnf_tx_bd *txbd; + unsigned long flags; int len, i; u32 info; int ret = 0; + spin_lock_irqsave(&priv->tx0_lock, flags); + if (!qtnf_tx_queue_ready(priv)) { if (skb->dev) netif_stop_queue(skb->dev); + spin_unlock_irqrestore(&priv->tx0_lock, flags); return NETDEV_TX_BUSY; } @@ -717,8 +721,10 @@ tx_done: dev_kfree_skb_any(skb); } - qtnf_pcie_data_tx_reclaim(priv); priv->tx_done_count++; + spin_unlock_irqrestore(&priv->tx0_lock, flags); + + qtnf_pcie_data_tx_reclaim(priv); return NETDEV_TX_OK; } @@ -1247,6 +1253,7 @@ static int qtnf_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) strcpy(bus->fwname, QTN_PCI_PEARL_FW_NAME); init_completion(&bus->request_firmware_complete); mutex_init(&bus->bus_lock); + spin_lock_init(&pcie_priv->tx0_lock); spin_lock_init(&pcie_priv->irq_lock); spin_lock_init(&pcie_priv->tx_reclaim_lock); diff --git a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h index e76a23716ee0..86ac1ccedb52 100644 --- a/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h +++ b/drivers/net/wireless/quantenna/qtnfmac/pearl/pcie_bus_priv.h @@ -34,6 +34,8 @@ struct qtnf_pcie_bus_priv { /* lock for tx reclaim operations */ spinlock_t tx_reclaim_lock; + /* lock for tx0 operations */ + spinlock_t tx0_lock; u8 msi_enabled; int mps; diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c index 4f73012978e9..1d431d4bf6d2 100644 --- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c +++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/hw.c @@ -1122,7 +1122,7 @@ static u8 _rtl8821ae_dbi_read(struct rtl_priv *rtlpriv, u16 addr) } if (0 == tmp) { read_addr = REG_DBI_RDATA + addr % 4; - ret = rtl_read_byte(rtlpriv, read_addr); + ret = rtl_read_word(rtlpriv, read_addr); } return ret; } diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index ee8ed9da00ad..4491ca5aee90 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c @@ -486,7 +486,7 @@ struct xenvif *xenvif_alloc(struct device *parent, domid_t domid, dev->tx_queue_len = XENVIF_QUEUE_LENGTH; - dev->min_mtu = 0; + dev->min_mtu = ETH_MIN_MTU; dev->max_mtu = ETH_MAX_MTU - VLAN_ETH_HLEN; /* diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 523387e71a80..8b8689c6d887 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -1316,7 +1316,7 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) netdev->features |= netdev->hw_features; netdev->ethtool_ops = &xennet_ethtool_ops; - netdev->min_mtu = 0; + netdev->min_mtu = ETH_MIN_MTU; netdev->max_mtu = XEN_NETIF_MAX_TX_SIZE; SET_NETDEV_DEV(netdev, &dev->dev); diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c index bb2aad078637..5a14cc7f28ee 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -2136,7 +2136,7 @@ static umode_t nvme_ns_attrs_are_visible(struct kobject *kobj, struct nvme_ns *ns = nvme_get_ns_from_dev(dev); if (a == &dev_attr_uuid.attr) { - if (uuid_is_null(&ns->uuid) || + if (uuid_is_null(&ns->uuid) && !memchr_inv(ns->nguid, 0, sizeof(ns->nguid))) return 0; } diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index af075e998944..be49d0f79381 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -2545,10 +2545,10 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl) nvme_fc_abort_aen_ops(ctrl); /* wait for all io that had to be aborted */ - spin_lock_irqsave(&ctrl->lock, flags); + spin_lock_irq(&ctrl->lock); wait_event_lock_irq(ctrl->ioabort_wait, ctrl->iocnt == 0, ctrl->lock); ctrl->flags &= ~FCCTRL_TERMIO; - spin_unlock_irqrestore(&ctrl->lock, flags); + spin_unlock_irq(&ctrl->lock); nvme_fc_term_aen_ops(ctrl); @@ -2734,7 +2734,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, { struct nvme_fc_ctrl *ctrl; unsigned long flags; - int ret, idx; + int ret, idx, retry; if (!(rport->remoteport.port_role & (FC_PORT_ROLE_NVME_DISCOVERY | FC_PORT_ROLE_NVME_TARGET))) { @@ -2760,6 +2760,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, ctrl->rport = rport; ctrl->dev = lport->dev; ctrl->cnum = idx; + init_waitqueue_head(&ctrl->ioabort_wait); get_device(ctrl->dev); kref_init(&ctrl->ref); @@ -2825,9 +2826,37 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts, list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list); spin_unlock_irqrestore(&rport->lock, flags); - ret = nvme_fc_create_association(ctrl); + /* + * It's possible that transactions used to create the association + * may fail. Examples: CreateAssociation LS or CreateIOConnection + * LS gets dropped/corrupted/fails; or a frame gets dropped or a + * command times out for one of the actions to init the controller + * (Connect, Get/Set_Property, Set_Features, etc). Many of these + * transport errors (frame drop, LS failure) inherently must kill + * the association. The transport is coded so that any command used + * to create the association (prior to a LIVE state transition + * while NEW or RECONNECTING) will fail if it completes in error or + * times out. + * + * As such: as the connect request was mostly likely due to a + * udev event that discovered the remote port, meaning there is + * not an admin or script there to restart if the connect + * request fails, retry the initial connection creation up to + * three times before giving up and declaring failure. + */ + for (retry = 0; retry < 3; retry++) { + ret = nvme_fc_create_association(ctrl); + if (!ret) + break; + } + if (ret) { + /* couldn't schedule retry - fail out */ + dev_err(ctrl->ctrl.device, + "NVME-FC{%d}: Connect retry failed\n", ctrl->cnum); + ctrl->ctrl.opts = NULL; + /* initiate nvme ctrl ref counting teardown */ nvme_uninit_ctrl(&ctrl->ctrl); nvme_put_ctrl(&ctrl->ctrl); diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c index cb73bc8cad3b..3f5a04c586ce 100644 --- a/drivers/nvme/host/pci.c +++ b/drivers/nvme/host/pci.c @@ -94,7 +94,7 @@ struct nvme_dev { struct mutex shutdown_lock; bool subsystem; void __iomem *cmb; - dma_addr_t cmb_dma_addr; + pci_bus_addr_t cmb_bus_addr; u64 cmb_size; u32 cmbsz; u32 cmbloc; @@ -1226,7 +1226,7 @@ static int nvme_alloc_sq_cmds(struct nvme_dev *dev, struct nvme_queue *nvmeq, if (qid && dev->cmb && use_cmb_sqes && NVME_CMB_SQS(dev->cmbsz)) { unsigned offset = (qid - 1) * roundup(SQ_SIZE(depth), dev->ctrl.page_size); - nvmeq->sq_dma_addr = dev->cmb_dma_addr + offset; + nvmeq->sq_dma_addr = dev->cmb_bus_addr + offset; nvmeq->sq_cmds_io = dev->cmb + offset; } else { nvmeq->sq_cmds = dma_alloc_coherent(dev->dev, SQ_SIZE(depth), @@ -1527,7 +1527,7 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev) resource_size_t bar_size; struct pci_dev *pdev = to_pci_dev(dev->dev); void __iomem *cmb; - dma_addr_t dma_addr; + int bar; dev->cmbsz = readl(dev->bar + NVME_REG_CMBSZ); if (!(NVME_CMB_SZ(dev->cmbsz))) @@ -1540,7 +1540,8 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev) szu = (u64)1 << (12 + 4 * NVME_CMB_SZU(dev->cmbsz)); size = szu * NVME_CMB_SZ(dev->cmbsz); offset = szu * NVME_CMB_OFST(dev->cmbloc); - bar_size = pci_resource_len(pdev, NVME_CMB_BIR(dev->cmbloc)); + bar = NVME_CMB_BIR(dev->cmbloc); + bar_size = pci_resource_len(pdev, bar); if (offset > bar_size) return NULL; @@ -1553,12 +1554,11 @@ static void __iomem *nvme_map_cmb(struct nvme_dev *dev) if (size > bar_size - offset) size = bar_size - offset; - dma_addr = pci_resource_start(pdev, NVME_CMB_BIR(dev->cmbloc)) + offset; - cmb = ioremap_wc(dma_addr, size); + cmb = ioremap_wc(pci_resource_start(pdev, bar) + offset, size); if (!cmb) return NULL; - dev->cmb_dma_addr = dma_addr; + dev->cmb_bus_addr = pci_bus_address(pdev, bar) + offset; dev->cmb_size = size; return cmb; } diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index 92a03ff5fb4d..87bac27ec64b 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -571,6 +571,12 @@ static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue) if (test_and_set_bit(NVME_RDMA_Q_DELETING, &queue->flags)) return; + if (nvme_rdma_queue_idx(queue) == 0) { + nvme_rdma_free_qe(queue->device->dev, + &queue->ctrl->async_event_sqe, + sizeof(struct nvme_command), DMA_TO_DEVICE); + } + nvme_rdma_destroy_queue_ib(queue); rdma_destroy_id(queue->cm_id); } @@ -739,8 +745,6 @@ out: static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl, bool remove) { - nvme_rdma_free_qe(ctrl->queues[0].device->dev, &ctrl->async_event_sqe, - sizeof(struct nvme_command), DMA_TO_DEVICE); nvme_rdma_stop_queue(&ctrl->queues[0]); if (remove) { blk_cleanup_queue(ctrl->ctrl.admin_q); @@ -765,8 +769,10 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl, if (new) { ctrl->ctrl.admin_tagset = nvme_rdma_alloc_tagset(&ctrl->ctrl, true); - if (IS_ERR(ctrl->ctrl.admin_tagset)) + if (IS_ERR(ctrl->ctrl.admin_tagset)) { + error = PTR_ERR(ctrl->ctrl.admin_tagset); goto out_free_queue; + } ctrl->ctrl.admin_q = blk_mq_init_queue(&ctrl->admin_tag_set); if (IS_ERR(ctrl->ctrl.admin_q)) { @@ -846,8 +852,10 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new) if (new) { ctrl->ctrl.tagset = nvme_rdma_alloc_tagset(&ctrl->ctrl, false); - if (IS_ERR(ctrl->ctrl.tagset)) + if (IS_ERR(ctrl->ctrl.tagset)) { + ret = PTR_ERR(ctrl->ctrl.tagset); goto out_free_io_queues; + } ctrl->ctrl.connect_q = blk_mq_init_queue(&ctrl->tag_set); if (IS_ERR(ctrl->ctrl.connect_q)) { diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index 1b208beeef50..645ba7eee35d 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -387,12 +387,21 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid) static void __nvmet_req_complete(struct nvmet_req *req, u16 status) { + u32 old_sqhd, new_sqhd; + u16 sqhd; + if (status) nvmet_set_status(req, status); - if (req->sq->size) - req->sq->sqhd = (req->sq->sqhd + 1) % req->sq->size; - req->rsp->sq_head = cpu_to_le16(req->sq->sqhd); + if (req->sq->size) { + do { + old_sqhd = req->sq->sqhd; + new_sqhd = (old_sqhd + 1) % req->sq->size; + } while (cmpxchg(&req->sq->sqhd, old_sqhd, new_sqhd) != + old_sqhd); + } + sqhd = req->sq->sqhd & 0x0000FFFF; + req->rsp->sq_head = cpu_to_le16(sqhd); req->rsp->sq_id = cpu_to_le16(req->sq->qid); req->rsp->command_id = req->cmd->common.command_id; diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h index 7b8e20adf760..87e429bfcd8a 100644 --- a/drivers/nvme/target/nvmet.h +++ b/drivers/nvme/target/nvmet.h @@ -74,7 +74,7 @@ struct nvmet_sq { struct percpu_ref ref; u16 qid; u16 size; - u16 sqhd; + u32 sqhd; struct completion free_done; struct completion confirm_done; }; diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index de54c7f5048a..d12e5de78e70 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -135,7 +135,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj, /* Stop the user from writing */ if (pos >= nvmem->size) - return 0; + return -EFBIG; if (count < nvmem->word_size) return -EINVAL; @@ -789,6 +789,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, return ERR_PTR(-EINVAL); nvmem = __nvmem_device_get(nvmem_np, NULL, NULL); + of_node_put(nvmem_np); if (IS_ERR(nvmem)) return ERR_CAST(nvmem); diff --git a/drivers/of/base.c b/drivers/of/base.c index 260d33c0f26c..63897531cd75 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -1781,8 +1781,12 @@ bool of_console_check(struct device_node *dn, char *name, int index) { if (!dn || dn != of_stdout || console_set_on_cmdline) return false; - return !add_preferred_console(name, index, - kstrdup(of_stdout_options, GFP_KERNEL)); + + /* + * XXX: cast `options' to char pointer to suppress complication + * warnings: printk, UART and console drivers expect char pointer. + */ + return !add_preferred_console(name, index, (char *)of_stdout_options); } EXPORT_SYMBOL_GPL(of_console_check); diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c index d94dd8b77abd..98258583abb0 100644 --- a/drivers/of/of_mdio.c +++ b/drivers/of/of_mdio.c @@ -44,7 +44,7 @@ static int of_get_phy_id(struct device_node *device, u32 *phy_id) return -EINVAL; } -static void of_mdiobus_register_phy(struct mii_bus *mdio, +static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *child, u32 addr) { struct phy_device *phy; @@ -60,9 +60,13 @@ static void of_mdiobus_register_phy(struct mii_bus *mdio, else phy = get_phy_device(mdio, addr, is_c45); if (IS_ERR(phy)) - return; + return PTR_ERR(phy); - rc = irq_of_parse_and_map(child, 0); + rc = of_irq_get(child, 0); + if (rc == -EPROBE_DEFER) { + phy_device_free(phy); + return rc; + } if (rc > 0) { phy->irq = rc; mdio->irq[addr] = rc; @@ -84,22 +88,23 @@ static void of_mdiobus_register_phy(struct mii_bus *mdio, if (rc) { phy_device_free(phy); of_node_put(child); - return; + return rc; } dev_dbg(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); + return 0; } -static void of_mdiobus_register_device(struct mii_bus *mdio, - struct device_node *child, u32 addr) +static int of_mdiobus_register_device(struct mii_bus *mdio, + struct device_node *child, u32 addr) { struct mdio_device *mdiodev; int rc; mdiodev = mdio_device_create(mdio, addr); if (IS_ERR(mdiodev)) - return; + return PTR_ERR(mdiodev); /* Associate the OF node with the device structure so it * can be looked up later. @@ -112,11 +117,12 @@ static void of_mdiobus_register_device(struct mii_bus *mdio, if (rc) { mdio_device_free(mdiodev); of_node_put(child); - return; + return rc; } dev_dbg(&mdio->dev, "registered mdio device %s at address %i\n", child->name, addr); + return 0; } /* The following is a list of PHY compatible strings which appear in @@ -219,9 +225,11 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) } if (of_mdiobus_child_is_phy(child)) - of_mdiobus_register_phy(mdio, child, addr); + rc = of_mdiobus_register_phy(mdio, child, addr); else - of_mdiobus_register_device(mdio, child, addr); + rc = of_mdiobus_register_device(mdio, child, addr); + if (rc) + goto unregister; } if (!scanphys) @@ -242,12 +250,19 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) dev_info(&mdio->dev, "scan phy %s at address %i\n", child->name, addr); - if (of_mdiobus_child_is_phy(child)) - of_mdiobus_register_phy(mdio, child, addr); + if (of_mdiobus_child_is_phy(child)) { + rc = of_mdiobus_register_phy(mdio, child, addr); + if (rc) + goto unregister; + } } } return 0; + +unregister: + mdiobus_unregister(mdio); + return rc; } EXPORT_SYMBOL(of_mdiobus_register); diff --git a/drivers/of/of_reserved_mem.c b/drivers/of/of_reserved_mem.c index d507c3569a88..32771c2ced7b 100644 --- a/drivers/of/of_reserved_mem.c +++ b/drivers/of/of_reserved_mem.c @@ -25,7 +25,7 @@ #include <linux/sort.h> #include <linux/slab.h> -#define MAX_RESERVED_REGIONS 16 +#define MAX_RESERVED_REGIONS 32 static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS]; static int reserved_mem_count; diff --git a/drivers/of/property.c b/drivers/of/property.c index fbb72116e9d4..264c355ba1ff 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -954,7 +954,7 @@ of_fwnode_graph_get_port_parent(struct fwnode_handle *fwnode) struct device_node *np; /* Get the parent of the port */ - np = of_get_next_parent(to_of_node(fwnode)); + np = of_get_parent(to_of_node(fwnode)); if (!np) return NULL; diff --git a/drivers/pci/host/pci-aardvark.c b/drivers/pci/host/pci-aardvark.c index 89f4e3d072d7..26ed0c08f209 100644 --- a/drivers/pci/host/pci-aardvark.c +++ b/drivers/pci/host/pci-aardvark.c @@ -935,6 +935,8 @@ static int advk_pcie_probe(struct platform_device *pdev) bridge->sysdata = pcie; bridge->busnr = 0; bridge->ops = &advk_pcie_ops; + bridge->map_irq = of_irq_parse_and_map_pci; + bridge->swizzle_irq = pci_common_swizzle; ret = pci_scan_root_bus_bridge(bridge); if (ret < 0) { diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c index 9c40da54f88a..1987fec1f126 100644 --- a/drivers/pci/host/pci-tegra.c +++ b/drivers/pci/host/pci-tegra.c @@ -233,6 +233,7 @@ struct tegra_msi { struct msi_controller chip; DECLARE_BITMAP(used, INT_PCI_MSI_NR); struct irq_domain *domain; + unsigned long pages; struct mutex lock; u64 phys; int irq; @@ -1529,22 +1530,9 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie) goto err; } - /* - * The PCI host bridge on Tegra contains some logic that intercepts - * MSI writes, which means that the MSI target address doesn't have - * to point to actual physical memory. Rather than allocating one 4 - * KiB page of system memory that's never used, we can simply pick - * an arbitrary address within an area reserved for system memory - * in the FPCI address map. - * - * However, in order to avoid confusion, we pick an address that - * doesn't map to physical memory. The FPCI address map reserves a - * 1012 GiB region for system memory and memory-mapped I/O. Since - * none of the Tegra SoCs that contain this PCI host bridge can - * address more than 16 GiB of system memory, the last 4 KiB of - * these 1012 GiB is a good candidate. - */ - msi->phys = 0xfcfffff000; + /* setup AFI/FPCI range */ + msi->pages = __get_free_pages(GFP_KERNEL, 0); + msi->phys = virt_to_phys((void *)msi->pages); afi_writel(pcie, msi->phys >> soc->msi_base_shift, AFI_MSI_FPCI_BAR_ST); afi_writel(pcie, msi->phys, AFI_MSI_AXI_BAR_ST); @@ -1596,6 +1584,8 @@ static int tegra_pcie_disable_msi(struct tegra_pcie *pcie) afi_writel(pcie, 0, AFI_MSI_EN_VEC6); afi_writel(pcie, 0, AFI_MSI_EN_VEC7); + free_pages(msi->pages, 0); + if (msi->irq > 0) free_irq(msi->irq, pcie); diff --git a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c index 73ebad6634a7..89c887ea5557 100644 --- a/drivers/phy/marvell/phy-mvebu-cp110-comphy.c +++ b/drivers/phy/marvell/phy-mvebu-cp110-comphy.c @@ -111,6 +111,8 @@ #define MVEBU_COMPHY_CONF6_40B BIT(18) #define MVEBU_COMPHY_SELECTOR 0x1140 #define MVEBU_COMPHY_SELECTOR_PHY(n) ((n) * 0x4) +#define MVEBU_COMPHY_PIPE_SELECTOR 0x1144 +#define MVEBU_COMPHY_PIPE_SELECTOR_PIPE(n) ((n) * 0x4) #define MVEBU_COMPHY_LANES 6 #define MVEBU_COMPHY_PORTS 3 @@ -468,13 +470,17 @@ static int mvebu_comphy_power_on(struct phy *phy) { struct mvebu_comphy_lane *lane = phy_get_drvdata(phy); struct mvebu_comphy_priv *priv = lane->priv; - int ret; - u32 mux, val; + int ret, mux; + u32 val; mux = mvebu_comphy_get_mux(lane->id, lane->port, lane->mode); if (mux < 0) return -ENOTSUPP; + regmap_read(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, &val); + val &= ~(0xf << MVEBU_COMPHY_PIPE_SELECTOR_PIPE(lane->id)); + regmap_write(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, val); + regmap_read(priv->regmap, MVEBU_COMPHY_SELECTOR, &val); val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id)); val |= mux << MVEBU_COMPHY_SELECTOR_PHY(lane->id); @@ -526,6 +532,10 @@ static int mvebu_comphy_power_off(struct phy *phy) val &= ~(0xf << MVEBU_COMPHY_SELECTOR_PHY(lane->id)); regmap_write(priv->regmap, MVEBU_COMPHY_SELECTOR, val); + regmap_read(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, &val); + val &= ~(0xf << MVEBU_COMPHY_PIPE_SELECTOR_PIPE(lane->id)); + regmap_write(priv->regmap, MVEBU_COMPHY_PIPE_SELECTOR, val); + return 0; } @@ -576,8 +586,8 @@ static int mvebu_comphy_probe(struct platform_device *pdev) return PTR_ERR(priv->regmap); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, res); - if (!priv->base) - return -ENOMEM; + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); for_each_available_child_of_node(pdev->dev.of_node, child) { struct mvebu_comphy_lane *lane; diff --git a/drivers/phy/mediatek/phy-mtk-tphy.c b/drivers/phy/mediatek/phy-mtk-tphy.c index e3baad78521f..721a2a1c97ef 100644 --- a/drivers/phy/mediatek/phy-mtk-tphy.c +++ b/drivers/phy/mediatek/phy-mtk-tphy.c @@ -27,6 +27,7 @@ /* banks shared by multiple phys */ #define SSUSB_SIFSLV_V1_SPLLC 0x000 /* shared by u3 phys */ #define SSUSB_SIFSLV_V1_U2FREQ 0x100 /* shared by u2 phys */ +#define SSUSB_SIFSLV_V1_CHIP 0x300 /* shared by u3 phys */ /* u2 phy bank */ #define SSUSB_SIFSLV_V1_U2PHY_COM 0x000 /* u3/pcie/sata phy banks */ @@ -762,7 +763,7 @@ static void phy_v1_banks_init(struct mtk_tphy *tphy, case PHY_TYPE_USB3: case PHY_TYPE_PCIE: u3_banks->spllc = tphy->sif_base + SSUSB_SIFSLV_V1_SPLLC; - u3_banks->chip = NULL; + u3_banks->chip = tphy->sif_base + SSUSB_SIFSLV_V1_CHIP; u3_banks->phyd = instance->port_base + SSUSB_SIFSLV_V1_U3PHYD; u3_banks->phya = instance->port_base + SSUSB_SIFSLV_V1_U3PHYA; break; diff --git a/drivers/phy/rockchip/phy-rockchip-typec.c b/drivers/phy/rockchip/phy-rockchip-typec.c index 4d2c57f21d76..a958c9bced01 100644 --- a/drivers/phy/rockchip/phy-rockchip-typec.c +++ b/drivers/phy/rockchip/phy-rockchip-typec.c @@ -443,14 +443,34 @@ static inline int property_enable(struct rockchip_typec_phy *tcphy, return regmap_write(tcphy->grf_regs, reg->offset, val | mask); } +static void tcphy_dp_aux_set_flip(struct rockchip_typec_phy *tcphy) +{ + u16 tx_ana_ctrl_reg_1; + + /* + * Select the polarity of the xcvr: + * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull + * down aux_m) + * 0, Normal polarity (if TYPEC, pulls up aux_m and pulls down + * aux_p) + */ + tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1); + if (!tcphy->flip) + tx_ana_ctrl_reg_1 |= BIT(12); + else + tx_ana_ctrl_reg_1 &= ~BIT(12); + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); +} + static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) { + u16 tx_ana_ctrl_reg_1; u16 rdata, rdata2, val; /* disable txda_cal_latch_en for rewrite the calibration values */ - rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); - val = rdata & 0xdfff; - writel(val, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 = readl(tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 &= ~BIT(13); + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); /* * read a resistor calibration code from CMN_TXPUCAL_CTRL[6:0] and @@ -472,9 +492,8 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) * Activate this signal for 1 clock cycle to sample new calibration * values. */ - rdata = readl(tcphy->base + TX_ANA_CTRL_REG_1); - val = rdata | 0x2000; - writel(val, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 |= BIT(13); + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); usleep_range(150, 200); /* set TX Voltage Level and TX Deemphasis to 0 */ @@ -482,8 +501,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) /* re-enable decap */ writel(0x100, tcphy->base + TX_ANA_CTRL_REG_2); writel(0x300, tcphy->base + TX_ANA_CTRL_REG_2); - writel(0x2008, tcphy->base + TX_ANA_CTRL_REG_1); - writel(0x2018, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 |= BIT(3); + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 |= BIT(4); + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); writel(0, tcphy->base + TX_ANA_CTRL_REG_5); @@ -494,8 +515,10 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) writel(0x1001, tcphy->base + TX_ANA_CTRL_REG_4); /* re-enables Bandgap reference for LDO */ - writel(0x2098, tcphy->base + TX_ANA_CTRL_REG_1); - writel(0x2198, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 |= BIT(7); + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 |= BIT(8); + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); /* * re-enables the transmitter pre-driver, driver data selection MUX, @@ -505,27 +528,26 @@ static void tcphy_dp_aux_calibration(struct rockchip_typec_phy *tcphy) writel(0x303, tcphy->base + TX_ANA_CTRL_REG_2); /* - * BIT 12: Controls auxda_polarity, which selects the polarity of the - * xcvr: - * 1, Reverses the polarity (If TYPEC, Pulls ups aux_p and pull - * down aux_m) - * 0, Normal polarity (if TYPE_C, pulls up aux_m and pulls down - * aux_p) + * Do some magic undocumented stuff, some of which appears to + * undo the "re-enables Bandgap reference for LDO" above. */ - val = 0xa078; - if (!tcphy->flip) - val |= BIT(12); - writel(val, tcphy->base + TX_ANA_CTRL_REG_1); + tx_ana_ctrl_reg_1 |= BIT(15); + tx_ana_ctrl_reg_1 &= ~BIT(8); + tx_ana_ctrl_reg_1 &= ~BIT(7); + tx_ana_ctrl_reg_1 |= BIT(6); + tx_ana_ctrl_reg_1 |= BIT(5); + writel(tx_ana_ctrl_reg_1, tcphy->base + TX_ANA_CTRL_REG_1); writel(0, tcphy->base + TX_ANA_CTRL_REG_3); writel(0, tcphy->base + TX_ANA_CTRL_REG_4); writel(0, tcphy->base + TX_ANA_CTRL_REG_5); /* - * Controls low_power_swing_en, set the voltage swing of the driver - * to 400mv. The values below are peak to peak (differential) values. + * Controls low_power_swing_en, don't set the voltage swing of the + * driver to 400mv. The values below are peak to peak (differential) + * values. */ - writel(4, tcphy->base + TXDA_COEFF_CALC_CTRL); + writel(0, tcphy->base + TXDA_COEFF_CALC_CTRL); writel(0, tcphy->base + TXDA_CYA_AUXDA_CYA); /* Controls tx_high_z_tm_en */ @@ -555,6 +577,7 @@ static int tcphy_phy_init(struct rockchip_typec_phy *tcphy, u8 mode) reset_control_deassert(tcphy->tcphy_rst); property_enable(tcphy, &cfg->typec_conn_dir, tcphy->flip); + tcphy_dp_aux_set_flip(tcphy); tcphy_cfg_24m(tcphy); @@ -685,8 +708,11 @@ static int rockchip_usb3_phy_power_on(struct phy *phy) if (tcphy->mode == new_mode) goto unlock_ret; - if (tcphy->mode == MODE_DISCONNECT) - tcphy_phy_init(tcphy, new_mode); + if (tcphy->mode == MODE_DISCONNECT) { + ret = tcphy_phy_init(tcphy, new_mode); + if (ret) + goto unlock_ret; + } /* wait TCPHY for pipe ready */ for (timeout = 0; timeout < 100; timeout++) { @@ -760,10 +786,12 @@ static int rockchip_dp_phy_power_on(struct phy *phy) */ if (new_mode == MODE_DFP_DP && tcphy->mode != MODE_DISCONNECT) { tcphy_phy_deinit(tcphy); - tcphy_phy_init(tcphy, new_mode); + ret = tcphy_phy_init(tcphy, new_mode); } else if (tcphy->mode == MODE_DISCONNECT) { - tcphy_phy_init(tcphy, new_mode); + ret = tcphy_phy_init(tcphy, new_mode); } + if (ret) + goto unlock_ret; ret = readx_poll_timeout(readl, tcphy->base + DP_MODE_CTL, val, val & DP_MODE_A2, 1000, diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index 3cbcb2537657..4307bf0013e1 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -454,6 +454,8 @@ tegra_xusb_find_port_node(struct tegra_xusb_padctl *padctl, const char *type, char *name; name = kasprintf(GFP_KERNEL, "%s-%u", type, index); + if (!name) + return ERR_PTR(-ENOMEM); np = of_find_node_by_name(np, name); kfree(name); } diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 1778cf4f81c7..82cd8b08d71f 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -100,6 +100,7 @@ config PINCTRL_AMD tristate "AMD GPIO pin control" depends on GPIOLIB select GPIOLIB_IRQCHIP + select PINMUX select PINCONF select GENERIC_PINCONF help diff --git a/drivers/pinctrl/bcm/pinctrl-bcm2835.c b/drivers/pinctrl/bcm/pinctrl-bcm2835.c index 0944310225db..ff782445dfb7 100644 --- a/drivers/pinctrl/bcm/pinctrl-bcm2835.c +++ b/drivers/pinctrl/bcm/pinctrl-bcm2835.c @@ -373,16 +373,12 @@ static void bcm2835_gpio_irq_handle_bank(struct bcm2835_pinctrl *pc, unsigned long events; unsigned offset; unsigned gpio; - unsigned int type; events = bcm2835_gpio_rd(pc, GPEDS0 + bank * 4); events &= mask; events &= pc->enabled_irq_map[bank]; for_each_set_bit(offset, &events, 32) { gpio = (32 * bank) + offset; - /* FIXME: no clue why the code looks up the type here */ - type = pc->irq_type[gpio]; - generic_handle_irq(irq_linear_revmap(pc->gpio_chip.irqdomain, gpio)); } diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c index 04e929fd0ffe..fadbca907c7c 100644 --- a/drivers/pinctrl/intel/pinctrl-cherryview.c +++ b/drivers/pinctrl/intel/pinctrl-cherryview.c @@ -1577,6 +1577,7 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) struct gpio_chip *chip = &pctrl->chip; bool need_valid_mask = !dmi_check_system(chv_no_valid_mask); int ret, i, offset; + int irq_base; *chip = chv_gpio_chip; @@ -1622,7 +1623,18 @@ static int chv_gpio_probe(struct chv_pinctrl *pctrl, int irq) /* Clear all interrupts */ chv_writel(0xffff, pctrl->regs + CHV_INTSTAT); - ret = gpiochip_irqchip_add(chip, &chv_gpio_irqchip, 0, + if (!need_valid_mask) { + irq_base = devm_irq_alloc_descs(pctrl->dev, -1, 0, + chip->ngpio, NUMA_NO_NODE); + if (irq_base < 0) { + dev_err(pctrl->dev, "Failed to allocate IRQ numbers\n"); + return irq_base; + } + } else { + irq_base = 0; + } + + ret = gpiochip_irqchip_add(chip, &chv_gpio_irqchip, irq_base, handle_bad_irq, IRQ_TYPE_NONE); if (ret) { dev_err(pctrl->dev, "failed to add IRQ chip\n"); diff --git a/drivers/pinctrl/pinctrl-amd.c b/drivers/pinctrl/pinctrl-amd.c index 3f6b34febbf1..433af328d981 100644 --- a/drivers/pinctrl/pinctrl-amd.c +++ b/drivers/pinctrl/pinctrl-amd.c @@ -534,8 +534,16 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id) continue; irq = irq_find_mapping(gc->irqdomain, irqnr + i); generic_handle_irq(irq); - /* Clear interrupt */ + + /* Clear interrupt. + * We must read the pin register again, in case the + * value was changed while executing + * generic_handle_irq() above. + */ + raw_spin_lock_irqsave(&gpio_dev->lock, flags); + regval = readl(regs + i); writel(regval, regs + i); + raw_spin_unlock_irqrestore(&gpio_dev->lock, flags); ret = IRQ_HANDLED; } } diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c index 3e40d4245512..9c950bbf07ba 100644 --- a/drivers/pinctrl/pinctrl-mcp23s08.c +++ b/drivers/pinctrl/pinctrl-mcp23s08.c @@ -407,10 +407,10 @@ static int mcp23s08_get(struct gpio_chip *chip, unsigned offset) ret = mcp_read(mcp, MCP_GPIO, &status); if (ret < 0) status = 0; - else + else { + mcp->cached_gpio = status; status = !!(status & (1 << offset)); - - mcp->cached_gpio = status; + } mutex_unlock(&mcp->lock); return status; diff --git a/drivers/platform/x86/intel_pmc_ipc.c b/drivers/platform/x86/intel_pmc_ipc.c index bb792a52248b..e03fa31446ca 100644 --- a/drivers/platform/x86/intel_pmc_ipc.c +++ b/drivers/platform/x86/intel_pmc_ipc.c @@ -33,6 +33,7 @@ #include <linux/suspend.h> #include <linux/acpi.h> #include <linux/io-64-nonatomic-lo-hi.h> +#include <linux/spinlock.h> #include <asm/intel_pmc_ipc.h> @@ -131,6 +132,7 @@ static struct intel_pmc_ipc_dev { /* gcr */ void __iomem *gcr_mem_base; bool has_gcr_regs; + spinlock_t gcr_lock; /* punit */ struct platform_device *punit_dev; @@ -225,17 +227,17 @@ int intel_pmc_gcr_read(u32 offset, u32 *data) { int ret; - mutex_lock(&ipclock); + spin_lock(&ipcdev.gcr_lock); ret = is_gcr_valid(offset); if (ret < 0) { - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return ret; } *data = readl(ipcdev.gcr_mem_base + offset); - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return 0; } @@ -255,17 +257,17 @@ int intel_pmc_gcr_write(u32 offset, u32 data) { int ret; - mutex_lock(&ipclock); + spin_lock(&ipcdev.gcr_lock); ret = is_gcr_valid(offset); if (ret < 0) { - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return ret; } writel(data, ipcdev.gcr_mem_base + offset); - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return 0; } @@ -287,7 +289,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) u32 new_val; int ret = 0; - mutex_lock(&ipclock); + spin_lock(&ipcdev.gcr_lock); ret = is_gcr_valid(offset); if (ret < 0) @@ -309,7 +311,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val) } gcr_ipc_unlock: - mutex_unlock(&ipclock); + spin_unlock(&ipcdev.gcr_lock); return ret; } EXPORT_SYMBOL_GPL(intel_pmc_gcr_update); @@ -480,52 +482,41 @@ static irqreturn_t ioc(int irq, void *dev_id) static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - resource_size_t pci_resource; + struct intel_pmc_ipc_dev *pmc = &ipcdev; int ret; - int len; - ipcdev.dev = &pci_dev_get(pdev)->dev; - ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; + /* Only one PMC is supported */ + if (pmc->dev) + return -EBUSY; - ret = pci_enable_device(pdev); + pmc->irq_mode = IPC_TRIGGER_MODE_IRQ; + + spin_lock_init(&ipcdev.gcr_lock); + + ret = pcim_enable_device(pdev); if (ret) return ret; - ret = pci_request_regions(pdev, "intel_pmc_ipc"); + ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev)); if (ret) return ret; - pci_resource = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - if (!pci_resource || !len) { - dev_err(&pdev->dev, "Failed to get resource\n"); - return -ENOMEM; - } + init_completion(&pmc->cmd_complete); - init_completion(&ipcdev.cmd_complete); + pmc->ipc_base = pcim_iomap_table(pdev)[0]; - if (request_irq(pdev->irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) { + ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc", + pmc); + if (ret) { dev_err(&pdev->dev, "Failed to request irq\n"); - return -EBUSY; + return ret; } - ipcdev.ipc_base = ioremap_nocache(pci_resource, len); - if (!ipcdev.ipc_base) { - dev_err(&pdev->dev, "Failed to ioremap ipc base\n"); - free_irq(pdev->irq, &ipcdev); - ret = -ENOMEM; - } + pmc->dev = &pdev->dev; - return ret; -} + pci_set_drvdata(pdev, pmc); -static void ipc_pci_remove(struct pci_dev *pdev) -{ - free_irq(pdev->irq, &ipcdev); - pci_release_regions(pdev); - pci_dev_put(pdev); - iounmap(ipcdev.ipc_base); - ipcdev.dev = NULL; + return 0; } static const struct pci_device_id ipc_pci_ids[] = { @@ -540,7 +531,6 @@ static struct pci_driver ipc_pci_driver = { .name = "intel_pmc_ipc", .id_table = ipc_pci_ids, .probe = ipc_pci_probe, - .remove = ipc_pci_remove, }; static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev, @@ -850,17 +840,12 @@ static int ipc_plat_get_res(struct platform_device *pdev) return -ENXIO; } size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE; + res->end = res->start + size - 1; + + addr = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(addr)) + return PTR_ERR(addr); - if (!request_mem_region(res->start, size, pdev->name)) { - dev_err(&pdev->dev, "Failed to request ipc resource\n"); - return -EBUSY; - } - addr = ioremap_nocache(res->start, size); - if (!addr) { - dev_err(&pdev->dev, "I/O memory remapping failed\n"); - release_mem_region(res->start, size); - return -ENOMEM; - } ipcdev.ipc_base = addr; ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET; @@ -917,12 +902,12 @@ MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids); static int ipc_plat_probe(struct platform_device *pdev) { - struct resource *res; int ret; ipcdev.dev = &pdev->dev; ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ; init_completion(&ipcdev.cmd_complete); + spin_lock_init(&ipcdev.gcr_lock); ipcdev.irq = platform_get_irq(pdev, 0); if (ipcdev.irq < 0) { @@ -939,11 +924,11 @@ static int ipc_plat_probe(struct platform_device *pdev) ret = ipc_create_pmc_devices(); if (ret) { dev_err(&pdev->dev, "Failed to create pmc devices\n"); - goto err_device; + return ret; } - if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND, - "intel_pmc_ipc", &ipcdev)) { + if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND, + "intel_pmc_ipc", &ipcdev)) { dev_err(&pdev->dev, "Failed to request irq\n"); ret = -EBUSY; goto err_irq; @@ -960,40 +945,22 @@ static int ipc_plat_probe(struct platform_device *pdev) return 0; err_sys: - free_irq(ipcdev.irq, &ipcdev); + devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); err_irq: platform_device_unregister(ipcdev.tco_dev); platform_device_unregister(ipcdev.punit_dev); platform_device_unregister(ipcdev.telemetry_dev); -err_device: - iounmap(ipcdev.ipc_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_IPC_INDEX); - if (res) { - release_mem_region(res->start, - PLAT_RESOURCE_IPC_SIZE + - PLAT_RESOURCE_GCR_SIZE); - } + return ret; } static int ipc_plat_remove(struct platform_device *pdev) { - struct resource *res; - sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group); - free_irq(ipcdev.irq, &ipcdev); + devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev); platform_device_unregister(ipcdev.tco_dev); platform_device_unregister(ipcdev.punit_dev); platform_device_unregister(ipcdev.telemetry_dev); - iounmap(ipcdev.ipc_base); - res = platform_get_resource(pdev, IORESOURCE_MEM, - PLAT_RESOURCE_IPC_INDEX); - if (res) { - release_mem_region(res->start, - PLAT_RESOURCE_IPC_SIZE + - PLAT_RESOURCE_GCR_SIZE); - } ipcdev.dev = NULL; return 0; } diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index 5beb0c361076..5c1b6388122a 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -876,10 +876,10 @@ rio_dma_transfer(struct file *filp, u32 transfer_mode, * offset within the internal buffer specified by handle parameter. */ if (xfer->loc_addr) { - unsigned long offset; + unsigned int offset; long pinned; - offset = (unsigned long)(uintptr_t)xfer->loc_addr & ~PAGE_MASK; + offset = lower_32_bits(offset_in_page(xfer->loc_addr)); nr_pages = PAGE_ALIGN(xfer->length + offset) >> PAGE_SHIFT; page_list = kmalloc_array(nr_pages, diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c index 315a4be8dc1e..9a68914100ad 100644 --- a/drivers/rapidio/devices/tsi721.c +++ b/drivers/rapidio/devices/tsi721.c @@ -51,6 +51,8 @@ module_param(mbox_sel, byte, S_IRUGO); MODULE_PARM_DESC(mbox_sel, "RIO Messaging MBOX Selection Mask (default: 0x0f = all)"); +static DEFINE_SPINLOCK(tsi721_maint_lock); + static void tsi721_omsg_handler(struct tsi721_device *priv, int ch); static void tsi721_imsg_handler(struct tsi721_device *priv, int ch); @@ -124,12 +126,15 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, void __iomem *regs = priv->regs + TSI721_DMAC_BASE(priv->mdma.ch_id); struct tsi721_dma_desc *bd_ptr; u32 rd_count, swr_ptr, ch_stat; + unsigned long flags; int i, err = 0; u32 op = do_wr ? MAINT_WR : MAINT_RD; if (offset > (RIO_MAINT_SPACE_SZ - len) || (len != sizeof(u32))) return -EINVAL; + spin_lock_irqsave(&tsi721_maint_lock, flags); + bd_ptr = priv->mdma.bd_base; rd_count = ioread32(regs + TSI721_DMAC_DRDCNT); @@ -197,7 +202,9 @@ static int tsi721_maint_dma(struct tsi721_device *priv, u32 sys_size, */ swr_ptr = ioread32(regs + TSI721_DMAC_DSWP); iowrite32(swr_ptr, regs + TSI721_DMAC_DSRP); + err_out: + spin_unlock_irqrestore(&tsi721_maint_lock, flags); return err; } diff --git a/drivers/rapidio/rio-access.c b/drivers/rapidio/rio-access.c index a3824baca2e5..3ee9af83b638 100644 --- a/drivers/rapidio/rio-access.c +++ b/drivers/rapidio/rio-access.c @@ -14,16 +14,8 @@ #include <linux/module.h> /* - * These interrupt-safe spinlocks protect all accesses to RIO - * configuration space and doorbell access. - */ -static DEFINE_SPINLOCK(rio_config_lock); -static DEFINE_SPINLOCK(rio_doorbell_lock); - -/* * Wrappers for all RIO configuration access functions. They just check - * alignment, do locking and call the low-level functions pointed to - * by rio_mport->ops. + * alignment and call the low-level functions pointed to by rio_mport->ops. */ #define RIO_8_BAD 0 @@ -44,13 +36,10 @@ int __rio_local_read_config_##size \ (struct rio_mport *mport, u32 offset, type *value) \ { \ int res; \ - unsigned long flags; \ u32 data = 0; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ - spin_lock_irqsave(&rio_config_lock, flags); \ res = mport->ops->lcread(mport, mport->id, offset, len, &data); \ *value = (type)data; \ - spin_unlock_irqrestore(&rio_config_lock, flags); \ return res; \ } @@ -67,13 +56,8 @@ int __rio_local_read_config_##size \ int __rio_local_write_config_##size \ (struct rio_mport *mport, u32 offset, type value) \ { \ - int res; \ - unsigned long flags; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ - spin_lock_irqsave(&rio_config_lock, flags); \ - res = mport->ops->lcwrite(mport, mport->id, offset, len, value);\ - spin_unlock_irqrestore(&rio_config_lock, flags); \ - return res; \ + return mport->ops->lcwrite(mport, mport->id, offset, len, value);\ } RIO_LOP_READ(8, u8, 1) @@ -104,13 +88,10 @@ int rio_mport_read_config_##size \ (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type *value) \ { \ int res; \ - unsigned long flags; \ u32 data = 0; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ - spin_lock_irqsave(&rio_config_lock, flags); \ res = mport->ops->cread(mport, mport->id, destid, hopcount, offset, len, &data); \ *value = (type)data; \ - spin_unlock_irqrestore(&rio_config_lock, flags); \ return res; \ } @@ -127,13 +108,9 @@ int rio_mport_read_config_##size \ int rio_mport_write_config_##size \ (struct rio_mport *mport, u16 destid, u8 hopcount, u32 offset, type value) \ { \ - int res; \ - unsigned long flags; \ if (RIO_##size##_BAD) return RIO_BAD_SIZE; \ - spin_lock_irqsave(&rio_config_lock, flags); \ - res = mport->ops->cwrite(mport, mport->id, destid, hopcount, offset, len, value); \ - spin_unlock_irqrestore(&rio_config_lock, flags); \ - return res; \ + return mport->ops->cwrite(mport, mport->id, destid, hopcount, \ + offset, len, value); \ } RIO_OP_READ(8, u8, 1) @@ -162,14 +139,7 @@ EXPORT_SYMBOL_GPL(rio_mport_write_config_32); */ int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, u16 data) { - int res; - unsigned long flags; - - spin_lock_irqsave(&rio_doorbell_lock, flags); - res = mport->ops->dsend(mport, mport->id, destid, data); - spin_unlock_irqrestore(&rio_doorbell_lock, flags); - - return res; + return mport->ops->dsend(mport, mport->id, destid, data); } EXPORT_SYMBOL_GPL(rio_mport_send_doorbell); diff --git a/drivers/ras/cec.c b/drivers/ras/cec.c index d0e5d6ee882c..e2c1988cd7c0 100644 --- a/drivers/ras/cec.c +++ b/drivers/ras/cec.c @@ -523,7 +523,7 @@ int __init parse_cec_param(char *str) if (*str == '=') str++; - if (!strncmp(str, "cec_disable", 7)) + if (!strcmp(str, "cec_disable")) ce_arr.disabled = 1; else return 0; diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index f18b36dd57dd..376a99b7cf5d 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -590,7 +590,7 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id) case AXP803_DCDC3: return !!(reg & BIT(6)); case AXP803_DCDC6: - return !!(reg & BIT(7)); + return !!(reg & BIT(5)); } break; diff --git a/drivers/regulator/rn5t618-regulator.c b/drivers/regulator/rn5t618-regulator.c index ef2be56460fe..790a4a73ea2c 100644 --- a/drivers/regulator/rn5t618-regulator.c +++ b/drivers/regulator/rn5t618-regulator.c @@ -29,7 +29,7 @@ static const struct regulator_ops rn5t618_reg_ops = { }; #define REG(rid, ereg, emask, vreg, vmask, min, max, step) \ - [RN5T618_##rid] = { \ + { \ .name = #rid, \ .of_match = of_match_ptr(#rid), \ .regulators_node = of_match_ptr("regulators"), \ diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index df63e44526ac..bf04479456a0 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -109,6 +109,7 @@ config QCOM_Q6V5_PIL depends on OF && ARCH_QCOM depends on QCOM_SMEM depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n) + depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n select MFD_SYSCON select QCOM_RPROC_COMMON select QCOM_SCM @@ -120,6 +121,7 @@ config QCOM_WCNSS_PIL tristate "Qualcomm WCNSS Peripheral Image Loader" depends on OF && ARCH_QCOM depends on RPMSG_QCOM_SMD || (COMPILE_TEST && RPMSG_QCOM_SMD=n) + depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n depends on QCOM_SMEM select QCOM_MDT_LOADER select QCOM_RPROC_COMMON diff --git a/drivers/remoteproc/imx_rproc.c b/drivers/remoteproc/imx_rproc.c index 612d91403341..633268e9d550 100644 --- a/drivers/remoteproc/imx_rproc.c +++ b/drivers/remoteproc/imx_rproc.c @@ -264,15 +264,14 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, if (!(att->flags & ATT_OWN)) continue; - if (b > IMX7D_RPROC_MEM_MAX) + if (b >= IMX7D_RPROC_MEM_MAX) break; priv->mem[b].cpu_addr = devm_ioremap(&pdev->dev, att->sa, att->size); - if (IS_ERR(priv->mem[b].cpu_addr)) { + if (!priv->mem[b].cpu_addr) { dev_err(dev, "devm_ioremap_resource failed\n"); - err = PTR_ERR(priv->mem[b].cpu_addr); - return err; + return -ENOMEM; } priv->mem[b].sys_addr = att->sa; priv->mem[b].size = att->size; @@ -296,7 +295,7 @@ static int imx_rproc_addr_init(struct imx_rproc *priv, return err; } - if (b > IMX7D_RPROC_MEM_MAX) + if (b >= IMX7D_RPROC_MEM_MAX) break; priv->mem[b].cpu_addr = devm_ioremap_resource(&pdev->dev, &res); diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index e0c393214264..e2baecbb9dd3 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -34,11 +34,12 @@ config RESET_BERLIN help This enables the reset controller driver for Marvell Berlin SoCs. -config RESET_HSDK_V1 - bool "HSDK v1 Reset Driver" - default n +config RESET_HSDK + bool "Synopsys HSDK Reset Driver" + depends on HAS_IOMEM + depends on ARC_SOC_HSDK || COMPILE_TEST help - This enables the reset controller driver for HSDK v1. + This enables the reset controller driver for HSDK board. config RESET_IMX7 bool "i.MX7 Reset Driver" if COMPILE_TEST diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index d368367110e5..af1c15c330b3 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o obj-$(CONFIG_RESET_ATH79) += reset-ath79.o obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o -obj-$(CONFIG_RESET_HSDK_V1) += reset-hsdk-v1.o +obj-$(CONFIG_RESET_HSDK) += reset-hsdk.o obj-$(CONFIG_RESET_IMX7) += reset-imx7.o obj-$(CONFIG_RESET_LANTIQ) += reset-lantiq.o obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o diff --git a/drivers/reset/reset-hsdk-v1.c b/drivers/reset/reset-hsdk.c index bca13e4bf622..8bce391c6943 100644 --- a/drivers/reset/reset-hsdk-v1.c +++ b/drivers/reset/reset-hsdk.c @@ -1,7 +1,7 @@ /* * Copyright (C) 2017 Synopsys. * - * Synopsys HSDKv1 SDP reset driver. + * Synopsys HSDK Development platform reset driver. * * This file is licensed under the terms of the GNU General Public * License version 2. This program is licensed "as is" without any @@ -18,9 +18,9 @@ #include <linux/slab.h> #include <linux/types.h> -#define to_hsdkv1_rst(p) container_of((p), struct hsdkv1_rst, rcdev) +#define to_hsdk_rst(p) container_of((p), struct hsdk_rst, rcdev) -struct hsdkv1_rst { +struct hsdk_rst { void __iomem *regs_ctl; void __iomem *regs_rst; spinlock_t lock; @@ -49,12 +49,12 @@ static const u32 rst_map[] = { #define CGU_IP_SW_RESET_RESET BIT(0) #define SW_RESET_TIMEOUT 10000 -static void hsdkv1_reset_config(struct hsdkv1_rst *rst, unsigned long id) +static void hsdk_reset_config(struct hsdk_rst *rst, unsigned long id) { writel(rst_map[id], rst->regs_ctl + CGU_SYS_RST_CTRL); } -static int hsdkv1_reset_do(struct hsdkv1_rst *rst) +static int hsdk_reset_do(struct hsdk_rst *rst) { u32 reg; @@ -69,28 +69,28 @@ static int hsdkv1_reset_do(struct hsdkv1_rst *rst) !(reg & CGU_IP_SW_RESET_RESET), 5, SW_RESET_TIMEOUT); } -static int hsdkv1_reset_reset(struct reset_controller_dev *rcdev, +static int hsdk_reset_reset(struct reset_controller_dev *rcdev, unsigned long id) { - struct hsdkv1_rst *rst = to_hsdkv1_rst(rcdev); + struct hsdk_rst *rst = to_hsdk_rst(rcdev); unsigned long flags; int ret; spin_lock_irqsave(&rst->lock, flags); - hsdkv1_reset_config(rst, id); - ret = hsdkv1_reset_do(rst); + hsdk_reset_config(rst, id); + ret = hsdk_reset_do(rst); spin_unlock_irqrestore(&rst->lock, flags); return ret; } -static const struct reset_control_ops hsdkv1_reset_ops = { - .reset = hsdkv1_reset_reset, +static const struct reset_control_ops hsdk_reset_ops = { + .reset = hsdk_reset_reset, }; -static int hsdkv1_reset_probe(struct platform_device *pdev) +static int hsdk_reset_probe(struct platform_device *pdev) { - struct hsdkv1_rst *rst; + struct hsdk_rst *rst; struct resource *mem; rst = devm_kzalloc(&pdev->dev, sizeof(*rst), GFP_KERNEL); @@ -110,7 +110,7 @@ static int hsdkv1_reset_probe(struct platform_device *pdev) spin_lock_init(&rst->lock); rst->rcdev.owner = THIS_MODULE; - rst->rcdev.ops = &hsdkv1_reset_ops; + rst->rcdev.ops = &hsdk_reset_ops; rst->rcdev.of_node = pdev->dev.of_node; rst->rcdev.nr_resets = HSDK_MAX_RESETS; rst->rcdev.of_reset_n_cells = 1; @@ -118,20 +118,20 @@ static int hsdkv1_reset_probe(struct platform_device *pdev) return reset_controller_register(&rst->rcdev); } -static const struct of_device_id hsdkv1_reset_dt_match[] = { - { .compatible = "snps,hsdk-v1.0-reset" }, +static const struct of_device_id hsdk_reset_dt_match[] = { + { .compatible = "snps,hsdk-reset" }, { }, }; -static struct platform_driver hsdkv1_reset_driver = { - .probe = hsdkv1_reset_probe, +static struct platform_driver hsdk_reset_driver = { + .probe = hsdk_reset_probe, .driver = { - .name = "hsdk-v1.0-reset", - .of_match_table = hsdkv1_reset_dt_match, + .name = "hsdk-reset", + .of_match_table = hsdk_reset_dt_match, }, }; -builtin_platform_driver(hsdkv1_reset_driver); +builtin_platform_driver(hsdk_reset_driver); MODULE_AUTHOR("Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>"); -MODULE_DESCRIPTION("Synopsys HSDKv1 SDP reset driver"); +MODULE_DESCRIPTION("Synopsys HSDK SDP reset driver"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c index c60904ff40b8..3907bbc9c6cf 100644 --- a/drivers/reset/reset-socfpga.c +++ b/drivers/reset/reset-socfpga.c @@ -40,8 +40,9 @@ static int socfpga_reset_assert(struct reset_controller_dev *rcdev, struct socfpga_reset_data *data = container_of(rcdev, struct socfpga_reset_data, rcdev); - int bank = id / BITS_PER_LONG; - int offset = id % BITS_PER_LONG; + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); unsigned long flags; u32 reg; @@ -61,8 +62,9 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev, struct socfpga_reset_data, rcdev); - int bank = id / BITS_PER_LONG; - int offset = id % BITS_PER_LONG; + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); unsigned long flags; u32 reg; @@ -81,8 +83,9 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev, { struct socfpga_reset_data *data = container_of(rcdev, struct socfpga_reset_data, rcdev); - int bank = id / BITS_PER_LONG; - int offset = id % BITS_PER_LONG; + int reg_width = sizeof(u32); + int bank = id / (reg_width * BITS_PER_BYTE); + int offset = id % (reg_width * BITS_PER_BYTE); u32 reg; reg = readl(data->membase + (bank * BANK_INCREMENT)); @@ -132,7 +135,7 @@ static int socfpga_reset_probe(struct platform_device *pdev) spin_lock_init(&data->lock); data->rcdev.owner = THIS_MODULE; - data->rcdev.nr_resets = NR_BANKS * BITS_PER_LONG; + data->rcdev.nr_resets = NR_BANKS * (sizeof(u32) * BITS_PER_BYTE); data->rcdev.ops = &socfpga_reset_ops; data->rcdev.of_node = pdev->dev.of_node; diff --git a/drivers/rpmsg/qcom_glink_native.c b/drivers/rpmsg/qcom_glink_native.c index 5a5e927ea50f..5dcc9bf1c5bc 100644 --- a/drivers/rpmsg/qcom_glink_native.c +++ b/drivers/rpmsg/qcom_glink_native.c @@ -635,19 +635,18 @@ qcom_glink_alloc_intent(struct qcom_glink *glink, unsigned long flags; intent = kzalloc(sizeof(*intent), GFP_KERNEL); - if (!intent) return NULL; intent->data = kzalloc(size, GFP_KERNEL); if (!intent->data) - return NULL; + goto free_intent; spin_lock_irqsave(&channel->intent_lock, flags); ret = idr_alloc_cyclic(&channel->liids, intent, 1, -1, GFP_ATOMIC); if (ret < 0) { spin_unlock_irqrestore(&channel->intent_lock, flags); - return NULL; + goto free_data; } spin_unlock_irqrestore(&channel->intent_lock, flags); @@ -656,6 +655,12 @@ qcom_glink_alloc_intent(struct qcom_glink *glink, intent->reuse = reuseable; return intent; + +free_data: + kfree(intent->data); +free_intent: + kfree(intent); + return NULL; } static void qcom_glink_handle_rx_done(struct qcom_glink *glink, @@ -1197,7 +1202,7 @@ static int qcom_glink_request_intent(struct qcom_glink *glink, ret = qcom_glink_tx(glink, &cmd, sizeof(cmd), NULL, 0, true); if (ret) - return ret; + goto unlock; ret = wait_for_completion_timeout(&channel->intent_req_comp, 10 * HZ); if (!ret) { @@ -1207,6 +1212,7 @@ static int qcom_glink_request_intent(struct qcom_glink *glink, ret = channel->intent_req_result ? 0 : -ECANCELED; } +unlock: mutex_unlock(&channel->intent_req_lock); return ret; } diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 82ac331d9125..84752152d41f 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -357,6 +357,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device) adapter->next_port_scan = jiffies; + adapter->erp_action.adapter = adapter; + if (zfcp_qdio_setup(adapter)) goto failed; @@ -513,6 +515,9 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn, port->dev.groups = zfcp_port_attr_groups; port->dev.release = zfcp_port_release; + port->erp_action.adapter = adapter; + port->erp_action.port = port; + if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) { kfree(port); goto err_out; diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 37408f5f81ce..ec2532ee1822 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -193,9 +193,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &zfcp_sdev->status); erp_action = &zfcp_sdev->erp_action; - memset(erp_action, 0, sizeof(struct zfcp_erp_action)); - erp_action->port = port; - erp_action->sdev = sdev; + WARN_ON_ONCE(erp_action->port != port); + WARN_ON_ONCE(erp_action->sdev != sdev); if (!(atomic_read(&zfcp_sdev->status) & ZFCP_STATUS_COMMON_RUNNING)) act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; @@ -208,8 +207,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, zfcp_erp_action_dismiss_port(port); atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status); erp_action = &port->erp_action; - memset(erp_action, 0, sizeof(struct zfcp_erp_action)); - erp_action->port = port; + WARN_ON_ONCE(erp_action->port != port); + WARN_ON_ONCE(erp_action->sdev != NULL); if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING)) act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; break; @@ -219,7 +218,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, zfcp_erp_action_dismiss_adapter(adapter); atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status); erp_action = &adapter->erp_action; - memset(erp_action, 0, sizeof(struct zfcp_erp_action)); + WARN_ON_ONCE(erp_action->port != NULL); + WARN_ON_ONCE(erp_action->sdev != NULL); if (!(atomic_read(&adapter->status) & ZFCP_STATUS_COMMON_RUNNING)) act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY; @@ -229,7 +229,11 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status, return NULL; } - erp_action->adapter = adapter; + WARN_ON_ONCE(erp_action->adapter != adapter); + memset(&erp_action->list, 0, sizeof(erp_action->list)); + memset(&erp_action->timer, 0, sizeof(erp_action->timer)); + erp_action->step = ZFCP_ERP_STEP_UNINITIALIZED; + erp_action->fsf_req_id = 0; erp_action->action = need; erp_action->status = act_status; diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index ec3ddd1d31d5..6cf8732627e0 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -115,10 +115,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev) struct zfcp_unit *unit; int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE; + zfcp_sdev->erp_action.adapter = adapter; + zfcp_sdev->erp_action.sdev = sdev; + port = zfcp_get_port_by_wwpn(adapter, rport->port_name); if (!port) return -ENXIO; + zfcp_sdev->erp_action.port = port; + unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev)); if (unit) put_device(&unit->dev); diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c index 97d269f16888..1bc623ad3faf 100644 --- a/drivers/scsi/aacraid/comminit.c +++ b/drivers/scsi/aacraid/comminit.c @@ -302,9 +302,11 @@ int aac_send_shutdown(struct aac_dev * dev) return -ENOMEM; aac_fib_init(fibctx); - mutex_lock(&dev->ioctl_mutex); - dev->adapter_shutdown = 1; - mutex_unlock(&dev->ioctl_mutex); + if (!dev->adapter_shutdown) { + mutex_lock(&dev->ioctl_mutex); + dev->adapter_shutdown = 1; + mutex_unlock(&dev->ioctl_mutex); + } cmd = (struct aac_close *) fib_data(fibctx); cmd->command = cpu_to_le32(VM_CloseAll); diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 62beb2596466..c9252b138c1f 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -1551,8 +1551,9 @@ static void __aac_shutdown(struct aac_dev * aac) { int i; + mutex_lock(&aac->ioctl_mutex); aac->adapter_shutdown = 1; - aac_send_shutdown(aac); + mutex_unlock(&aac->ioctl_mutex); if (aac->aif_thread) { int i; @@ -1565,7 +1566,11 @@ static void __aac_shutdown(struct aac_dev * aac) } kthread_stop(aac->thread); } + + aac_send_shutdown(aac); + aac_adapter_disable_int(aac); + if (aac_is_src(aac)) { if (aac->max_msix > 1) { for (i = 0; i < aac->max_msix; i++) { diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9abe81021484..4ed3d26ffdde 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4091,7 +4091,7 @@ static int hpsa_set_local_logical_count(struct ctlr_info *h, memset(id_ctlr, 0, sizeof(*id_ctlr)); rc = hpsa_bmic_id_controller(h, id_ctlr, sizeof(*id_ctlr)); if (!rc) - if (id_ctlr->configured_logical_drive_count < 256) + if (id_ctlr->configured_logical_drive_count < 255) *nlocals = id_ctlr->configured_logical_drive_count; else *nlocals = le16_to_cpu( diff --git a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c index 785fb42f6650..2799a6b08f73 100644 --- a/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c +++ b/drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c @@ -3767,7 +3767,7 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd) */ if ((vscsi->flags & (CLIENT_FAILED | RESPONSE_Q_DOWN))) { pr_err("write_pending failed since: %d\n", vscsi->flags); - return 0; + return -EIO; } rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma, diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 520325867e2b..31d31aad3de1 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -383,11 +383,11 @@ static void fc_rport_work(struct work_struct *work) fc_rport_enter_flogi(rdata); mutex_unlock(&rdata->rp_mutex); } else { + mutex_unlock(&rdata->rp_mutex); FC_RPORT_DBG(rdata, "work delete\n"); mutex_lock(&lport->disc.disc_mutex); list_del_rcu(&rdata->peers); mutex_unlock(&lport->disc.disc_mutex); - mutex_unlock(&rdata->rp_mutex); kref_put(&rdata->kref, fc_rport_destroy); } } else { diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index bd4605a34f54..f8dc1601efd5 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1728,7 +1728,7 @@ int iscsi_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc) if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx)) { reason = FAILURE_SESSION_IN_RECOVERY; - sc->result = DID_REQUEUE; + sc->result = DID_REQUEUE << 16; goto fault; } @@ -2851,9 +2851,6 @@ EXPORT_SYMBOL_GPL(iscsi_session_setup); /** * iscsi_session_teardown - destroy session, host, and cls_session * @cls_session: iscsi session - * - * The driver must have called iscsi_remove_session before - * calling this. */ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) { @@ -2863,6 +2860,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) iscsi_pool_free(&session->cmdpool); + iscsi_remove_session(cls_session); + kfree(session->password); kfree(session->password_in); kfree(session->username); @@ -2877,7 +2876,8 @@ void iscsi_session_teardown(struct iscsi_cls_session *cls_session) kfree(session->portal_type); kfree(session->discovery_parent_type); - iscsi_destroy_session(cls_session); + iscsi_free_session(cls_session); + iscsi_host_dec_session_cnt(shost); module_put(owner); } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 5b2437a5ea44..3bd956d3bc5d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3061,6 +3061,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) host->max_cmd_len, host->max_channel, host->max_lun, host->transportt, sht->vendor_id); + INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn); + /* Set up the irqs */ ret = qla2x00_request_irqs(ha, rsp); if (ret) @@ -3223,7 +3225,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) */ qla2xxx_wake_dpc(base_vha); - INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn); INIT_WORK(&ha->board_disable, qla2x00_disable_board_on_pci_error); if (IS_QLA8031(ha) || IS_MCTP_CAPABLE(ha)) { diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 9cf6a80fe297..ad3ea24f0885 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1379,8 +1379,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) ret = scsi_setup_cmnd(sdev, req); out: - if (ret != BLKPREP_OK) - cmd->flags &= ~SCMD_INITIALIZED; return scsi_prep_return(q, req, ret); } @@ -1900,7 +1898,6 @@ static int scsi_mq_prep_fn(struct request *req) struct scsi_device *sdev = req->q->queuedata; struct Scsi_Host *shost = sdev->host; struct scatterlist *sg; - int ret; scsi_init_command(sdev, cmd); @@ -1934,10 +1931,7 @@ static int scsi_mq_prep_fn(struct request *req) blk_mq_start_request(req); - ret = scsi_setup_cmnd(sdev, req); - if (ret != BLK_STS_OK) - cmd->flags &= ~SCMD_INITIALIZED; - return ret; + return scsi_setup_cmnd(sdev, req); } static void scsi_mq_done(struct scsi_cmnd *cmd) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index e7818afeda2b..15590a063ad9 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -956,6 +956,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, if (*bflags & BLIST_NO_DIF) sdev->no_dif = 1; + if (*bflags & BLIST_UNMAP_LIMIT_WS) + sdev->unmap_limit_for_ws = 1; + sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT; if (*bflags & BLIST_TRY_VPD_PAGES) diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index bf53356f41f0..f796bd61f3f0 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -1376,13 +1376,19 @@ static void __scsi_remove_target(struct scsi_target *starget) spin_lock_irqsave(shost->host_lock, flags); restart: list_for_each_entry(sdev, &shost->__devices, siblings) { + /* + * We cannot call scsi_device_get() here, as + * we might've been called from rmmod() causing + * scsi_device_get() to fail the module_is_live() + * check. + */ if (sdev->channel != starget->channel || sdev->id != starget->id || - scsi_device_get(sdev)) + !get_device(&sdev->sdev_gendev)) continue; spin_unlock_irqrestore(shost->host_lock, flags); scsi_remove_device(sdev); - scsi_device_put(sdev); + put_device(&sdev->sdev_gendev); spin_lock_irqsave(shost->host_lock, flags); goto restart; } diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index cbd4495d0ff9..8c46a6d536af 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -3320,6 +3320,9 @@ int fc_block_scsi_eh(struct scsi_cmnd *cmnd) { struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device)); + if (WARN_ON_ONCE(!rport)) + return FAST_IO_FAIL; + return fc_block_rport(rport); } EXPORT_SYMBOL(fc_block_scsi_eh); diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 0190aeff5f7f..7404d26895f5 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2211,22 +2211,6 @@ void iscsi_free_session(struct iscsi_cls_session *session) EXPORT_SYMBOL_GPL(iscsi_free_session); /** - * iscsi_destroy_session - destroy iscsi session - * @session: iscsi_session - * - * Can be called by a LLD or iscsi_transport. There must not be - * any running connections. - */ -int iscsi_destroy_session(struct iscsi_cls_session *session) -{ - iscsi_remove_session(session); - ISCSI_DBG_TRANS_SESSION(session, "Completing session destruction\n"); - iscsi_free_session(session); - return 0; -} -EXPORT_SYMBOL_GPL(iscsi_destroy_session); - -/** * iscsi_create_conn - create iscsi class connection * @session: iscsi cls session * @dd_size: private driver data size diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index fb9f8b5f4673..d175c5c5ccf8 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -715,13 +715,21 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) break; case SD_LBP_WS16: - max_blocks = min_not_zero(sdkp->max_ws_blocks, - (u32)SD_MAX_WS16_BLOCKS); + if (sdkp->device->unmap_limit_for_ws) + max_blocks = sdkp->max_unmap_blocks; + else + max_blocks = sdkp->max_ws_blocks; + + max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS16_BLOCKS); break; case SD_LBP_WS10: - max_blocks = min_not_zero(sdkp->max_ws_blocks, - (u32)SD_MAX_WS10_BLOCKS); + if (sdkp->device->unmap_limit_for_ws) + max_blocks = sdkp->max_unmap_blocks; + else + max_blocks = sdkp->max_ws_blocks; + + max_blocks = min_not_zero(max_blocks, (u32)SD_MAX_WS10_BLOCKS); break; case SD_LBP_ZERO: @@ -3099,8 +3107,6 @@ static int sd_revalidate_disk(struct gendisk *disk) sd_read_security(sdkp, buffer); } - sdkp->first_scan = 0; - /* * We now have all cache related info, determine how we deal * with flush requests. @@ -3115,7 +3121,7 @@ static int sd_revalidate_disk(struct gendisk *disk) q->limits.max_dev_sectors = logical_to_sectors(sdp, dev_max); /* - * Use the device's preferred I/O size for reads and writes + * Determine the device's preferred I/O size for reads and writes * unless the reported value is unreasonably small, large, or * garbage. */ @@ -3129,8 +3135,19 @@ static int sd_revalidate_disk(struct gendisk *disk) rw_max = min_not_zero(logical_to_sectors(sdp, dev_max), (sector_t)BLK_DEF_MAX_SECTORS); - /* Combine with controller limits */ - q->limits.max_sectors = min(rw_max, queue_max_hw_sectors(q)); + /* Do not exceed controller limit */ + rw_max = min(rw_max, queue_max_hw_sectors(q)); + + /* + * Only update max_sectors if previously unset or if the current value + * exceeds the capabilities of the hardware. + */ + if (sdkp->first_scan || + q->limits.max_sectors > q->limits.max_dev_sectors || + q->limits.max_sectors > q->limits.max_hw_sectors) + q->limits.max_sectors = rw_max; + + sdkp->first_scan = 0; set_capacity(disk, logical_to_sectors(sdp, sdkp->capacity)); sd_config_write_same(sdkp); diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 0419c2298eab..aa28874e8fb9 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -837,7 +837,7 @@ sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo) val = 0; list_for_each_entry(srp, &sfp->rq_list, entry) { - if (val > SG_MAX_QUEUE) + if (val >= SG_MAX_QUEUE) break; rinfo[val].req_state = srp->done + 1; rinfo[val].problem = diff --git a/drivers/spi/spi-armada-3700.c b/drivers/spi/spi-armada-3700.c index 6c7d7a460689..568e1c65aa82 100644 --- a/drivers/spi/spi-armada-3700.c +++ b/drivers/spi/spi-armada-3700.c @@ -99,11 +99,6 @@ /* A3700_SPI_IF_TIME_REG */ #define A3700_SPI_CLK_CAPT_EDGE BIT(7) -/* Flags and macros for struct a3700_spi */ -#define A3700_INSTR_CNT 1 -#define A3700_ADDR_CNT 3 -#define A3700_DUMMY_CNT 1 - struct a3700_spi { struct spi_master *master; void __iomem *base; @@ -117,9 +112,6 @@ struct a3700_spi { u8 byte_len; u32 wait_mask; struct completion done; - u32 addr_cnt; - u32 instr_cnt; - size_t hdr_cnt; }; static u32 spireg_read(struct a3700_spi *a3700_spi, u32 offset) @@ -161,7 +153,7 @@ static void a3700_spi_deactivate_cs(struct a3700_spi *a3700_spi, } static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, - unsigned int pin_mode) + unsigned int pin_mode, bool receiving) { u32 val; @@ -177,6 +169,9 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi, break; case SPI_NBITS_QUAD: val |= A3700_SPI_DATA_PIN1; + /* RX during address reception uses 4-pin */ + if (receiving) + val |= A3700_SPI_ADDR_PIN; break; default: dev_err(&a3700_spi->master->dev, "wrong pin mode %u", pin_mode); @@ -392,7 +387,8 @@ static bool a3700_spi_wait_completion(struct spi_device *spi) spireg_write(a3700_spi, A3700_SPI_INT_MASK_REG, 0); - return true; + /* Timeout was reached */ + return false; } static bool a3700_spi_transfer_wait(struct spi_device *spi, @@ -446,59 +442,43 @@ static void a3700_spi_set_cs(struct spi_device *spi, bool enable) static void a3700_spi_header_set(struct a3700_spi *a3700_spi) { - u32 instr_cnt = 0, addr_cnt = 0, dummy_cnt = 0; + unsigned int addr_cnt; u32 val = 0; /* Clear the header registers */ spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, 0); spireg_write(a3700_spi, A3700_SPI_IF_RMODE_REG, 0); + spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, 0); /* Set header counters */ if (a3700_spi->tx_buf) { - if (a3700_spi->buf_len <= a3700_spi->instr_cnt) { - instr_cnt = a3700_spi->buf_len; - } else if (a3700_spi->buf_len <= (a3700_spi->instr_cnt + - a3700_spi->addr_cnt)) { - instr_cnt = a3700_spi->instr_cnt; - addr_cnt = a3700_spi->buf_len - instr_cnt; - } else if (a3700_spi->buf_len <= a3700_spi->hdr_cnt) { - instr_cnt = a3700_spi->instr_cnt; - addr_cnt = a3700_spi->addr_cnt; - /* Need to handle the normal write case with 1 byte - * data - */ - if (!a3700_spi->tx_buf[instr_cnt + addr_cnt]) - dummy_cnt = a3700_spi->buf_len - instr_cnt - - addr_cnt; + /* + * when tx data is not 4 bytes aligned, there will be unexpected + * bytes out of SPI output register, since it always shifts out + * as whole 4 bytes. This might cause incorrect transaction with + * some devices. To avoid that, use SPI header count feature to + * transfer up to 3 bytes of data first, and then make the rest + * of data 4-byte aligned. + */ + addr_cnt = a3700_spi->buf_len % 4; + if (addr_cnt) { + val = (addr_cnt & A3700_SPI_ADDR_CNT_MASK) + << A3700_SPI_ADDR_CNT_BIT; + spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, val); + + /* Update the buffer length to be transferred */ + a3700_spi->buf_len -= addr_cnt; + + /* transfer 1~3 bytes through address count */ + val = 0; + while (addr_cnt--) { + val = (val << 8) | a3700_spi->tx_buf[0]; + a3700_spi->tx_buf++; + } + spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, val); } - val |= ((instr_cnt & A3700_SPI_INSTR_CNT_MASK) - << A3700_SPI_INSTR_CNT_BIT); - val |= ((addr_cnt & A3700_SPI_ADDR_CNT_MASK) - << A3700_SPI_ADDR_CNT_BIT); - val |= ((dummy_cnt & A3700_SPI_DUMMY_CNT_MASK) - << A3700_SPI_DUMMY_CNT_BIT); } - spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, val); - - /* Update the buffer length to be transferred */ - a3700_spi->buf_len -= (instr_cnt + addr_cnt + dummy_cnt); - - /* Set Instruction */ - val = 0; - while (instr_cnt--) { - val = (val << 8) | a3700_spi->tx_buf[0]; - a3700_spi->tx_buf++; - } - spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, val); - - /* Set Address */ - val = 0; - while (addr_cnt--) { - val = (val << 8) | a3700_spi->tx_buf[0]; - a3700_spi->tx_buf++; - } - spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, val); } static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi) @@ -512,35 +492,12 @@ static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi) static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi) { u32 val; - int i = 0; while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) { - val = 0; - if (a3700_spi->buf_len >= 4) { - val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf); - spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); - - a3700_spi->buf_len -= 4; - a3700_spi->tx_buf += 4; - } else { - /* - * If the remained buffer length is less than 4-bytes, - * we should pad the write buffer with all ones. So that - * it avoids overwrite the unexpected bytes following - * the last one. - */ - val = GENMASK(31, 0); - while (a3700_spi->buf_len) { - val &= ~(0xff << (8 * i)); - val |= *a3700_spi->tx_buf++ << (8 * i); - i++; - a3700_spi->buf_len--; - - spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, - val); - } - break; - } + val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf); + spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val); + a3700_spi->buf_len -= 4; + a3700_spi->tx_buf += 4; } return 0; @@ -645,15 +602,18 @@ static int a3700_spi_transfer_one(struct spi_master *master, a3700_spi->rx_buf = xfer->rx_buf; a3700_spi->buf_len = xfer->len; - /* SPI transfer headers */ - a3700_spi_header_set(a3700_spi); - if (xfer->tx_buf) nbits = xfer->tx_nbits; else if (xfer->rx_buf) nbits = xfer->rx_nbits; - a3700_spi_pin_mode_set(a3700_spi, nbits); + a3700_spi_pin_mode_set(a3700_spi, nbits, xfer->rx_buf ? true : false); + + /* Flush the FIFOs */ + a3700_spi_fifo_flush(a3700_spi); + + /* Transfer first bytes of data when buffer is not 4-byte aligned */ + a3700_spi_header_set(a3700_spi); if (xfer->rx_buf) { /* Set read data length */ @@ -733,16 +693,11 @@ static int a3700_spi_transfer_one(struct spi_master *master, dev_err(&spi->dev, "wait wfifo empty timed out\n"); return -ETIMEDOUT; } - } else { - /* - * If the instruction in SPI_INSTR does not require data - * to be written to the SPI device, wait until SPI_RDY - * is 1 for the SPI interface to be in idle. - */ - if (!a3700_spi_transfer_wait(spi, A3700_SPI_XFER_RDY)) { - dev_err(&spi->dev, "wait xfer ready timed out\n"); - return -ETIMEDOUT; - } + } + + if (!a3700_spi_transfer_wait(spi, A3700_SPI_XFER_RDY)) { + dev_err(&spi->dev, "wait xfer ready timed out\n"); + return -ETIMEDOUT; } val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG); @@ -834,10 +789,6 @@ static int a3700_spi_probe(struct platform_device *pdev) memset(spi, 0, sizeof(struct a3700_spi)); spi->master = master; - spi->instr_cnt = A3700_INSTR_CNT; - spi->addr_cnt = A3700_ADDR_CNT; - spi->hdr_cnt = A3700_INSTR_CNT + A3700_ADDR_CNT + - A3700_DUMMY_CNT; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); spi->base = devm_ioremap_resource(dev, res); diff --git a/drivers/spi/spi-bcm-qspi.c b/drivers/spi/spi-bcm-qspi.c index 6ef6c44f39f5..a172ab299e80 100644 --- a/drivers/spi/spi-bcm-qspi.c +++ b/drivers/spi/spi-bcm-qspi.c @@ -1250,7 +1250,7 @@ int bcm_qspi_probe(struct platform_device *pdev, goto qspi_probe_err; } } else { - goto qspi_probe_err; + goto qspi_resource_err; } res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi"); @@ -1272,7 +1272,7 @@ int bcm_qspi_probe(struct platform_device *pdev, qspi->base[CHIP_SELECT] = devm_ioremap_resource(dev, res); if (IS_ERR(qspi->base[CHIP_SELECT])) { ret = PTR_ERR(qspi->base[CHIP_SELECT]); - goto qspi_probe_err; + goto qspi_resource_err; } } @@ -1280,7 +1280,7 @@ int bcm_qspi_probe(struct platform_device *pdev, GFP_KERNEL); if (!qspi->dev_ids) { ret = -ENOMEM; - goto qspi_probe_err; + goto qspi_resource_err; } for (val = 0; val < num_irqs; val++) { @@ -1369,8 +1369,9 @@ qspi_reg_err: bcm_qspi_hw_uninit(qspi); clk_disable_unprepare(qspi->clk); qspi_probe_err: - spi_master_put(master); kfree(qspi->dev_ids); +qspi_resource_err: + spi_master_put(master); return ret; } /* probe function to be called by SoC specific platform driver probe */ diff --git a/drivers/spi/spi-stm32.c b/drivers/spi/spi-stm32.c index 680cdf549506..ba9743fa2326 100644 --- a/drivers/spi/spi-stm32.c +++ b/drivers/spi/spi-stm32.c @@ -263,8 +263,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz) * no need to check it there. * However, we need to ensure the following calculations. */ - if ((div < SPI_MBR_DIV_MIN) && - (div > SPI_MBR_DIV_MAX)) + if (div < SPI_MBR_DIV_MIN || + div > SPI_MBR_DIV_MAX) return -EINVAL; /* Determine the first power of 2 greater than or equal to div */ diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 6e65524cbfd9..e8b5a5e21b2e 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -45,7 +45,6 @@ #define CREATE_TRACE_POINTS #include <trace/events/spi.h> -#define SPI_DYN_FIRST_BUS_NUM 0 static DEFINE_IDR(spi_master_idr); @@ -2086,7 +2085,7 @@ int spi_register_controller(struct spi_controller *ctlr) struct device *dev = ctlr->dev.parent; struct boardinfo *bi; int status = -ENODEV; - int id; + int id, first_dynamic; if (!dev) return -ENODEV; @@ -2116,9 +2115,15 @@ int spi_register_controller(struct spi_controller *ctlr) } } if (ctlr->bus_num < 0) { + first_dynamic = of_alias_get_highest_id("spi"); + if (first_dynamic < 0) + first_dynamic = 0; + else + first_dynamic++; + mutex_lock(&board_lock); - id = idr_alloc(&spi_master_idr, ctlr, SPI_DYN_FIRST_BUS_NUM, 0, - GFP_KERNEL); + id = idr_alloc(&spi_master_idr, ctlr, first_dynamic, + 0, GFP_KERNEL); mutex_unlock(&board_lock); if (WARN(id < 0, "couldn't get idr")) return id; diff --git a/drivers/staging/iio/adc/ad7192.c b/drivers/staging/iio/adc/ad7192.c index d11c6de9c777..6150d2780e22 100644 --- a/drivers/staging/iio/adc/ad7192.c +++ b/drivers/staging/iio/adc/ad7192.c @@ -223,11 +223,9 @@ static int ad7192_setup(struct ad7192_state *st, struct iio_dev *indio_dev = spi_get_drvdata(st->sd.spi); unsigned long long scale_uv; int i, ret, id; - u8 ones[6]; /* reset the serial interface */ - memset(&ones, 0xFF, 6); - ret = spi_write(st->sd.spi, &ones, 6); + ret = ad_sd_reset(&st->sd, 48); if (ret < 0) goto out; usleep_range(500, 1000); /* Wait for at least 500us */ diff --git a/drivers/staging/iio/meter/ade7759.c b/drivers/staging/iio/meter/ade7759.c index 1691760339da..02573c517d9d 100644 --- a/drivers/staging/iio/meter/ade7759.c +++ b/drivers/staging/iio/meter/ade7759.c @@ -172,7 +172,7 @@ static int ade7759_spi_read_reg_40(struct device *dev, reg_address); goto error_ret; } - *val = ((u64)st->rx[1] << 32) | (st->rx[2] << 24) | + *val = ((u64)st->rx[1] << 32) | ((u64)st->rx[2] << 24) | (st->rx[3] << 16) | (st->rx[4] << 8) | st->rx[5]; error_ret: diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c index d96f4512224f..b55e5ebba8b4 100644 --- a/drivers/staging/media/imx/imx-media-dev.c +++ b/drivers/staging/media/imx/imx-media-dev.c @@ -400,10 +400,10 @@ static int imx_media_create_pad_vdev_lists(struct imx_media_dev *imxmd) struct media_link, list); ret = imx_media_add_vdev_to_pad(imxmd, vdev, link->source); if (ret) - break; + return ret; } - return ret; + return 0; } /* async subdev complete notifier */ diff --git a/drivers/staging/mt29f_spinand/mt29f_spinand.c b/drivers/staging/mt29f_spinand/mt29f_spinand.c index 13eaf16ecd16..87595c594b12 100644 --- a/drivers/staging/mt29f_spinand/mt29f_spinand.c +++ b/drivers/staging/mt29f_spinand/mt29f_spinand.c @@ -496,8 +496,12 @@ static int spinand_program_page(struct spi_device *spi_nand, if (!wbuf) return -ENOMEM; - enable_read_hw_ecc = 0; - spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf); + enable_read_hw_ecc = 1; + retval = spinand_read_page(spi_nand, page_id, 0, CACHE_BUF, wbuf); + if (retval < 0) { + dev_err(&spi_nand->dev, "ecc error on read page!!!\n"); + return retval; + } for (i = offset, j = 0; i < len; i++, j++) wbuf[i] &= buf[j]; diff --git a/drivers/staging/pi433/rf69.c b/drivers/staging/pi433/rf69.c index c4b1b218ea38..290b419aa9dd 100644 --- a/drivers/staging/pi433/rf69.c +++ b/drivers/staging/pi433/rf69.c @@ -570,12 +570,6 @@ int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value) dev_dbg(&spi->dev, "set: DIO mapping"); #endif - // check DIO number - if (DIONumber > 5) { - dev_dbg(&spi->dev, "set: illegal input param"); - return -EINVAL; - } - switch (DIONumber) { case 0: mask=MASK_DIO0; shift=SHIFT_DIO0; regaddr=REG_DIOMAPPING1; break; case 1: mask=MASK_DIO1; shift=SHIFT_DIO1; regaddr=REG_DIOMAPPING1; break; @@ -583,6 +577,9 @@ int rf69_set_dio_mapping(struct spi_device *spi, u8 DIONumber, u8 value) case 3: mask=MASK_DIO3; shift=SHIFT_DIO3; regaddr=REG_DIOMAPPING1; break; case 4: mask=MASK_DIO4; shift=SHIFT_DIO4; regaddr=REG_DIOMAPPING2; break; case 5: mask=MASK_DIO5; shift=SHIFT_DIO5; regaddr=REG_DIOMAPPING2; break; + default: + dev_dbg(&spi->dev, "set: illegal input param"); + return -EINVAL; } // read reg diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c index 6b778206a1a3..cb8a95aabd6c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c @@ -119,9 +119,8 @@ void rtw_free_mlme_priv_ie_data(struct mlme_priv *pmlmepriv) void _rtw_free_mlme_priv(struct mlme_priv *pmlmepriv) { - rtw_free_mlme_priv_ie_data(pmlmepriv); - if (pmlmepriv) { + rtw_free_mlme_priv_ie_data(pmlmepriv); if (pmlmepriv->free_bss_buf) { vfree(pmlmepriv->free_bss_buf); } diff --git a/drivers/staging/rtl8723bs/os_dep/rtw_proc.c b/drivers/staging/rtl8723bs/os_dep/rtw_proc.c index 92277457aba4..ce1dd6f9036f 100644 --- a/drivers/staging/rtl8723bs/os_dep/rtw_proc.c +++ b/drivers/staging/rtl8723bs/os_dep/rtw_proc.c @@ -311,6 +311,8 @@ static ssize_t proc_set_cam(struct file *file, const char __user *buffer, size_t if (num < 2) return count; + if (id >= TOTAL_CAM_ENTRY) + return -EINVAL; if (strcmp("c", cmd) == 0) { _clear_cam_entry(adapter, id); diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c index 5f84526cb5b5..edbf6af1c8b7 100644 --- a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_api_88xx.c @@ -2901,11 +2901,11 @@ halmac_update_datapack_88xx(struct halmac_adapter *halmac_adapter, if (halmac_adapter->fw_version.h2c_version < 4) return HALMAC_RET_FW_NO_SUPPORT; + driver_adapter = halmac_adapter->driver_adapter; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, "[TRACE]%s ==========>\n", __func__); - driver_adapter = halmac_adapter->driver_adapter; - HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, "[TRACE]%s <==========\n", __func__); diff --git a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c index f33024e4d853..544f638ed3ef 100644 --- a/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c +++ b/drivers/staging/rtlwifi/halmac/halmac_88xx/halmac_func_88xx.c @@ -1618,10 +1618,11 @@ halmac_send_h2c_set_pwr_mode_88xx(struct halmac_adapter *halmac_adapter, void *driver_adapter = NULL; enum halmac_ret_status status = HALMAC_RET_SUCCESS; + driver_adapter = halmac_adapter->driver_adapter; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, "%s!!\n", __func__); - driver_adapter = halmac_adapter->driver_adapter; h2c_header = h2c_buff; h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX; @@ -1713,10 +1714,11 @@ halmac_media_status_rpt_88xx(struct halmac_adapter *halmac_adapter, u8 op_mode, void *driver_adapter = NULL; enum halmac_ret_status status = HALMAC_RET_SUCCESS; + driver_adapter = halmac_adapter->driver_adapter; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, "halmac_send_h2c_set_pwr_mode_88xx!!\n"); - driver_adapter = halmac_adapter->driver_adapter; h2c_header = H2c_buff; h2c_cmd = h2c_header + HALMAC_H2C_CMD_HDR_SIZE_88XX; @@ -2143,10 +2145,11 @@ halmac_func_ctrl_ch_switch_88xx(struct halmac_adapter *halmac_adapter, enum halmac_cmd_process_status *process_status = &halmac_adapter->halmac_state.scan_state_set.process_status; + driver_adapter = halmac_adapter->driver_adapter; + HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, "halmac_ctrl_ch_switch!!\n"); - driver_adapter = halmac_adapter->driver_adapter; halmac_api = (struct halmac_api *)halmac_adapter->halmac_api; if (halmac_transition_scan_state_88xx( @@ -2276,15 +2279,13 @@ enum halmac_ret_status halmac_send_h2c_update_bcn_parse_info_88xx( { u8 h2c_buff[HALMAC_H2C_CMD_SIZE_88XX] = {0}; u16 h2c_seq_mum = 0; - void *driver_adapter = NULL; + void *driver_adapter = halmac_adapter->driver_adapter; struct halmac_h2c_header_info h2c_header_info; enum halmac_ret_status status = HALMAC_RET_SUCCESS; HALMAC_RT_TRACE(driver_adapter, HALMAC_MSG_H2C, DBG_DMESG, "%s!!\n", __func__); - driver_adapter = halmac_adapter->driver_adapter; - UPDATE_BEACON_PARSING_INFO_SET_FUNC_EN(h2c_buff, bcn_ie_info->func_en); UPDATE_BEACON_PARSING_INFO_SET_SIZE_TH(h2c_buff, bcn_ie_info->size_th); UPDATE_BEACON_PARSING_INFO_SET_TIMEOUT(h2c_buff, bcn_ie_info->timeout); diff --git a/drivers/staging/speakup/main.c b/drivers/staging/speakup/main.c index 67956e24779c..56f7be6af1f6 100644 --- a/drivers/staging/speakup/main.c +++ b/drivers/staging/speakup/main.c @@ -1376,6 +1376,8 @@ static void reset_highlight_buffers(struct vc_data *); static int read_all_key; +static int in_keyboard_notifier; + static void start_read_all_timer(struct vc_data *vc, int command); enum { @@ -1408,7 +1410,10 @@ static void read_all_doc(struct vc_data *vc) cursor_track = read_all_mode; spk_reset_index_count(0); if (get_sentence_buf(vc, 0) == -1) { - kbd_fakekey2(vc, RA_DOWN_ARROW); + del_timer(&cursor_timer); + if (!in_keyboard_notifier) + speakup_fake_down_arrow(); + start_read_all_timer(vc, RA_DOWN_ARROW); } else { say_sentence_num(0, 0); synth_insert_next_index(0); @@ -2212,8 +2217,10 @@ static int keyboard_notifier_call(struct notifier_block *nb, int ret = NOTIFY_OK; static int keycode; /* to hold the current keycode */ + in_keyboard_notifier = 1; + if (vc->vc_mode == KD_GRAPHICS) - return ret; + goto out; /* * First, determine whether we are handling a fake keypress on @@ -2225,7 +2232,7 @@ static int keyboard_notifier_call(struct notifier_block *nb, */ if (speakup_fake_key_pressed()) - return ret; + goto out; switch (code) { case KBD_KEYCODE: @@ -2266,6 +2273,8 @@ static int keyboard_notifier_call(struct notifier_block *nb, break; } } +out: + in_keyboard_notifier = 0; return ret; } diff --git a/drivers/staging/unisys/visorbus/visorchipset.c b/drivers/staging/unisys/visorbus/visorchipset.c index 74cce4f1a7bd..27ecf6fb49fd 100644 --- a/drivers/staging/unisys/visorbus/visorchipset.c +++ b/drivers/staging/unisys/visorbus/visorchipset.c @@ -1826,7 +1826,7 @@ static __init int visorutil_spar_detect(void) return 0; } -static int init_unisys(void) +static int __init init_unisys(void) { int result; @@ -1841,7 +1841,7 @@ static int init_unisys(void) return 0; }; -static void exit_unisys(void) +static void __exit exit_unisys(void) { acpi_bus_unregister_driver(&unisys_acpi_driver); } diff --git a/drivers/staging/vboxvideo/vbox_mode.c b/drivers/staging/vboxvideo/vbox_mode.c index 257a77830410..c745a0402c68 100644 --- a/drivers/staging/vboxvideo/vbox_mode.c +++ b/drivers/staging/vboxvideo/vbox_mode.c @@ -377,7 +377,7 @@ static struct drm_encoder *vbox_best_single_encoder(struct drm_connector /* pick the encoder ids */ if (enc_id) - return drm_encoder_find(connector->dev, enc_id); + return drm_encoder_find(connector->dev, NULL, enc_id); return NULL; } diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c index 5f3d8f2339e3..4be864dbd41c 100644 --- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c +++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c @@ -390,8 +390,7 @@ static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream *alsa_stream __func__, instance); instance->alsa_stream = alsa_stream; alsa_stream->instance = instance; - ret = 0; // xxx todo -1; - goto err_free_mem; + return 0; } /* Initialize and create a VCHI connection */ @@ -401,16 +400,15 @@ static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream *alsa_stream LOG_ERR("%s: failed to initialise VCHI instance (ret=%d)\n", __func__, ret); - ret = -EIO; - goto err_free_mem; + return -EIO; } ret = vchi_connect(NULL, 0, vchi_instance); if (ret) { LOG_ERR("%s: failed to connect VCHI instance (ret=%d)\n", __func__, ret); - ret = -EIO; - goto err_free_mem; + kfree(vchi_instance); + return -EIO; } initted = 1; } @@ -421,19 +419,16 @@ static int bcm2835_audio_open_connection(struct bcm2835_alsa_stream *alsa_stream if (IS_ERR(instance)) { LOG_ERR("%s: failed to initialize audio service\n", __func__); - ret = PTR_ERR(instance); - goto err_free_mem; + /* vchi_instance is retained for use the next time. */ + return PTR_ERR(instance); } instance->alsa_stream = alsa_stream; alsa_stream->instance = instance; LOG_DBG(" success !\n"); - ret = 0; -err_free_mem: - kfree(vchi_instance); - return ret; + return 0; } int bcm2835_audio_open(struct bcm2835_alsa_stream *alsa_stream) diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c index 0159ca4407d8..be08849175ea 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_2835_arm.c @@ -612,18 +612,20 @@ free_pagelist(struct vchiq_pagelist_info *pagelistinfo, if (head_bytes > actual) head_bytes = actual; - memcpy((char *)page_address(pages[0]) + + memcpy((char *)kmap(pages[0]) + pagelist->offset, fragments, head_bytes); + kunmap(pages[0]); } if ((actual >= 0) && (head_bytes < actual) && (tail_bytes != 0)) { - memcpy((char *)page_address(pages[num_pages - 1]) + + memcpy((char *)kmap(pages[num_pages - 1]) + ((pagelist->offset + actual) & (PAGE_SIZE - 1) & ~(g_cache_line_size - 1)), fragments + g_cache_line_size, tail_bytes); + kunmap(pages[num_pages - 1]); } down(&g_free_fragments_mutex); diff --git a/drivers/tty/mxser.c b/drivers/tty/mxser.c index 1c0c9553bc05..7dd38047ba23 100644 --- a/drivers/tty/mxser.c +++ b/drivers/tty/mxser.c @@ -246,11 +246,11 @@ struct mxser_port { unsigned char err_shadow; struct async_icount icount; /* kernel counters for 4 input interrupts */ - int timeout; + unsigned int timeout; int read_status_mask; int ignore_status_mask; - int xmit_fifo_size; + unsigned int xmit_fifo_size; int xmit_head; int xmit_tail; int xmit_cnt; @@ -572,8 +572,9 @@ static void mxser_dtr_rts(struct tty_port *port, int on) static int mxser_set_baud(struct tty_struct *tty, long newspd) { struct mxser_port *info = tty->driver_data; - int quot = 0, baud; + unsigned int quot = 0, baud; unsigned char cval; + u64 timeout; if (!info->ioaddr) return -1; @@ -594,8 +595,13 @@ static int mxser_set_baud(struct tty_struct *tty, long newspd) quot = 0; } - info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base); - info->timeout += HZ / 50; /* Add .02 seconds of slop */ + /* + * worst case (128 * 1000 * 10 * 18432) needs 35 bits, so divide in the + * u64 domain + */ + timeout = (u64)info->xmit_fifo_size * HZ * 10 * quot; + do_div(timeout, info->baud_base); + info->timeout = timeout + HZ / 50; /* Add .02 seconds of slop */ if (quot) { info->MCR |= UART_MCR_DTR; diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index 583c9a0c7ecc..8c48c3784831 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c @@ -507,9 +507,14 @@ static void bcm_uart_set_termios(struct uart_port *port, { unsigned int ctl, baud, quot, ier; unsigned long flags; + int tries; spin_lock_irqsave(&port->lock, flags); + /* Drain the hot tub fully before we power it off for the winter. */ + for (tries = 3; !bcm_uart_tx_empty(port) && tries; tries--) + mdelay(10); + /* disable uart while changing speed */ bcm_uart_disable(port); bcm_uart_flush(port); diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c index 849c1f9991ce..f0252184291e 100644 --- a/drivers/tty/serial/fsl_lpuart.c +++ b/drivers/tty/serial/fsl_lpuart.c @@ -1276,7 +1276,6 @@ static void rx_dma_timer_init(struct lpuart_port *sport) static int lpuart_startup(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - int ret; unsigned long flags; unsigned char temp; @@ -1291,11 +1290,6 @@ static int lpuart_startup(struct uart_port *port) sport->rxfifo_size = 0x1 << (((temp >> UARTPFIFO_RXSIZE_OFF) & UARTPFIFO_FIFOSIZE_MASK) + 1); - ret = devm_request_irq(port->dev, port->irq, lpuart_int, 0, - DRIVER_NAME, sport); - if (ret) - return ret; - spin_lock_irqsave(&sport->port.lock, flags); lpuart_setup_watermark(sport); @@ -1333,7 +1327,6 @@ static int lpuart_startup(struct uart_port *port) static int lpuart32_startup(struct uart_port *port) { struct lpuart_port *sport = container_of(port, struct lpuart_port, port); - int ret; unsigned long flags; unsigned long temp; @@ -1346,11 +1339,6 @@ static int lpuart32_startup(struct uart_port *port) sport->rxfifo_size = 0x1 << (((temp >> UARTFIFO_RXSIZE_OFF) & UARTFIFO_FIFOSIZE_MASK) - 1); - ret = devm_request_irq(port->dev, port->irq, lpuart32_int, 0, - DRIVER_NAME, sport); - if (ret) - return ret; - spin_lock_irqsave(&sport->port.lock, flags); lpuart32_setup_watermark(sport); @@ -1380,8 +1368,6 @@ static void lpuart_shutdown(struct uart_port *port) spin_unlock_irqrestore(&port->lock, flags); - devm_free_irq(port->dev, port->irq, sport); - if (sport->lpuart_dma_rx_use) { del_timer_sync(&sport->lpuart_timer); lpuart_dma_rx_free(&sport->port); @@ -1400,7 +1386,6 @@ static void lpuart_shutdown(struct uart_port *port) static void lpuart32_shutdown(struct uart_port *port) { - struct lpuart_port *sport = container_of(port, struct lpuart_port, port); unsigned long temp; unsigned long flags; @@ -1413,8 +1398,6 @@ static void lpuart32_shutdown(struct uart_port *port) lpuart32_write(port, temp, UARTCTRL); spin_unlock_irqrestore(&port->lock, flags); - - devm_free_irq(port->dev, port->irq, sport); } static void @@ -2212,16 +2195,22 @@ static int lpuart_probe(struct platform_device *pdev) platform_set_drvdata(pdev, &sport->port); - if (lpuart_is_32(sport)) + if (lpuart_is_32(sport)) { lpuart_reg.cons = LPUART32_CONSOLE; - else + ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart32_int, 0, + DRIVER_NAME, sport); + } else { lpuart_reg.cons = LPUART_CONSOLE; + ret = devm_request_irq(&pdev->dev, sport->port.irq, lpuart_int, 0, + DRIVER_NAME, sport); + } + + if (ret) + goto failed_irq_request; ret = uart_add_one_port(&lpuart_reg, &sport->port); - if (ret) { - clk_disable_unprepare(sport->clk); - return ret; - } + if (ret) + goto failed_attach_port; sport->dma_tx_chan = dma_request_slave_channel(sport->port.dev, "tx"); if (!sport->dma_tx_chan) @@ -2240,6 +2229,11 @@ static int lpuart_probe(struct platform_device *pdev) } return 0; + +failed_attach_port: +failed_irq_request: + clk_disable_unprepare(sport->clk); + return ret; } static int lpuart_remove(struct platform_device *pdev) diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c index cdd2f942317c..b9c7a904c1ea 100644 --- a/drivers/tty/serial/sccnxp.c +++ b/drivers/tty/serial/sccnxp.c @@ -889,7 +889,16 @@ static int sccnxp_probe(struct platform_device *pdev) goto err_out; uartclk = 0; } else { - clk_prepare_enable(clk); + ret = clk_prepare_enable(clk); + if (ret) + goto err_out; + + ret = devm_add_action_or_reset(&pdev->dev, + (void(*)(void *))clk_disable_unprepare, + clk); + if (ret) + goto err_out; + uartclk = clk_get_rate(clk); } @@ -988,7 +997,7 @@ static int sccnxp_probe(struct platform_device *pdev) uart_unregister_driver(&s->uart); err_out: if (!IS_ERR(s->regulator)) - return regulator_disable(s->regulator); + regulator_disable(s->regulator); return ret; } diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 2fe216b276e2..84a8ac2a779f 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -694,10 +694,8 @@ int tty_ldisc_reinit(struct tty_struct *tty, int disc) tty_set_termios_ldisc(tty, disc); retval = tty_ldisc_open(tty, tty->ldisc); if (retval) { - if (!WARN_ON(disc == N_TTY)) { - tty_ldisc_put(tty->ldisc); - tty->ldisc = NULL; - } + tty_ldisc_put(tty->ldisc); + tty->ldisc = NULL; } return retval; } @@ -752,8 +750,9 @@ void tty_ldisc_hangup(struct tty_struct *tty, bool reinit) if (tty->ldisc) { if (reinit) { - if (tty_ldisc_reinit(tty, tty->termios.c_line) < 0) - tty_ldisc_reinit(tty, N_TTY); + if (tty_ldisc_reinit(tty, tty->termios.c_line) < 0 && + tty_ldisc_reinit(tty, N_TTY) < 0) + WARN_ON(tty_ldisc_reinit(tty, N_NULL) < 0); } else tty_ldisc_kill(tty); } diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 5e056064259c..18c923a4c16e 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1832,6 +1832,9 @@ static const struct usb_device_id acm_ids[] = { { USB_DEVICE(0xfff0, 0x0100), /* DATECS FP-2000 */ .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ }, + { USB_DEVICE(0x09d8, 0x0320), /* Elatec GmbH TWN3 */ + .driver_info = NO_UNION_NORMAL, /* has misplaced union descriptor */ + }, { USB_DEVICE(0x2912, 0x0001), /* ATOL FPrint */ .driver_info = CLEAR_HALT_CONDITIONS, diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 5aacea1978a5..3e865dbf878c 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c @@ -190,8 +190,10 @@ static void wdm_in_callback(struct urb *urb) /* * only set a new error if there is no previous error. * Errors are only cleared during read/open + * Avoid propagating -EPIPE (stall) to userspace since it is + * better handled as an empty read */ - if (desc->rerr == 0) + if (desc->rerr == 0 && status != -EPIPE) desc->rerr = status; if (length + desc->length > desc->wMaxCommand) { diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index 4be52c602e9b..883549ee946c 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -643,15 +643,23 @@ static int usb_parse_configuration(struct usb_device *dev, int cfgidx, } else if (header->bDescriptorType == USB_DT_INTERFACE_ASSOCIATION) { + struct usb_interface_assoc_descriptor *d; + + d = (struct usb_interface_assoc_descriptor *)header; + if (d->bLength < USB_DT_INTERFACE_ASSOCIATION_SIZE) { + dev_warn(ddev, + "config %d has an invalid interface association descriptor of length %d, skipping\n", + cfgno, d->bLength); + continue; + } + if (iad_num == USB_MAXIADS) { dev_warn(ddev, "found more Interface " "Association Descriptors " "than allocated for in " "configuration %d\n", cfgno); } else { - config->intf_assoc[iad_num] = - (struct usb_interface_assoc_descriptor - *)header; + config->intf_assoc[iad_num] = d; iad_num++; } @@ -852,7 +860,7 @@ int usb_get_configuration(struct usb_device *dev) } if (dev->quirks & USB_QUIRK_DELAY_INIT) - msleep(100); + msleep(200); result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, bigbuffer, length); @@ -952,10 +960,12 @@ int usb_get_bos_descriptor(struct usb_device *dev) for (i = 0; i < num; i++) { buffer += length; cap = (struct usb_dev_cap_header *)buffer; - length = cap->bLength; - if (total_len < length) + if (total_len < sizeof(*cap) || total_len < cap->bLength) { + dev->bos->desc->bNumDeviceCaps = i; break; + } + length = cap->bLength; total_len -= length; if (cap->bDescriptorType != USB_DT_DEVICE_CAPABILITY) { diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 318bb3b96687..e9326f31db8d 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -140,6 +140,9 @@ module_param(usbfs_memory_mb, uint, 0644); MODULE_PARM_DESC(usbfs_memory_mb, "maximum MB allowed for usbfs buffers (0 = no limit)"); +/* Hard limit, necessary to avoid arithmetic overflow */ +#define USBFS_XFER_MAX (UINT_MAX / 2 - 1000000) + static atomic64_t usbfs_memory_usage; /* Total memory currently allocated */ /* Check whether it's okay to allocate more memory for a transfer */ @@ -1460,6 +1463,8 @@ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb USBDEVFS_URB_ZERO_PACKET | USBDEVFS_URB_NO_INTERRUPT)) return -EINVAL; + if ((unsigned int)uurb->buffer_length >= USBFS_XFER_MAX) + return -EINVAL; if (uurb->buffer_length > 0 && !uurb->buffer) return -EINVAL; if (!(uurb->type == USBDEVFS_URB_TYPE_CONTROL && diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 41eaf0b52518..e9ce6bb0b22d 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2710,13 +2710,16 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, if (!(portstatus & USB_PORT_STAT_CONNECTION)) return -ENOTCONN; - /* bomb out completely if the connection bounced. A USB 3.0 - * connection may bounce if multiple warm resets were issued, + /* Retry if connect change is set but status is still connected. + * A USB 3.0 connection may bounce if multiple warm resets were issued, * but the device may have successfully re-connected. Ignore it. */ if (!hub_is_superspeed(hub->hdev) && - (portchange & USB_PORT_STAT_C_CONNECTION)) - return -ENOTCONN; + (portchange & USB_PORT_STAT_C_CONNECTION)) { + usb_clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_C_CONNECTION); + return -EAGAIN; + } if (!(portstatus & USB_PORT_STAT_ENABLE)) return -EBUSY; @@ -4838,7 +4841,7 @@ static void hub_port_connect(struct usb_hub *hub, int port1, u16 portstatus, goto loop; if (udev->quirks & USB_QUIRK_DELAY_INIT) - msleep(1000); + msleep(2000); /* consecutive bus-powered hubs aren't reliable; they can * violate the voltage drop budget. if the new child has diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 4c38ea41ae96..371a07d874a3 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -2069,6 +2069,10 @@ int cdc_parse_cdc_header(struct usb_cdc_parsed_header *hdr, elength = 1; goto next_desc; } + if ((buflen < elength) || (elength < 3)) { + dev_err(&intf->dev, "invalid descriptor buffer length\n"); + break; + } if (buffer[1] != USB_DT_CS_INTERFACE) { dev_err(&intf->dev, "skipping garbage\n"); goto next_desc; diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 82806e311202..a6aaf2f193a4 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -221,6 +221,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* Corsair Strafe RGB */ { USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT }, + /* MIDI keyboard WORLDE MINI */ + { USB_DEVICE(0x1c75, 0x0204), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* Acer C120 LED Projector */ { USB_DEVICE(0x1de1, 0xc102), .driver_info = USB_QUIRK_NO_LPM }, diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c index 4cef7d4f9cd0..a26d1fde0f5e 100644 --- a/drivers/usb/dwc3/dwc3-of-simple.c +++ b/drivers/usb/dwc3/dwc3-of-simple.c @@ -177,6 +177,7 @@ static const struct of_device_id of_dwc3_simple_match[] = { { .compatible = "rockchip,rk3399-dwc3" }, { .compatible = "xlnx,zynqmp-dwc3" }, { .compatible = "cavium,octeon-7130-usb-uctl" }, + { .compatible = "sprd,sc9860-dwc3" }, { /* Sentinel */ } }; MODULE_DEVICE_TABLE(of, of_dwc3_simple_match); diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 827e376bfa97..75e6cb044eb2 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -990,6 +990,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, DWC3_TRBCTL_CONTROL_DATA, true); + req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1]; + /* Now prepare one extra TRB to align transfer size */ dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, maxpacket - rem, @@ -1015,6 +1017,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, DWC3_TRBCTL_CONTROL_DATA, true); + req->trb = &dwc->ep0_trb[dep->trb_enqueue - 1]; + /* Now prepare one extra TRB to align transfer size */ dwc3_ep0_prepare_one_trb(dep, dwc->bounce_addr, 0, DWC3_TRBCTL_CONTROL_DATA, @@ -1029,6 +1033,9 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, dwc3_ep0_prepare_one_trb(dep, req->request.dma, req->request.length, DWC3_TRBCTL_CONTROL_DATA, false); + + req->trb = &dwc->ep0_trb[dep->trb_enqueue]; + ret = dwc3_ep0_start_trans(dep); } diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index dd74c99d6ce1..5d061b3d8224 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -2026,6 +2026,8 @@ static DEVICE_ATTR_RO(suspended); static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) { struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_gadget_strings *gstr = cdev->driver->strings[0]; + struct usb_string *dev_str = gstr->strings; /* composite_disconnect() must already have been called * by the underlying peripheral controller driver! @@ -2045,6 +2047,9 @@ static void __composite_unbind(struct usb_gadget *gadget, bool unbind_driver) composite_dev_cleanup(cdev); + if (dev_str[USB_GADGET_MANUFACTURER_IDX].s == cdev->def_manufacturer) + dev_str[USB_GADGET_MANUFACTURER_IDX].s = ""; + kfree(cdev->def_manufacturer); kfree(cdev); set_gadget_data(gadget, NULL); diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c index a22a892de7b7..aeb9f3c40521 100644 --- a/drivers/usb/gadget/configfs.c +++ b/drivers/usb/gadget/configfs.c @@ -1143,11 +1143,12 @@ static struct configfs_attribute *interf_grp_attrs[] = { NULL }; -int usb_os_desc_prepare_interf_dir(struct config_group *parent, - int n_interf, - struct usb_os_desc **desc, - char **names, - struct module *owner) +struct config_group *usb_os_desc_prepare_interf_dir( + struct config_group *parent, + int n_interf, + struct usb_os_desc **desc, + char **names, + struct module *owner) { struct config_group *os_desc_group; struct config_item_type *os_desc_type, *interface_type; @@ -1159,7 +1160,7 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent, char *vlabuf = kzalloc(vla_group_size(data_chunk), GFP_KERNEL); if (!vlabuf) - return -ENOMEM; + return ERR_PTR(-ENOMEM); os_desc_group = vla_ptr(vlabuf, data_chunk, os_desc_group); os_desc_type = vla_ptr(vlabuf, data_chunk, os_desc_type); @@ -1184,7 +1185,7 @@ int usb_os_desc_prepare_interf_dir(struct config_group *parent, configfs_add_default_group(&d->group, os_desc_group); } - return 0; + return os_desc_group; } EXPORT_SYMBOL(usb_os_desc_prepare_interf_dir); diff --git a/drivers/usb/gadget/configfs.h b/drivers/usb/gadget/configfs.h index 36c468c4f5e9..540d5e92ed22 100644 --- a/drivers/usb/gadget/configfs.h +++ b/drivers/usb/gadget/configfs.h @@ -5,11 +5,12 @@ void unregister_gadget_item(struct config_item *item); -int usb_os_desc_prepare_interf_dir(struct config_group *parent, - int n_interf, - struct usb_os_desc **desc, - char **names, - struct module *owner); +struct config_group *usb_os_desc_prepare_interf_dir( + struct config_group *parent, + int n_interf, + struct usb_os_desc **desc, + char **names, + struct module *owner); static inline struct usb_os_desc *to_usb_os_desc(struct config_item *item) { diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 9990944a7245..8b342587f8ad 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -46,7 +46,8 @@ static void ffs_data_get(struct ffs_data *ffs); static void ffs_data_put(struct ffs_data *ffs); /* Creates new ffs_data object. */ -static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc)); +static struct ffs_data *__must_check ffs_data_new(const char *dev_name) + __attribute__((malloc)); /* Opened counter handling. */ static void ffs_data_opened(struct ffs_data *ffs); @@ -780,11 +781,12 @@ static void ffs_epfile_async_io_complete(struct usb_ep *_ep, struct usb_request *req) { struct ffs_io_data *io_data = req->context; + struct ffs_data *ffs = io_data->ffs; ENTER(); INIT_WORK(&io_data->work, ffs_user_copy_worker); - schedule_work(&io_data->work); + queue_work(ffs->io_completion_wq, &io_data->work); } static void __ffs_epfile_read_buffer_free(struct ffs_epfile *epfile) @@ -1500,7 +1502,7 @@ ffs_fs_mount(struct file_system_type *t, int flags, if (unlikely(ret < 0)) return ERR_PTR(ret); - ffs = ffs_data_new(); + ffs = ffs_data_new(dev_name); if (unlikely(!ffs)) return ERR_PTR(-ENOMEM); ffs->file_perms = data.perms; @@ -1610,6 +1612,7 @@ static void ffs_data_put(struct ffs_data *ffs) BUG_ON(waitqueue_active(&ffs->ev.waitq) || waitqueue_active(&ffs->ep0req_completion.wait) || waitqueue_active(&ffs->wait)); + destroy_workqueue(ffs->io_completion_wq); kfree(ffs->dev_name); kfree(ffs); } @@ -1642,7 +1645,7 @@ static void ffs_data_closed(struct ffs_data *ffs) ffs_data_put(ffs); } -static struct ffs_data *ffs_data_new(void) +static struct ffs_data *ffs_data_new(const char *dev_name) { struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); if (unlikely(!ffs)) @@ -1650,6 +1653,12 @@ static struct ffs_data *ffs_data_new(void) ENTER(); + ffs->io_completion_wq = alloc_ordered_workqueue("%s", 0, dev_name); + if (!ffs->io_completion_wq) { + kfree(ffs); + return NULL; + } + refcount_set(&ffs->ref, 1); atomic_set(&ffs->opened, 0); ffs->state = FFS_READ_DESCRIPTORS; diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c index d6bd0244b008..5153e29870c3 100644 --- a/drivers/usb/gadget/function/f_mass_storage.c +++ b/drivers/usb/gadget/function/f_mass_storage.c @@ -307,8 +307,6 @@ struct fsg_common { struct completion thread_notifier; struct task_struct *thread_task; - /* Callback functions. */ - const struct fsg_operations *ops; /* Gadget's private data. */ void *private_data; @@ -2438,6 +2436,7 @@ static void handle_exception(struct fsg_common *common) static int fsg_main_thread(void *common_) { struct fsg_common *common = common_; + int i; /* * Allow the thread to be killed by a signal, but set the signal mask @@ -2476,21 +2475,16 @@ static int fsg_main_thread(void *common_) common->thread_task = NULL; spin_unlock_irq(&common->lock); - if (!common->ops || !common->ops->thread_exits - || common->ops->thread_exits(common) < 0) { - int i; + /* Eject media from all LUNs */ - down_write(&common->filesem); - for (i = 0; i < ARRAY_SIZE(common->luns); i++) { - struct fsg_lun *curlun = common->luns[i]; - if (!curlun || !fsg_lun_is_open(curlun)) - continue; + down_write(&common->filesem); + for (i = 0; i < ARRAY_SIZE(common->luns); i++) { + struct fsg_lun *curlun = common->luns[i]; + if (curlun && fsg_lun_is_open(curlun)) fsg_lun_close(curlun); - curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; - } - up_write(&common->filesem); } + up_write(&common->filesem); /* Let fsg_unbind() know the thread has exited */ complete_and_exit(&common->thread_notifier, 0); @@ -2681,13 +2675,6 @@ void fsg_common_remove_luns(struct fsg_common *common) } EXPORT_SYMBOL_GPL(fsg_common_remove_luns); -void fsg_common_set_ops(struct fsg_common *common, - const struct fsg_operations *ops) -{ - common->ops = ops; -} -EXPORT_SYMBOL_GPL(fsg_common_set_ops); - void fsg_common_free_buffers(struct fsg_common *common) { _fsg_common_free_buffers(common->buffhds, common->fsg_num_buffers); diff --git a/drivers/usb/gadget/function/f_mass_storage.h b/drivers/usb/gadget/function/f_mass_storage.h index d3902313b8ac..dc05ca0c4359 100644 --- a/drivers/usb/gadget/function/f_mass_storage.h +++ b/drivers/usb/gadget/function/f_mass_storage.h @@ -60,17 +60,6 @@ struct fsg_module_parameters { struct fsg_common; /* FSF callback functions */ -struct fsg_operations { - /* - * Callback function to call when thread exits. If no - * callback is set or it returns value lower then zero MSF - * will force eject all LUNs it operates on (including those - * marked as non-removable or with prevent_medium_removal flag - * set). - */ - int (*thread_exits)(struct fsg_common *common); -}; - struct fsg_lun_opts { struct config_group group; struct fsg_lun *lun; @@ -142,9 +131,6 @@ void fsg_common_remove_lun(struct fsg_lun *lun); void fsg_common_remove_luns(struct fsg_common *common); -void fsg_common_set_ops(struct fsg_common *common, - const struct fsg_operations *ops); - int fsg_common_create_lun(struct fsg_common *common, struct fsg_lun_config *cfg, unsigned int id, const char *name, const char **name_pfx); diff --git a/drivers/usb/gadget/function/f_printer.c b/drivers/usb/gadget/function/f_printer.c index 8df244fc9d80..ea0da35a44e2 100644 --- a/drivers/usb/gadget/function/f_printer.c +++ b/drivers/usb/gadget/function/f_printer.c @@ -555,6 +555,7 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) size_t size; /* Amount of data in a TX request. */ size_t bytes_copied = 0; struct usb_request *req; + int value; DBG(dev, "printer_write trying to send %d bytes\n", (int)len); @@ -634,7 +635,11 @@ printer_write(struct file *fd, const char __user *buf, size_t len, loff_t *ptr) return -EAGAIN; } - if (usb_ep_queue(dev->in_ep, req, GFP_ATOMIC)) { + /* here, we unlock, and only unlock, to avoid deadlock. */ + spin_unlock(&dev->lock); + value = usb_ep_queue(dev->in_ep, req, GFP_ATOMIC); + spin_lock(&dev->lock); + if (value) { list_add(&req->list, &dev->tx_reqs); spin_unlock_irqrestore(&dev->lock, flags); mutex_unlock(&dev->lock_printer_io); diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c index e1d5853ef1e4..c7c5b3ce1d98 100644 --- a/drivers/usb/gadget/function/f_rndis.c +++ b/drivers/usb/gadget/function/f_rndis.c @@ -908,6 +908,7 @@ static void rndis_free_inst(struct usb_function_instance *f) free_netdev(opts->net); } + kfree(opts->rndis_interf_group); /* single VLA chunk */ kfree(opts); } @@ -916,6 +917,7 @@ static struct usb_function_instance *rndis_alloc_inst(void) struct f_rndis_opts *opts; struct usb_os_desc *descs[1]; char *names[1]; + struct config_group *rndis_interf_group; opts = kzalloc(sizeof(*opts), GFP_KERNEL); if (!opts) @@ -940,8 +942,14 @@ static struct usb_function_instance *rndis_alloc_inst(void) names[0] = "rndis"; config_group_init_type_name(&opts->func_inst.group, "", &rndis_func_type); - usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, - names, THIS_MODULE); + rndis_interf_group = + usb_os_desc_prepare_interf_dir(&opts->func_inst.group, 1, descs, + names, THIS_MODULE); + if (IS_ERR(rndis_interf_group)) { + rndis_free_inst(&opts->func_inst); + return ERR_CAST(rndis_interf_group); + } + opts->rndis_interf_group = rndis_interf_group; return &opts->func_inst; } diff --git a/drivers/usb/gadget/function/u_fs.h b/drivers/usb/gadget/function/u_fs.h index 540f1c48c1a8..79f70ebf85dc 100644 --- a/drivers/usb/gadget/function/u_fs.h +++ b/drivers/usb/gadget/function/u_fs.h @@ -279,6 +279,7 @@ struct ffs_data { } file_perms; struct eventfd_ctx *ffs_eventfd; + struct workqueue_struct *io_completion_wq; bool no_disconnect; struct work_struct reset_work; diff --git a/drivers/usb/gadget/function/u_rndis.h b/drivers/usb/gadget/function/u_rndis.h index a35ee3c2545d..efdb7ac381d9 100644 --- a/drivers/usb/gadget/function/u_rndis.h +++ b/drivers/usb/gadget/function/u_rndis.h @@ -26,6 +26,7 @@ struct f_rndis_opts { bool bound; bool borrowed_net; + struct config_group *rndis_interf_group; struct usb_os_desc rndis_os_desc; char rndis_ext_compat_id[16]; diff --git a/drivers/usb/gadget/legacy/inode.c b/drivers/usb/gadget/legacy/inode.c index 684900fcfe24..5c28bee327e1 100644 --- a/drivers/usb/gadget/legacy/inode.c +++ b/drivers/usb/gadget/legacy/inode.c @@ -28,7 +28,7 @@ #include <linux/aio.h> #include <linux/uio.h> #include <linux/refcount.h> - +#include <linux/delay.h> #include <linux/device.h> #include <linux/moduleparam.h> @@ -116,6 +116,7 @@ enum ep0_state { struct dev_data { spinlock_t lock; refcount_t count; + int udc_usage; enum ep0_state state; /* P: lock */ struct usb_gadgetfs_event event [N_EVENT]; unsigned ev_next; @@ -513,9 +514,9 @@ static void ep_aio_complete(struct usb_ep *ep, struct usb_request *req) INIT_WORK(&priv->work, ep_user_copy_worker); schedule_work(&priv->work); } - spin_unlock(&epdata->dev->lock); usb_ep_free_request(ep, req); + spin_unlock(&epdata->dev->lock); put_ep(epdata); } @@ -939,9 +940,11 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) struct usb_request *req = dev->req; if ((retval = setup_req (ep, req, 0)) == 0) { + ++dev->udc_usage; spin_unlock_irq (&dev->lock); retval = usb_ep_queue (ep, req, GFP_KERNEL); spin_lock_irq (&dev->lock); + --dev->udc_usage; } dev->state = STATE_DEV_CONNECTED; @@ -983,11 +986,14 @@ ep0_read (struct file *fd, char __user *buf, size_t len, loff_t *ptr) retval = -EIO; else { len = min (len, (size_t)dev->req->actual); -// FIXME don't call this with the spinlock held ... + ++dev->udc_usage; + spin_unlock_irq(&dev->lock); if (copy_to_user (buf, dev->req->buf, len)) retval = -EFAULT; else retval = len; + spin_lock_irq(&dev->lock); + --dev->udc_usage; clean_req (dev->gadget->ep0, dev->req); /* NOTE userspace can't yet choose to stall */ } @@ -1131,6 +1137,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) retval = setup_req (dev->gadget->ep0, dev->req, len); if (retval == 0) { dev->state = STATE_DEV_CONNECTED; + ++dev->udc_usage; spin_unlock_irq (&dev->lock); if (copy_from_user (dev->req->buf, buf, len)) retval = -EFAULT; @@ -1142,6 +1149,7 @@ ep0_write (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) GFP_KERNEL); } spin_lock_irq(&dev->lock); + --dev->udc_usage; if (retval < 0) { clean_req (dev->gadget->ep0, dev->req); } else @@ -1243,9 +1251,21 @@ static long dev_ioctl (struct file *fd, unsigned code, unsigned long value) struct usb_gadget *gadget = dev->gadget; long ret = -ENOTTY; - if (gadget->ops->ioctl) + spin_lock_irq(&dev->lock); + if (dev->state == STATE_DEV_OPENED || + dev->state == STATE_DEV_UNBOUND) { + /* Not bound to a UDC */ + } else if (gadget->ops->ioctl) { + ++dev->udc_usage; + spin_unlock_irq(&dev->lock); + ret = gadget->ops->ioctl (gadget, code, value); + spin_lock_irq(&dev->lock); + --dev->udc_usage; + } + spin_unlock_irq(&dev->lock); + return ret; } @@ -1463,10 +1483,12 @@ delegate: if (value < 0) break; + ++dev->udc_usage; spin_unlock (&dev->lock); value = usb_ep_queue (gadget->ep0, dev->req, GFP_KERNEL); spin_lock (&dev->lock); + --dev->udc_usage; if (value < 0) { clean_req (gadget->ep0, dev->req); break; @@ -1490,8 +1512,12 @@ delegate: req->length = value; req->zero = value < w_length; + ++dev->udc_usage; spin_unlock (&dev->lock); value = usb_ep_queue (gadget->ep0, req, GFP_KERNEL); + spin_lock(&dev->lock); + --dev->udc_usage; + spin_unlock(&dev->lock); if (value < 0) { DBG (dev, "ep_queue --> %d\n", value); req->status = 0; @@ -1518,21 +1544,24 @@ static void destroy_ep_files (struct dev_data *dev) /* break link to FS */ ep = list_first_entry (&dev->epfiles, struct ep_data, epfiles); list_del_init (&ep->epfiles); + spin_unlock_irq (&dev->lock); + dentry = ep->dentry; ep->dentry = NULL; parent = d_inode(dentry->d_parent); /* break link to controller */ + mutex_lock(&ep->lock); if (ep->state == STATE_EP_ENABLED) (void) usb_ep_disable (ep->ep); ep->state = STATE_EP_UNBOUND; usb_ep_free_request (ep->ep, ep->req); ep->ep = NULL; + mutex_unlock(&ep->lock); + wake_up (&ep->wait); put_ep (ep); - spin_unlock_irq (&dev->lock); - /* break link to dcache */ inode_lock(parent); d_delete (dentry); @@ -1603,6 +1632,11 @@ gadgetfs_unbind (struct usb_gadget *gadget) spin_lock_irq (&dev->lock); dev->state = STATE_DEV_UNBOUND; + while (dev->udc_usage > 0) { + spin_unlock_irq(&dev->lock); + usleep_range(1000, 2000); + spin_lock_irq(&dev->lock); + } spin_unlock_irq (&dev->lock); destroy_ep_files (dev); diff --git a/drivers/usb/gadget/legacy/mass_storage.c b/drivers/usb/gadget/legacy/mass_storage.c index e99ab57ee3e5..fcba59782f26 100644 --- a/drivers/usb/gadget/legacy/mass_storage.c +++ b/drivers/usb/gadget/legacy/mass_storage.c @@ -107,15 +107,6 @@ static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; FSG_MODULE_PARAMETERS(/* no prefix */, mod_data); -static unsigned long msg_registered; -static void msg_cleanup(void); - -static int msg_thread_exits(struct fsg_common *common) -{ - msg_cleanup(); - return 0; -} - static int msg_do_config(struct usb_configuration *c) { struct fsg_opts *opts; @@ -154,9 +145,6 @@ static struct usb_configuration msg_config_driver = { static int msg_bind(struct usb_composite_dev *cdev) { - static const struct fsg_operations ops = { - .thread_exits = msg_thread_exits, - }; struct fsg_opts *opts; struct fsg_config config; int status; @@ -173,8 +161,6 @@ static int msg_bind(struct usb_composite_dev *cdev) if (status) goto fail; - fsg_common_set_ops(opts->common, &ops); - status = fsg_common_set_cdev(opts->common, cdev, config.can_stall); if (status) goto fail_set_cdev; @@ -256,18 +242,12 @@ MODULE_LICENSE("GPL"); static int __init msg_init(void) { - int ret; - - ret = usb_composite_probe(&msg_driver); - set_bit(0, &msg_registered); - - return ret; + return usb_composite_probe(&msg_driver); } module_init(msg_init); -static void msg_cleanup(void) +static void __exit msg_cleanup(void) { - if (test_and_clear_bit(0, &msg_registered)) - usb_composite_unregister(&msg_driver); + usb_composite_unregister(&msg_driver); } module_exit(msg_cleanup); diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig index 7cd5c969fcbe..1e9567091d86 100644 --- a/drivers/usb/gadget/udc/Kconfig +++ b/drivers/usb/gadget/udc/Kconfig @@ -273,6 +273,7 @@ config USB_SNP_CORE config USB_SNP_UDC_PLAT tristate "Synopsys USB 2.0 Device controller" depends on USB_GADGET && OF && HAS_DMA + depends on EXTCON || EXTCON=n select USB_GADGET_DUALSPEED select USB_SNP_CORE default ARCH_BCM_IPROC diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c index 98d71400f8a1..a884c022df7a 100644 --- a/drivers/usb/gadget/udc/atmel_usba_udc.c +++ b/drivers/usb/gadget/udc/atmel_usba_udc.c @@ -29,6 +29,8 @@ #include <linux/of_gpio.h> #include "atmel_usba_udc.h" +#define USBA_VBUS_IRQFLAGS (IRQF_ONESHOT \ + | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING) #ifdef CONFIG_USB_GADGET_DEBUG_FS #include <linux/debugfs.h> @@ -2361,7 +2363,7 @@ static int usba_udc_probe(struct platform_device *pdev) IRQ_NOAUTOEN); ret = devm_request_threaded_irq(&pdev->dev, gpio_to_irq(udc->vbus_pin), NULL, - usba_vbus_irq_thread, IRQF_ONESHOT, + usba_vbus_irq_thread, USBA_VBUS_IRQFLAGS, "atmel_usba_udc", udc); if (ret) { udc->vbus_pin = -ENODEV; diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c index 75c51ca4ee0f..d41d07aae0ce 100644 --- a/drivers/usb/gadget/udc/core.c +++ b/drivers/usb/gadget/udc/core.c @@ -1320,8 +1320,7 @@ static int udc_bind_to_driver(struct usb_udc *udc, struct usb_gadget_driver *dri udc->dev.driver = &driver->driver; udc->gadget->dev.driver = &driver->driver; - if (driver->max_speed < udc->gadget->max_speed) - usb_gadget_udc_set_speed(udc, driver->max_speed); + usb_gadget_udc_set_speed(udc, driver->max_speed); ret = driver->bind(udc->gadget, driver); if (ret) diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c index a030d7923d7d..f04e91ef9e7c 100644 --- a/drivers/usb/gadget/udc/dummy_hcd.c +++ b/drivers/usb/gadget/udc/dummy_hcd.c @@ -237,6 +237,8 @@ struct dummy_hcd { struct usb_device *udev; struct list_head urbp_list; + struct urbp *next_frame_urbp; + u32 stream_en_ep; u8 num_stream[30 / 2]; @@ -253,11 +255,13 @@ struct dummy { */ struct dummy_ep ep[DUMMY_ENDPOINTS]; int address; + int callback_usage; struct usb_gadget gadget; struct usb_gadget_driver *driver; struct dummy_request fifo_req; u8 fifo_buf[FIFO_SIZE]; u16 devstatus; + unsigned ints_enabled:1; unsigned udc_suspended:1; unsigned pullup:1; @@ -375,11 +379,10 @@ static void set_link_state_by_speed(struct dummy_hcd *dum_hcd) USB_PORT_STAT_CONNECTION) == 0) dum_hcd->port_status |= (USB_PORT_STAT_C_CONNECTION << 16); - if ((dum_hcd->port_status & - USB_PORT_STAT_ENABLE) == 1 && - (dum_hcd->port_status & - USB_SS_PORT_LS_U0) == 1 && - dum_hcd->rh_state != DUMMY_RH_SUSPENDED) + if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) && + (dum_hcd->port_status & + USB_PORT_STAT_LINK_STATE) == USB_SS_PORT_LS_U0 && + dum_hcd->rh_state != DUMMY_RH_SUSPENDED) dum_hcd->active = 1; } } else { @@ -416,6 +419,7 @@ static void set_link_state_by_speed(struct dummy_hcd *dum_hcd) static void set_link_state(struct dummy_hcd *dum_hcd) { struct dummy *dum = dum_hcd->dum; + unsigned int power_bit; dum_hcd->active = 0; if (dum->pullup) @@ -426,32 +430,43 @@ static void set_link_state(struct dummy_hcd *dum_hcd) return; set_link_state_by_speed(dum_hcd); + power_bit = (dummy_hcd_to_hcd(dum_hcd)->speed == HCD_USB3 ? + USB_SS_PORT_STAT_POWER : USB_PORT_STAT_POWER); if ((dum_hcd->port_status & USB_PORT_STAT_ENABLE) == 0 || dum_hcd->active) dum_hcd->resuming = 0; /* Currently !connected or in reset */ - if ((dum_hcd->port_status & USB_PORT_STAT_CONNECTION) == 0 || + if ((dum_hcd->port_status & power_bit) == 0 || (dum_hcd->port_status & USB_PORT_STAT_RESET) != 0) { - unsigned disconnect = USB_PORT_STAT_CONNECTION & + unsigned int disconnect = power_bit & dum_hcd->old_status & (~dum_hcd->port_status); - unsigned reset = USB_PORT_STAT_RESET & + unsigned int reset = USB_PORT_STAT_RESET & (~dum_hcd->old_status) & dum_hcd->port_status; /* Report reset and disconnect events to the driver */ - if (dum->driver && (disconnect || reset)) { + if (dum->ints_enabled && (disconnect || reset)) { stop_activity(dum); + ++dum->callback_usage; + spin_unlock(&dum->lock); if (reset) usb_gadget_udc_reset(&dum->gadget, dum->driver); else dum->driver->disconnect(&dum->gadget); + spin_lock(&dum->lock); + --dum->callback_usage; } - } else if (dum_hcd->active != dum_hcd->old_active) { + } else if (dum_hcd->active != dum_hcd->old_active && + dum->ints_enabled) { + ++dum->callback_usage; + spin_unlock(&dum->lock); if (dum_hcd->old_active && dum->driver->suspend) dum->driver->suspend(&dum->gadget); else if (!dum_hcd->old_active && dum->driver->resume) dum->driver->resume(&dum->gadget); + spin_lock(&dum->lock); + --dum->callback_usage; } dum_hcd->old_status = dum_hcd->port_status; @@ -972,8 +987,11 @@ static int dummy_udc_start(struct usb_gadget *g, * can't enumerate without help from the driver we're binding. */ + spin_lock_irq(&dum->lock); dum->devstatus = 0; dum->driver = driver; + dum->ints_enabled = 1; + spin_unlock_irq(&dum->lock); return 0; } @@ -984,6 +1002,16 @@ static int dummy_udc_stop(struct usb_gadget *g) struct dummy *dum = dum_hcd->dum; spin_lock_irq(&dum->lock); + dum->ints_enabled = 0; + stop_activity(dum); + + /* emulate synchronize_irq(): wait for callbacks to finish */ + while (dum->callback_usage > 0) { + spin_unlock_irq(&dum->lock); + usleep_range(1000, 2000); + spin_lock_irq(&dum->lock); + } + dum->driver = NULL; spin_unlock_irq(&dum->lock); @@ -1037,7 +1065,12 @@ static int dummy_udc_probe(struct platform_device *pdev) memzero_explicit(&dum->gadget, sizeof(struct usb_gadget)); dum->gadget.name = gadget_name; dum->gadget.ops = &dummy_ops; - dum->gadget.max_speed = USB_SPEED_SUPER; + if (mod_data.is_super_speed) + dum->gadget.max_speed = USB_SPEED_SUPER; + else if (mod_data.is_high_speed) + dum->gadget.max_speed = USB_SPEED_HIGH; + else + dum->gadget.max_speed = USB_SPEED_FULL; dum->gadget.dev.parent = &pdev->dev; init_dummy_udc_hw(dum); @@ -1246,6 +1279,8 @@ static int dummy_urb_enqueue( list_add_tail(&urbp->urbp_list, &dum_hcd->urbp_list); urb->hcpriv = urbp; + if (!dum_hcd->next_frame_urbp) + dum_hcd->next_frame_urbp = urbp; if (usb_pipetype(urb->pipe) == PIPE_CONTROL) urb->error_count = 1; /* mark as a new urb */ @@ -1521,6 +1556,8 @@ static struct dummy_ep *find_endpoint(struct dummy *dum, u8 address) if (!is_active((dum->gadget.speed == USB_SPEED_SUPER ? dum->ss_hcd : dum->hs_hcd))) return NULL; + if (!dum->ints_enabled) + return NULL; if ((address & ~USB_DIR_IN) == 0) return &dum->ep[0]; for (i = 1; i < DUMMY_ENDPOINTS; i++) { @@ -1762,6 +1799,7 @@ static void dummy_timer(unsigned long _dum_hcd) spin_unlock_irqrestore(&dum->lock, flags); return; } + dum_hcd->next_frame_urbp = NULL; for (i = 0; i < DUMMY_ENDPOINTS; i++) { if (!ep_info[i].name) @@ -1778,6 +1816,10 @@ restart: int type; int status = -EINPROGRESS; + /* stop when we reach URBs queued after the timer interrupt */ + if (urbp == dum_hcd->next_frame_urbp) + break; + urb = urbp->urb; if (urb->unlinked) goto return_urb; @@ -1857,10 +1899,12 @@ restart: * until setup() returns; no reentrancy issues etc. */ if (value > 0) { + ++dum->callback_usage; spin_unlock(&dum->lock); value = dum->driver->setup(&dum->gadget, &setup); spin_lock(&dum->lock); + --dum->callback_usage; if (value >= 0) { /* no delays (max 64KB data stage) */ @@ -2561,8 +2605,6 @@ static struct hc_driver dummy_hcd = { .product_desc = "Dummy host controller", .hcd_priv_size = sizeof(struct dummy_hcd), - .flags = HCD_USB3 | HCD_SHARED, - .reset = dummy_setup, .start = dummy_start, .stop = dummy_stop, @@ -2591,8 +2633,12 @@ static int dummy_hcd_probe(struct platform_device *pdev) dev_info(&pdev->dev, "%s, driver " DRIVER_VERSION "\n", driver_desc); dum = *((void **)dev_get_platdata(&pdev->dev)); - if (!mod_data.is_super_speed) + if (mod_data.is_super_speed) + dummy_hcd.flags = HCD_USB3 | HCD_SHARED; + else if (mod_data.is_high_speed) dummy_hcd.flags = HCD_USB2; + else + dummy_hcd.flags = HCD_USB11; hs_hcd = usb_create_hcd(&dummy_hcd, &pdev->dev, dev_name(&pdev->dev)); if (!hs_hcd) return -ENOMEM; diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c index df37c1e6e9d5..63a206122058 100644 --- a/drivers/usb/gadget/udc/renesas_usb3.c +++ b/drivers/usb/gadget/udc/renesas_usb3.c @@ -1038,7 +1038,7 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep, usb3_ep->ep.maxpacket); u8 *buf = usb3_req->req.buf + usb3_req->req.actual; u32 tmp = 0; - bool is_last; + bool is_last = !len ? true : false; if (usb3_wait_pipe_status(usb3_ep, PX_STA_BUFSTS) < 0) return -EBUSY; @@ -1059,7 +1059,8 @@ static int usb3_write_pipe(struct renesas_usb3_ep *usb3_ep, usb3_write(usb3, tmp, fifo_reg); } - is_last = usb3_is_transfer_complete(usb3_ep, usb3_req); + if (!is_last) + is_last = usb3_is_transfer_complete(usb3_ep, usb3_req); /* Send the data */ usb3_set_px_con_send(usb3_ep, len, is_last); @@ -1150,7 +1151,8 @@ static void usb3_start_pipe0(struct renesas_usb3_ep *usb3_ep, usb3_set_p0_con_for_ctrl_read_data(usb3); } else { usb3_clear_bit(usb3, P0_MOD_DIR, USB3_P0_MOD); - usb3_set_p0_con_for_ctrl_write_data(usb3); + if (usb3_req->req.length) + usb3_set_p0_con_for_ctrl_write_data(usb3); } usb3_p0_xfer(usb3_ep, usb3_req); @@ -2053,7 +2055,16 @@ static u32 usb3_calc_ramarea(int ram_size) static u32 usb3_calc_rammap_val(struct renesas_usb3_ep *usb3_ep, const struct usb_endpoint_descriptor *desc) { - return usb3_ep->rammap_val | PN_RAMMAP_MPKT(usb_endpoint_maxp(desc)); + int i; + const u32 max_packet_array[] = {8, 16, 32, 64, 512}; + u32 mpkt = PN_RAMMAP_MPKT(1024); + + for (i = 0; i < ARRAY_SIZE(max_packet_array); i++) { + if (usb_endpoint_maxp(desc) <= max_packet_array[i]) + mpkt = PN_RAMMAP_MPKT(max_packet_array[i]); + } + + return usb3_ep->rammap_val | mpkt; } static int usb3_enable_pipe_n(struct renesas_usb3_ep *usb3_ep, diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 658d9d1f9ea3..6dda3623a276 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -447,7 +447,7 @@ static int usb_asmedia_wait_write(struct pci_dev *pdev) if ((value & ASMT_CONTROL_WRITE_BIT) == 0) return 0; - usleep_range(40, 60); + udelay(50); } dev_warn(&pdev->dev, "%s: check_write_ready timeout", __func__); @@ -1022,7 +1022,7 @@ EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); * * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS. * It signals to the BIOS that the OS wants control of the host controller, - * and then waits 5 seconds for the BIOS to hand over control. + * and then waits 1 second for the BIOS to hand over control. * If we timeout, assume the BIOS is broken and take control anyway. */ static void quirk_usb_handoff_xhci(struct pci_dev *pdev) @@ -1069,9 +1069,9 @@ static void quirk_usb_handoff_xhci(struct pci_dev *pdev) if (val & XHCI_HC_BIOS_OWNED) { writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset); - /* Wait for 5 seconds with 10 microsecond polling interval */ + /* Wait for 1 second with 10 microsecond polling interval */ timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, - 0, 5000, 10); + 0, 1000000, 10); /* Assume a buggy BIOS and take HC ownership anyway */ if (timeout) { @@ -1100,7 +1100,7 @@ hc_init: * operational or runtime registers. Wait 5 seconds and no more. */ timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_CNR, 0, - 5000, 10); + 5000000, 10); /* Assume a buggy HC and start HC initialization anyway */ if (timeout) { val = readl(op_reg_base + XHCI_STS_OFFSET); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index ad89a6d4111b..a2336deb5e36 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -112,7 +112,7 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf, /* If PSI table exists, add the custom speed attributes from it */ if (usb3_1 && xhci->usb3_rhub.psi_count) { - u32 ssp_cap_base, bm_attrib, psi; + u32 ssp_cap_base, bm_attrib, psi, psi_mant, psi_exp; int offset; ssp_cap_base = USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE; @@ -139,6 +139,15 @@ static int xhci_create_usb3_bos_desc(struct xhci_hcd *xhci, char *buf, for (i = 0; i < xhci->usb3_rhub.psi_count; i++) { psi = xhci->usb3_rhub.psi[i]; psi &= ~USB_SSP_SUBLINK_SPEED_RSVD; + psi_exp = XHCI_EXT_PORT_PSIE(psi); + psi_mant = XHCI_EXT_PORT_PSIM(psi); + + /* Shift to Gbps and set SSP Link BIT(14) if 10Gpbs */ + for (; psi_exp < 3; psi_exp++) + psi_mant /= 1000; + if (psi_mant >= 10) + psi |= BIT(14); + if ((psi & PLT_MASK) == PLT_SYM) { /* Symmetric, create SSA RX and TX from one PSI entry */ put_unaligned_le32(psi, &buf[offset]); @@ -411,14 +420,25 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) GFP_NOWAIT); if (!command) { spin_unlock_irqrestore(&xhci->lock, flags); - xhci_free_command(xhci, cmd); - return -ENOMEM; + ret = -ENOMEM; + goto cmd_cleanup; + } + + ret = xhci_queue_stop_endpoint(xhci, command, slot_id, + i, suspend); + if (ret) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_free_command(xhci, command); + goto cmd_cleanup; } - xhci_queue_stop_endpoint(xhci, command, slot_id, i, - suspend); } } - xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); + ret = xhci_queue_stop_endpoint(xhci, cmd, slot_id, 0, suspend); + if (ret) { + spin_unlock_irqrestore(&xhci->lock, flags); + goto cmd_cleanup; + } + xhci_ring_cmd_db(xhci); spin_unlock_irqrestore(&xhci->lock, flags); @@ -430,6 +450,8 @@ static int xhci_stop_device(struct xhci_hcd *xhci, int slot_id, int suspend) xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n"); ret = -ETIME; } + +cmd_cleanup: xhci_free_command(xhci, cmd); return ret; } @@ -1506,9 +1528,6 @@ int xhci_bus_suspend(struct usb_hcd *hcd) t2 |= PORT_WKOC_E | PORT_WKCONN_E; t2 &= ~PORT_WKDISC_E; } - if ((xhci->quirks & XHCI_U2_DISABLE_WAKE) && - (hcd->speed < HCD_USB3)) - t2 &= ~PORT_WAKE_BITS; } else t2 &= ~PORT_WAKE_BITS; diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 8071c8fdd15e..76f392954733 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -54,11 +54,6 @@ #define PCI_DEVICE_ID_INTEL_APL_XHCI 0x5aa8 #define PCI_DEVICE_ID_INTEL_DNV_XHCI 0x19d0 -#define PCI_DEVICE_ID_AMD_PROMONTORYA_4 0x43b9 -#define PCI_DEVICE_ID_AMD_PROMONTORYA_3 0x43ba -#define PCI_DEVICE_ID_AMD_PROMONTORYA_2 0x43bb -#define PCI_DEVICE_ID_AMD_PROMONTORYA_1 0x43bc - #define PCI_DEVICE_ID_ASMEDIA_1042A_XHCI 0x1142 static const char hcd_name[] = "xhci_hcd"; @@ -142,13 +137,6 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) if (pdev->vendor == PCI_VENDOR_ID_AMD) xhci->quirks |= XHCI_TRUST_TX_LENGTH; - if ((pdev->vendor == PCI_VENDOR_ID_AMD) && - ((pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_4) || - (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_3) || - (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_2) || - (pdev->device == PCI_DEVICE_ID_AMD_PROMONTORYA_1))) - xhci->quirks |= XHCI_U2_DISABLE_WAKE; - if (pdev->vendor == PCI_VENDOR_ID_INTEL) { xhci->quirks |= XHCI_LPM_SUPPORT; xhci->quirks |= XHCI_INTEL_HOST; diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 163bafde709f..1cb6eaef4ae1 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -178,14 +178,18 @@ static int xhci_plat_probe(struct platform_device *pdev) * 2. xhci_plat is child of a device from firmware (dwc3-plat) * 3. xhci_plat is grandchild of a pci device (dwc3-pci) */ - sysdev = &pdev->dev; - if (sysdev->parent && !sysdev->of_node && sysdev->parent->of_node) - sysdev = sysdev->parent; + for (sysdev = &pdev->dev; sysdev; sysdev = sysdev->parent) { + if (is_of_node(sysdev->fwnode) || + is_acpi_device_node(sysdev->fwnode)) + break; #ifdef CONFIG_PCI - else if (sysdev->parent && sysdev->parent->parent && - sysdev->parent->parent->bus == &pci_bus_type) - sysdev = sysdev->parent->parent; + else if (sysdev->bus == &pci_bus_type) + break; #endif + } + + if (!sysdev) + sysdev = &pdev->dev; /* Try to set 64-bit DMA first */ if (WARN_ON(!sysdev->dma_mask)) diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a9443651ce0f..82c746e2d85c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1309,6 +1309,7 @@ static void xhci_complete_del_and_free_cmd(struct xhci_command *cmd, u32 status) void xhci_cleanup_command_queue(struct xhci_hcd *xhci) { struct xhci_command *cur_cmd, *tmp_cmd; + xhci->current_cmd = NULL; list_for_each_entry_safe(cur_cmd, tmp_cmd, &xhci->cmd_list, cmd_list) xhci_complete_del_and_free_cmd(cur_cmd, COMP_COMMAND_ABORTED); } @@ -2579,15 +2580,21 @@ static int handle_tx_event(struct xhci_hcd *xhci, (struct xhci_generic_trb *) ep_trb); /* - * No-op TRB should not trigger interrupts. - * If ep_trb is a no-op TRB, it means the - * corresponding TD has been cancelled. Just ignore - * the TD. + * No-op TRB could trigger interrupts in a case where + * a URB was killed and a STALL_ERROR happens right + * after the endpoint ring stopped. Reset the halted + * endpoint. Otherwise, the endpoint remains stalled + * indefinitely. */ if (trb_is_noop(ep_trb)) { - xhci_dbg(xhci, - "ep_trb is a no-op TRB. Skip it for slot %u ep %u\n", - slot_id, ep_index); + if (trb_comp_code == COMP_STALL_ERROR || + xhci_requires_manual_halt_cleanup(xhci, ep_ctx, + trb_comp_code)) + xhci_cleanup_halted_endpoint(xhci, slot_id, + ep_index, + ep_ring->stream_id, + td, ep_trb, + EP_HARD_RESET); goto cleanup; } diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b2ff1ff1a02f..51535ba2bcd4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1703,7 +1703,8 @@ static int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, if (xhci->quirks & XHCI_MTK_HOST) { ret = xhci_mtk_add_ep_quirk(hcd, udev, ep); if (ret < 0) { - xhci_free_endpoint_ring(xhci, virt_dev, ep_index); + xhci_ring_free(xhci, virt_dev->eps[ep_index].new_ring); + virt_dev->eps[ep_index].new_ring = NULL; return ret; } } @@ -4804,7 +4805,8 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks) */ hcd->has_tt = 1; } else { - if (xhci->sbrn == 0x31) { + /* Some 3.1 hosts return sbrn 0x30, can't rely on sbrn alone */ + if (xhci->sbrn == 0x31 || xhci->usb3_rhub.min_rev >= 1) { xhci_info(xhci, "Host supports USB 3.1 Enhanced SuperSpeed\n"); hcd->speed = HCD_USB31; hcd->self.root_hub->speed = USB_SPEED_SUPER_PLUS; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 2abaa4d6d39d..2b48aa4f6b76 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -735,6 +735,8 @@ struct xhci_ep_ctx { #define EP_MAXPSTREAMS(p) (((p) << 10) & EP_MAXPSTREAMS_MASK) /* Endpoint is set up with a Linear Stream Array (vs. Secondary Stream Array) */ #define EP_HAS_LSA (1 << 15) +/* hosts with LEC=1 use bits 31:24 as ESIT high bits. */ +#define CTX_TO_MAX_ESIT_PAYLOAD_HI(p) (((p) >> 24) & 0xff) /* ep_info2 bitmasks */ /* @@ -1681,7 +1683,7 @@ struct xhci_bus_state { static inline unsigned int hcd_index(struct usb_hcd *hcd) { - if (hcd->speed == HCD_USB3) + if (hcd->speed >= HCD_USB3) return 0; else return 1; @@ -1826,7 +1828,7 @@ struct xhci_hcd { /* For controller with a broken Port Disable implementation */ #define XHCI_BROKEN_PORT_PED (1 << 25) #define XHCI_LIMIT_ENDPOINT_INTERVAL_7 (1 << 26) -#define XHCI_U2_DISABLE_WAKE (1 << 27) +/* Reserved. It was XHCI_U2_DISABLE_WAKE */ #define XHCI_ASMEDIA_MODIFY_FLOWCONTROL (1 << 28) unsigned int num_active_eps; @@ -2540,8 +2542,8 @@ static inline const char *xhci_decode_ep_context(u32 info, u32 info2, u64 deq, u8 lsa; u8 hid; - esit = EP_MAX_ESIT_PAYLOAD_HI(info) << 16 | - EP_MAX_ESIT_PAYLOAD_LO(tx_info); + esit = CTX_TO_MAX_ESIT_PAYLOAD_HI(info) << 16 | + CTX_TO_MAX_ESIT_PAYLOAD(tx_info); ep_state = info & EP_STATE_MASK; max_pstr = info & EP_MAXPSTREAMS_MASK; diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index eee82ca55b7b..b3fc602b2e24 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -202,12 +202,13 @@ found: return tmp; } - if (in) { + if (in) dev->in_pipe = usb_rcvbulkpipe(udev, in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + if (out) dev->out_pipe = usb_sndbulkpipe(udev, out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - } + if (iso_in) { dev->iso_in = &iso_in->desc; dev->in_iso_pipe = usb_rcvisocpipe(udev, @@ -1964,6 +1965,9 @@ test_queue(struct usbtest_dev *dev, struct usbtest_param_32 *param, int status = 0; struct urb *urbs[param->sglen]; + if (!param->sglen || param->iterations > UINT_MAX / param->sglen) + return -EINVAL; + memset(&context, 0, sizeof(context)); context.count = param->iterations * param->sglen; context.dev = dev; @@ -2087,6 +2091,8 @@ usbtest_do_ioctl(struct usb_interface *intf, struct usbtest_param_32 *param) if (param->iterations <= 0) return -EINVAL; + if (param->sglen > MAX_SGLEN) + return -EINVAL; /* * Just a bunch of test cases that every HCD is expected to handle. * diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 029692053dd3..ff5a1a8989d5 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -906,7 +906,7 @@ b_host: */ if (int_usb & MUSB_INTR_RESET) { handled = IRQ_HANDLED; - if (devctl & MUSB_DEVCTL_HM) { + if (is_host_active(musb)) { /* * When BABBLE happens what we can depends on which * platform MUSB is running, because some platforms @@ -916,9 +916,7 @@ b_host: * drop the session. */ dev_err(musb->controller, "Babble\n"); - - if (is_host_active(musb)) - musb_recover_from_babble(musb); + musb_recover_from_babble(musb); } else { musb_dbg(musb, "BUS RESET as %s", usb_otg_state_string(musb->xceiv->otg->state)); @@ -1861,22 +1859,22 @@ static void musb_pm_runtime_check_session(struct musb *musb) MUSB_DEVCTL_HR; switch (devctl & ~s) { case MUSB_QUIRK_B_INVALID_VBUS_91: - if (musb->quirk_retries--) { + if (musb->quirk_retries && !musb->flush_irq_work) { musb_dbg(musb, "Poll devctl on invalid vbus, assume no session"); schedule_delayed_work(&musb->irq_work, msecs_to_jiffies(1000)); - + musb->quirk_retries--; return; } /* fall through */ case MUSB_QUIRK_A_DISCONNECT_19: - if (musb->quirk_retries--) { + if (musb->quirk_retries && !musb->flush_irq_work) { musb_dbg(musb, "Poll devctl on possible host mode disconnect"); schedule_delayed_work(&musb->irq_work, msecs_to_jiffies(1000)); - + musb->quirk_retries--; return; } if (!musb->session) @@ -2681,8 +2679,15 @@ static int musb_suspend(struct device *dev) musb_platform_disable(musb); musb_disable_interrupts(musb); + + musb->flush_irq_work = true; + while (flush_delayed_work(&musb->irq_work)) + ; + musb->flush_irq_work = false; + if (!(musb->io.quirks & MUSB_PRESERVE_SESSION)) musb_writeb(musb->mregs, MUSB_DEVCTL, 0); + WARN_ON(!list_empty(&musb->pending_list)); spin_lock_irqsave(&musb->lock, flags); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index c748f4ac1154..20f4614178d9 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -428,6 +428,8 @@ struct musb { unsigned test_mode:1; unsigned softconnect:1; + unsigned flush_irq_work:1; + u8 address; u8 test_mode_nr; u16 ackpend; /* ep0 */ diff --git a/drivers/usb/musb/musb_cppi41.c b/drivers/usb/musb/musb_cppi41.c index ba255280a624..1ec0a4947b6b 100644 --- a/drivers/usb/musb/musb_cppi41.c +++ b/drivers/usb/musb/musb_cppi41.c @@ -26,15 +26,28 @@ #define MUSB_DMA_NUM_CHANNELS 15 +#define DA8XX_USB_MODE 0x10 +#define DA8XX_USB_AUTOREQ 0x14 +#define DA8XX_USB_TEARDOWN 0x1c + +#define DA8XX_DMA_NUM_CHANNELS 4 + struct cppi41_dma_controller { struct dma_controller controller; - struct cppi41_dma_channel rx_channel[MUSB_DMA_NUM_CHANNELS]; - struct cppi41_dma_channel tx_channel[MUSB_DMA_NUM_CHANNELS]; + struct cppi41_dma_channel *rx_channel; + struct cppi41_dma_channel *tx_channel; struct hrtimer early_tx; struct list_head early_tx_list; u32 rx_mode; u32 tx_mode; u32 auto_req; + + u32 tdown_reg; + u32 autoreq_reg; + + void (*set_dma_mode)(struct cppi41_dma_channel *cppi41_channel, + unsigned int mode); + u8 num_channels; }; static void save_rx_toggle(struct cppi41_dma_channel *cppi41_channel) @@ -349,6 +362,32 @@ static void cppi41_set_dma_mode(struct cppi41_dma_channel *cppi41_channel, } } +static void da8xx_set_dma_mode(struct cppi41_dma_channel *cppi41_channel, + unsigned int mode) +{ + struct cppi41_dma_controller *controller = cppi41_channel->controller; + struct musb *musb = controller->controller.musb; + unsigned int shift; + u32 port; + u32 new_mode; + u32 old_mode; + + old_mode = controller->tx_mode; + port = cppi41_channel->port_num; + + shift = (port - 1) * 4; + if (!cppi41_channel->is_tx) + shift += 16; + new_mode = old_mode & ~(3 << shift); + new_mode |= mode << shift; + + if (new_mode == old_mode) + return; + controller->tx_mode = new_mode; + musb_writel(musb->ctrl_base, DA8XX_USB_MODE, new_mode); +} + + static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel, unsigned mode) { @@ -364,8 +403,8 @@ static void cppi41_set_autoreq_mode(struct cppi41_dma_channel *cppi41_channel, if (new_mode == old_mode) return; controller->auto_req = new_mode; - musb_writel(controller->controller.musb->ctrl_base, USB_CTRL_AUTOREQ, - new_mode); + musb_writel(controller->controller.musb->ctrl_base, + controller->autoreq_reg, new_mode); } static bool cppi41_configure_channel(struct dma_channel *channel, @@ -373,6 +412,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel, dma_addr_t dma_addr, u32 len) { struct cppi41_dma_channel *cppi41_channel = channel->private_data; + struct cppi41_dma_controller *controller = cppi41_channel->controller; struct dma_chan *dc = cppi41_channel->dc; struct dma_async_tx_descriptor *dma_desc; enum dma_transfer_direction direction; @@ -398,7 +438,7 @@ static bool cppi41_configure_channel(struct dma_channel *channel, musb_writel(musb->ctrl_base, RNDIS_REG(cppi41_channel->port_num), len); /* gen rndis */ - cppi41_set_dma_mode(cppi41_channel, + controller->set_dma_mode(cppi41_channel, EP_MODE_DMA_GEN_RNDIS); /* auto req */ @@ -407,14 +447,15 @@ static bool cppi41_configure_channel(struct dma_channel *channel, } else { musb_writel(musb->ctrl_base, RNDIS_REG(cppi41_channel->port_num), 0); - cppi41_set_dma_mode(cppi41_channel, + controller->set_dma_mode(cppi41_channel, EP_MODE_DMA_TRANSPARENT); cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE); } } else { /* fallback mode */ - cppi41_set_dma_mode(cppi41_channel, EP_MODE_DMA_TRANSPARENT); + controller->set_dma_mode(cppi41_channel, + EP_MODE_DMA_TRANSPARENT); cppi41_set_autoreq_mode(cppi41_channel, EP_MODE_AUTOREQ_NONE); len = min_t(u32, packet_sz, len); } @@ -445,7 +486,7 @@ static struct dma_channel *cppi41_dma_channel_allocate(struct dma_controller *c, struct cppi41_dma_channel *cppi41_channel = NULL; u8 ch_num = hw_ep->epnum - 1; - if (ch_num >= MUSB_DMA_NUM_CHANNELS) + if (ch_num >= controller->num_channels) return NULL; if (is_tx) @@ -581,12 +622,13 @@ static int cppi41_dma_channel_abort(struct dma_channel *channel) do { if (is_tx) - musb_writel(musb->ctrl_base, USB_TDOWN, tdbit); + musb_writel(musb->ctrl_base, controller->tdown_reg, + tdbit); ret = dmaengine_terminate_all(cppi41_channel->dc); } while (ret == -EAGAIN); if (is_tx) { - musb_writel(musb->ctrl_base, USB_TDOWN, tdbit); + musb_writel(musb->ctrl_base, controller->tdown_reg, tdbit); csr = musb_readw(epio, MUSB_TXCSR); if (csr & MUSB_TXCSR_TXPKTRDY) { @@ -604,7 +646,7 @@ static void cppi41_release_all_dma_chans(struct cppi41_dma_controller *ctrl) struct dma_chan *dc; int i; - for (i = 0; i < MUSB_DMA_NUM_CHANNELS; i++) { + for (i = 0; i < ctrl->num_channels; i++) { dc = ctrl->tx_channel[i].dc; if (dc) dma_release_channel(dc); @@ -656,7 +698,7 @@ static int cppi41_dma_controller_start(struct cppi41_dma_controller *controller) goto err; ret = -EINVAL; - if (port > MUSB_DMA_NUM_CHANNELS || !port) + if (port > controller->num_channels || !port) goto err; if (is_tx) cppi41_channel = &controller->tx_channel[port - 1]; @@ -697,6 +739,8 @@ void cppi41_dma_controller_destroy(struct dma_controller *c) hrtimer_cancel(&controller->early_tx); cppi41_dma_controller_stop(controller); + kfree(controller->rx_channel); + kfree(controller->tx_channel); kfree(controller); } EXPORT_SYMBOL_GPL(cppi41_dma_controller_destroy); @@ -705,6 +749,7 @@ struct dma_controller * cppi41_dma_controller_create(struct musb *musb, void __iomem *base) { struct cppi41_dma_controller *controller; + int channel_size; int ret = 0; if (!musb->controller->parent->of_node) { @@ -727,12 +772,37 @@ cppi41_dma_controller_create(struct musb *musb, void __iomem *base) controller->controller.is_compatible = cppi41_is_compatible; controller->controller.musb = musb; + if (musb->io.quirks & MUSB_DA8XX) { + controller->tdown_reg = DA8XX_USB_TEARDOWN; + controller->autoreq_reg = DA8XX_USB_AUTOREQ; + controller->set_dma_mode = da8xx_set_dma_mode; + controller->num_channels = DA8XX_DMA_NUM_CHANNELS; + } else { + controller->tdown_reg = USB_TDOWN; + controller->autoreq_reg = USB_CTRL_AUTOREQ; + controller->set_dma_mode = cppi41_set_dma_mode; + controller->num_channels = MUSB_DMA_NUM_CHANNELS; + } + + channel_size = controller->num_channels * + sizeof(struct cppi41_dma_channel); + controller->rx_channel = kzalloc(channel_size, GFP_KERNEL); + if (!controller->rx_channel) + goto rx_channel_alloc_fail; + controller->tx_channel = kzalloc(channel_size, GFP_KERNEL); + if (!controller->tx_channel) + goto tx_channel_alloc_fail; + ret = cppi41_dma_controller_start(controller); if (ret) goto plat_get_fail; return &controller->controller; plat_get_fail: + kfree(controller->tx_channel); +tx_channel_alloc_fail: + kfree(controller->rx_channel); +rx_channel_alloc_fail: kfree(controller); kzalloc_fail: if (ret == -EPROBE_DEFER) diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c index c9a09b5bb6e5..dc353e24d53c 100644 --- a/drivers/usb/musb/sunxi.c +++ b/drivers/usb/musb/sunxi.c @@ -297,6 +297,8 @@ static int sunxi_musb_exit(struct musb *musb) if (test_bit(SUNXI_MUSB_FL_HAS_SRAM, &glue->flags)) sunxi_sram_release(musb->controller->parent); + devm_usb_put_phy(glue->dev, glue->xceiv); + return 0; } diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c index 5fe4a5704bde..ccc2bf5274b4 100644 --- a/drivers/usb/phy/phy-tegra-usb.c +++ b/drivers/usb/phy/phy-tegra-usb.c @@ -329,6 +329,14 @@ static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) unsigned long val; void __iomem *base = phy->regs; + /* + * The USB driver may have already initiated the phy clock + * disable so wait to see if the clock turns off and if not + * then proceed with gating the clock. + */ + if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) == 0) + return; + if (phy->is_legacy_phy) { val = readl(base + USB_SUSP_CTRL); val |= USB_SUSP_SET; @@ -351,6 +359,15 @@ static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) unsigned long val; void __iomem *base = phy->regs; + /* + * The USB driver may have already initiated the phy clock + * enable so wait to see if the clock turns on and if not + * then proceed with ungating the clock. + */ + if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, + USB_PHY_CLK_VALID) == 0) + return; + if (phy->is_legacy_phy) { val = readl(base + USB_SUSP_CTRL); val |= USB_SUSP_CLR; diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index d1af831f43eb..50285b01da92 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -282,11 +282,26 @@ static void usbhsf_fifo_clear(struct usbhs_pipe *pipe, struct usbhs_fifo *fifo) { struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); + int ret = 0; - if (!usbhs_pipe_is_dcp(pipe)) - usbhsf_fifo_barrier(priv, fifo); + if (!usbhs_pipe_is_dcp(pipe)) { + /* + * This driver checks the pipe condition first to avoid -EBUSY + * from usbhsf_fifo_barrier() with about 10 msec delay in + * the interrupt handler if the pipe is RX direction and empty. + */ + if (usbhs_pipe_is_dir_in(pipe)) + ret = usbhs_pipe_is_accessible(pipe); + if (!ret) + ret = usbhsf_fifo_barrier(priv, fifo); + } - usbhs_write(priv, fifo->ctr, BCLR); + /* + * if non-DCP pipe, this driver should set BCLR when + * usbhsf_fifo_barrier() returns 0. + */ + if (!ret) + usbhs_write(priv, fifo->ctr, BCLR); } static int usbhsf_fifo_rcv_len(struct usbhs_priv *priv, @@ -842,9 +857,9 @@ static void xfer_work(struct work_struct *work) fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero); usbhs_pipe_running(pipe, 1); - usbhsf_dma_start(pipe, fifo); usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans); dma_async_issue_pending(chan); + usbhsf_dma_start(pipe, fifo); usbhs_pipe_enable(pipe); xfer_work_end: diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index fdf89800ebc3..43a862a90a77 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -186,6 +186,7 @@ static int usb_console_setup(struct console *co, char *options) tty_kref_put(tty); reset_open_count: port->port.count = 0; + info->port = NULL; usb_autopm_put_interface(serial->interface); error_get_interface: usb_serial_put(serial); @@ -265,7 +266,7 @@ static struct console usbcons = { void usb_serial_console_disconnect(struct usb_serial *serial) { - if (serial->port[0] == usbcons_info.port) { + if (serial->port[0] && serial->port[0] == usbcons_info.port) { usb_serial_console_exit(); usb_serial_put(serial); } diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2d945c9f975c..412f812522ee 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -177,6 +177,7 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1843, 0x0200) }, /* Vaisala USB Instrument Cable */ { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ { USB_DEVICE(0x18EF, 0xE025) }, /* ELV Marble Sound Board 1 */ + { USB_DEVICE(0x18EF, 0xE032) }, /* ELV TFD500 Data Logger */ { USB_DEVICE(0x1901, 0x0190) }, /* GE B850 CP2105 Recorder interface */ { USB_DEVICE(0x1901, 0x0193) }, /* GE B650 CP2104 PMC interface */ { USB_DEVICE(0x1901, 0x0194) }, /* GE Healthcare Remote Alarm Box */ @@ -352,6 +353,7 @@ static struct usb_serial_driver * const serial_drivers[] = { #define CP210X_PARTNUM_CP2104 0x04 #define CP210X_PARTNUM_CP2105 0x05 #define CP210X_PARTNUM_CP2108 0x08 +#define CP210X_PARTNUM_UNKNOWN 0xFF /* CP210X_GET_COMM_STATUS returns these 0x13 bytes */ struct cp210x_comm_status { @@ -1491,8 +1493,11 @@ static int cp210x_attach(struct usb_serial *serial) result = cp210x_read_vendor_block(serial, REQTYPE_DEVICE_TO_HOST, CP210X_GET_PARTNUM, &priv->partnum, sizeof(priv->partnum)); - if (result < 0) - goto err_free_priv; + if (result < 0) { + dev_warn(&serial->interface->dev, + "querying part number failed\n"); + priv->partnum = CP210X_PARTNUM_UNKNOWN; + } usb_set_serial_data(serial, priv); @@ -1505,10 +1510,6 @@ static int cp210x_attach(struct usb_serial *serial) } return 0; -err_free_priv: - kfree(priv); - - return result; } static void cp210x_disconnect(struct usb_serial *serial) diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 1cec03799cdf..49d1b2d4606d 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1015,6 +1015,8 @@ static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(WICED_VID, WICED_USB20706V2_PID) }, { USB_DEVICE(TI_VID, TI_CC3200_LAUNCHPAD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, + { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_BT_USB_PID) }, + { USB_DEVICE(CYPRESS_VID, CYPRESS_WICED_WL_USB_PID) }, { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 4fcf1cecb6d7..f9d15bd62785 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -610,6 +610,13 @@ #define ADI_GNICEPLUS_PID 0xF001 /* + * Cypress WICED USB UART + */ +#define CYPRESS_VID 0x04B4 +#define CYPRESS_WICED_BT_USB_PID 0x009B +#define CYPRESS_WICED_WL_USB_PID 0xF900 + +/* * Microchip Technology, Inc. * * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index cc84da8dbb84..14511d6a7d44 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -45,6 +45,7 @@ struct metrousb_private { static const struct usb_device_id id_table[] = { { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_BI) }, { USB_DEVICE(FOCUS_VENDOR_ID, FOCUS_PRODUCT_ID_UNI) }, + { USB_DEVICE_INTERFACE_CLASS(0x0c2e, 0x0730, 0xff) }, /* MS7820 */ { }, /* Terminating entry. */ }; MODULE_DEVICE_TABLE(usb, id_table); diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 54bfef13966a..ba672cf4e888 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -522,6 +522,7 @@ static void option_instat_callback(struct urb *urb); /* TP-LINK Incorporated products */ #define TPLINK_VENDOR_ID 0x2357 +#define TPLINK_PRODUCT_LTE 0x000D #define TPLINK_PRODUCT_MA180 0x0201 /* Changhong products */ @@ -2011,6 +2012,7 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600A) }, { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T_600E) }, + { USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, TPLINK_PRODUCT_LTE, 0xff, 0x00, 0x00) }, /* TP-Link LTE Module */ { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, { USB_DEVICE(TPLINK_VENDOR_ID, 0x9000), /* TP-Link MA260 */ diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index ebc0beea69d6..eb9928963a53 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -174,6 +174,10 @@ static const struct usb_device_id id_table[] = { {DEVICE_SWI(0x413c, 0x81b3)}, /* Dell Wireless 5809e Gobi(TM) 4G LTE Mobile Broadband Card (rev3) */ {DEVICE_SWI(0x413c, 0x81b5)}, /* Dell Wireless 5811e QDL */ {DEVICE_SWI(0x413c, 0x81b6)}, /* Dell Wireless 5811e QDL */ + {DEVICE_SWI(0x413c, 0x81cf)}, /* Dell Wireless 5819 */ + {DEVICE_SWI(0x413c, 0x81d0)}, /* Dell Wireless 5819 */ + {DEVICE_SWI(0x413c, 0x81d1)}, /* Dell Wireless 5818 */ + {DEVICE_SWI(0x413c, 0x81d2)}, /* Dell Wireless 5818 */ /* Huawei devices */ {DEVICE_HWI(0x03f0, 0x581d)}, /* HP lt4112 LTE/HSPA+ Gobi 4G Modem (Huawei me906e) */ diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 1a59f335b063..a3ccb899df60 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -834,13 +834,25 @@ Retry_Sense: if (result == USB_STOR_TRANSPORT_GOOD) { srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; + } + + /* + * ATA-passthru commands use sense data to report + * the command completion status, and often devices + * return Check Condition status when nothing is + * wrong. + */ + else if (srb->cmnd[0] == ATA_16 || + srb->cmnd[0] == ATA_12) { + /* leave the data alone */ + } /* * If there was a problem, report an unspecified * hardware error to prevent the higher layers from * entering an infinite retry loop. */ - } else { + else { srb->result = DID_ERROR << 16; if ((sshdr.response_code & 0x72) == 0x72) srb->sense_buffer[1] = HARDWARE_ERROR; diff --git a/drivers/usb/storage/uas-detect.h b/drivers/usb/storage/uas-detect.h index f58caa9e6a27..a155cd02bce2 100644 --- a/drivers/usb/storage/uas-detect.h +++ b/drivers/usb/storage/uas-detect.h @@ -9,7 +9,8 @@ static int uas_is_interface(struct usb_host_interface *intf) intf->desc.bInterfaceProtocol == USB_PR_UAS); } -static int uas_find_uas_alt_setting(struct usb_interface *intf) +static struct usb_host_interface *uas_find_uas_alt_setting( + struct usb_interface *intf) { int i; @@ -17,10 +18,10 @@ static int uas_find_uas_alt_setting(struct usb_interface *intf) struct usb_host_interface *alt = &intf->altsetting[i]; if (uas_is_interface(alt)) - return alt->desc.bAlternateSetting; + return alt; } - return -ENODEV; + return NULL; } static int uas_find_endpoints(struct usb_host_interface *alt, @@ -58,14 +59,14 @@ static int uas_use_uas_driver(struct usb_interface *intf, struct usb_device *udev = interface_to_usbdev(intf); struct usb_hcd *hcd = bus_to_hcd(udev->bus); unsigned long flags = id->driver_info; - int r, alt; - + struct usb_host_interface *alt; + int r; alt = uas_find_uas_alt_setting(intf); - if (alt < 0) + if (!alt) return 0; - r = uas_find_endpoints(&intf->altsetting[alt], eps); + r = uas_find_endpoints(alt, eps); if (r < 0) return 0; diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index cfb1e3bbd434..63cf981ed81c 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -873,14 +873,14 @@ MODULE_DEVICE_TABLE(usb, uas_usb_ids); static int uas_switch_interface(struct usb_device *udev, struct usb_interface *intf) { - int alt; + struct usb_host_interface *alt; alt = uas_find_uas_alt_setting(intf); - if (alt < 0) - return alt; + if (!alt) + return -ENODEV; - return usb_set_interface(udev, - intf->altsetting[0].desc.bInterfaceNumber, alt); + return usb_set_interface(udev, alt->desc.bInterfaceNumber, + alt->desc.bAlternateSetting); } static int uas_configure_endpoints(struct uas_dev_info *devinfo) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 5a70c33ef0e0..eb06d88b41d6 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1459,6 +1459,13 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_SANE_SENSE ), +/* Reported by Kris Lindgren <kris.lindgren@gmail.com> */ +UNUSUAL_DEV( 0x0bc2, 0x3332, 0x0000, 0x9999, + "Seagate", + "External", + USB_SC_DEVICE, USB_PR_DEVICE, NULL, + US_FL_NO_WP_DETECT ), + UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", "USB to SATA", diff --git a/drivers/uwb/hwa-rc.c b/drivers/uwb/hwa-rc.c index 35a1e777b449..9a53912bdfe9 100644 --- a/drivers/uwb/hwa-rc.c +++ b/drivers/uwb/hwa-rc.c @@ -825,6 +825,8 @@ static int hwarc_probe(struct usb_interface *iface, if (iface->cur_altsetting->desc.bNumEndpoints < 1) return -ENODEV; + if (!usb_endpoint_xfer_int(&iface->cur_altsetting->endpoint[0].desc)) + return -ENODEV; result = -ENOMEM; uwb_rc = uwb_rc_alloc(); diff --git a/drivers/uwb/uwbd.c b/drivers/uwb/uwbd.c index 01c20a260a8b..39dd4ef53c77 100644 --- a/drivers/uwb/uwbd.c +++ b/drivers/uwb/uwbd.c @@ -302,18 +302,22 @@ static int uwbd(void *param) /** Start the UWB daemon */ void uwbd_start(struct uwb_rc *rc) { - rc->uwbd.task = kthread_run(uwbd, rc, "uwbd"); - if (rc->uwbd.task == NULL) + struct task_struct *task = kthread_run(uwbd, rc, "uwbd"); + if (IS_ERR(task)) { + rc->uwbd.task = NULL; printk(KERN_ERR "UWB: Cannot start management daemon; " "UWB won't work\n"); - else + } else { + rc->uwbd.task = task; rc->uwbd.pid = rc->uwbd.task->pid; + } } /* Stop the UWB daemon and free any unprocessed events */ void uwbd_stop(struct uwb_rc *rc) { - kthread_stop(rc->uwbd.task); + if (rc->uwbd.task) + kthread_stop(rc->uwbd.task); uwbd_flush(rc); } diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 82360594fa8e..57efbd3b053b 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c @@ -1024,6 +1024,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) mutex_unlock(&priv->lock); if (use_ptemod) { + map->pages_vm_start = vma->vm_start; err = apply_to_page_range(vma->vm_mm, vma->vm_start, vma->vm_end - vma->vm_start, find_grant_ptes, map); @@ -1061,7 +1062,6 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma) set_grant_ptes_as_special, NULL); } #endif - map->pages_vm_start = vma->vm_start; } return 0; diff --git a/drivers/xen/xen-balloon.c b/drivers/xen/xen-balloon.c index e89136ab851e..b437fccd4e62 100644 --- a/drivers/xen/xen-balloon.c +++ b/drivers/xen/xen-balloon.c @@ -57,7 +57,7 @@ static int register_balloon(struct device *dev); static void watch_target(struct xenbus_watch *watch, const char *path, const char *token) { - unsigned long long new_target; + unsigned long long new_target, static_max; int err; static bool watch_fired; static long target_diff; @@ -72,13 +72,20 @@ static void watch_target(struct xenbus_watch *watch, * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10. */ new_target >>= PAGE_SHIFT - 10; - if (watch_fired) { - balloon_set_new_target(new_target - target_diff); - return; + + if (!watch_fired) { + watch_fired = true; + err = xenbus_scanf(XBT_NIL, "memory", "static-max", "%llu", + &static_max); + if (err != 1) + static_max = new_target; + else + static_max >>= PAGE_SHIFT - 10; + target_diff = xen_pv_domain() ? 0 + : static_max - balloon_stats.target_pages; } - watch_fired = true; - target_diff = new_target - balloon_stats.target_pages; + balloon_set_new_target(new_target - target_diff); } static struct xenbus_watch target_watch = { .node = "memory/target", |