diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index fe106da41ae5..6fd78cbfe1d6 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -605,6 +605,14 @@ config X86_NUMACHIP enable more than ~168 cores. If you don't have one of these, you should say N here. +config X86_PS5 + bool "Sony PlayStation 5" + depends on X86_64 + depends on X86_EXTENDED_PLATFORM + depends on PCI + help + Select to include support for the Sony PlayStation 5 game console. + config X86_VSMP bool "ScaleMP vSMP" select HYPERVISOR_GUEST diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h index 4efbbf9d117b..403d5ff74ef0 100644 --- a/arch/x86/include/asm/msr-index.h +++ b/arch/x86/include/asm/msr-index.h @@ -26,6 +26,7 @@ #define _EFER_LMSLE 13 /* Long Mode Segment Limit Enable */ #define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */ #define _EFER_TCE 15 /* Enable Translation Cache Extensions */ +#define _EFER_NDA 16 /* No data access enable */ #define _EFER_AUTOIBRS 21 /* Enable Automatic IBRS */ #define EFER_SCE (1<<_EFER_SCE) @@ -36,6 +37,7 @@ #define EFER_LMSLE (1<<_EFER_LMSLE) #define EFER_FFXSR (1<<_EFER_FFXSR) #define EFER_TCE (1<<_EFER_TCE) +#define EFER_NDA (1<<_EFER_NDA) #define EFER_AUTOIBRS (1<<_EFER_AUTOIBRS) /* diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h index 2ec250ba467e..f4654b2e63d0 100644 --- a/arch/x86/include/asm/pgtable_types.h +++ b/arch/x86/include/asm/pgtable_types.h @@ -21,8 +21,9 @@ #define _PAGE_BIT_SOFTW2 10 /* " */ #define _PAGE_BIT_SOFTW3 11 /* " */ #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */ -#define _PAGE_BIT_SOFTW4 57 /* available for programmer */ -#define _PAGE_BIT_SOFTW5 58 /* available for programmer */ +#define _PAGE_BIT_SOFTW4 56 /* available for programmer */ +#define _PAGE_BIT_SOFTW5 57 /* available for programmer */ +#define _PAGE_BIT_NDA 58 /* No data access */ #define _PAGE_BIT_PKEY_BIT0 59 /* Protection Keys, bit 1/4 */ #define _PAGE_BIT_PKEY_BIT1 60 /* Protection Keys, bit 2/4 */ #define _PAGE_BIT_PKEY_BIT2 61 /* Protection Keys, bit 3/4 */ @@ -65,6 +66,7 @@ #define _PAGE_SPECIAL (_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL) #define _PAGE_CPA_TEST (_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST) #define _PAGE_KERNEL_4K (_AT(pteval_t, 1) << _PAGE_BIT_KERNEL_4K) +#define _PAGE_NDA (_AT(pteval_t, 1) << _PAGE_BIT_NDA) #ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS #define _PAGE_PKEY_BIT0 (_AT(pteval_t, 1) << _PAGE_BIT_PKEY_BIT0) #define _PAGE_PKEY_BIT1 (_AT(pteval_t, 1) << _PAGE_BIT_PKEY_BIT1) @@ -192,6 +194,7 @@ enum page_cache_mode { #define ___D _PAGE_DIRTY #define ___G _PAGE_GLOBAL #define __NX _PAGE_NX +#define _NDA _PAGE_NDA #define _ENC _PAGE_ENC #define __WP _PAGE_CACHE_WP @@ -210,6 +213,7 @@ enum page_cache_mode { #define PAGE_COPY __pg(__PP| 0|_USR|___A|__NX| 0| 0| 0) #define PAGE_READONLY __pg(__PP| 0|_USR|___A|__NX| 0| 0| 0) #define PAGE_READONLY_EXEC __pg(__PP| 0|_USR|___A| 0| 0| 0| 0) +#define PAGE_EXECONLY __pg(__PP| 0|_USR|___A|_NDA| 0| 0| 0) /* * Page tables needs to have Write=1 in order for any lower PTEs to be diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h index 914eb32581c7..1199b0762d60 100644 --- a/arch/x86/include/asm/setup.h +++ b/arch/x86/include/asm/setup.h @@ -69,6 +69,12 @@ extern void x86_ce4100_early_setup(void); static inline void x86_ce4100_early_setup(void) { } #endif +#ifdef CONFIG_X86_PS5 +extern void x86_ps5_early_setup(void); +#else +static inline void x86_ps5_early_setup(void) { } +#endif + #include #ifndef _SETUP diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h index dafbf581c515..791687363cbf 100644 --- a/arch/x86/include/uapi/asm/bootparam.h +++ b/arch/x86/include/uapi/asm/bootparam.h @@ -207,6 +207,7 @@ enum x86_hardware_subarch { X86_SUBARCH_XEN, X86_SUBARCH_INTEL_MID, X86_SUBARCH_CE4100, + X86_SUBARCH_PS5, X86_NR_SUBARCHS, }; diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index fd28b53dbac5..569fc764d267 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c @@ -303,6 +303,11 @@ void __init __noreturn x86_64_start_reservations(char *real_mode_data) case X86_SUBARCH_INTEL_MID: x86_intel_mid_early_setup(); break; +#ifdef CONFIG_X86_PS5 + case X86_SUBARCH_PS5: + x86_ps5_early_setup(); + break; +#endif default: break; } diff --git a/arch/x86/kernel/i8253.c b/arch/x86/kernel/i8253.c index cb9852ad6098..83bb0cf9e40b 100644 --- a/arch/x86/kernel/i8253.c +++ b/arch/x86/kernel/i8253.c @@ -31,6 +31,11 @@ struct clock_event_device *global_clock_event; */ static bool __init use_pit(void) { +#ifdef CONFIG_X86_PS5 + /* PIT is not available. */ + return false; +#endif + if (!IS_ENABLED(CONFIG_X86_TSC) || !boot_cpu_has(X86_FEATURE_TSC)) return true; diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index ccc7b2e34a11..7d941c4d30f6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -112,7 +112,11 @@ EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_host); */ #ifdef CONFIG_X86_64 static +#ifdef CONFIG_X86_PS5 +u64 __read_mostly efer_reserved_bits = ~((u64)(EFER_SCE | EFER_LME | EFER_LMA | EFER_NDA)); +#else u64 __read_mostly efer_reserved_bits = ~((u64)(EFER_SCE | EFER_LME | EFER_LMA)); +#endif #else static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE); #endif diff --git a/arch/x86/mm/pgprot.c b/arch/x86/mm/pgprot.c index dc1afd5c839d..745db92fb2c1 100644 --- a/arch/x86/mm/pgprot.c +++ b/arch/x86/mm/pgprot.c @@ -10,7 +10,11 @@ static pgprot_t protection_map[16] __ro_after_init = { [VM_READ] = PAGE_READONLY, [VM_WRITE] = PAGE_COPY, [VM_WRITE | VM_READ] = PAGE_COPY, +#ifdef CONFIG_X86_PS5 + [VM_EXEC] = PAGE_EXECONLY, +#else [VM_EXEC] = PAGE_READONLY_EXEC, +#endif [VM_EXEC | VM_READ] = PAGE_READONLY_EXEC, [VM_EXEC | VM_WRITE] = PAGE_COPY_EXEC, [VM_EXEC | VM_WRITE | VM_READ] = PAGE_COPY_EXEC, @@ -18,7 +22,11 @@ static pgprot_t protection_map[16] __ro_after_init = { [VM_SHARED | VM_READ] = PAGE_READONLY, [VM_SHARED | VM_WRITE] = PAGE_SHARED, [VM_SHARED | VM_WRITE | VM_READ] = PAGE_SHARED, +#ifdef CONFIG_X86_PS5 + [VM_SHARED | VM_EXEC] = PAGE_EXECONLY, +#else [VM_SHARED | VM_EXEC] = PAGE_READONLY_EXEC, +#endif [VM_SHARED | VM_EXEC | VM_READ] = PAGE_READONLY_EXEC, [VM_SHARED | VM_EXEC | VM_WRITE] = PAGE_SHARED_EXEC, [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = PAGE_SHARED_EXEC diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 63105b29fbf5..f38e2601531c 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -57,14 +57,100 @@ int raw_pci_write(unsigned int domain, unsigned int bus, unsigned int devfn, return -EINVAL; } +#ifdef CONFIG_X86_PS5 +static DEFINE_RAW_SPINLOCK(pci_lock); + +static int sfc_read(unsigned int domain, unsigned int bus, unsigned int rid, + int reg, int len, u32 *val) +{ + int busno; + int slot; + int func; + + busno = (rid >> 8) & 0xff; + slot = (rid & 0xff) >> 3; + func = rid & 0x07; + + if (busno == 0 || busno == 32) { + raw_pci_write(domain, bus, 0, 0xd90, 4, 4); + raw_pci_write(domain, bus, 0, 0xd80, 4, (32 << 24) | (slot << 19) | (func << 16) | (reg & 0xf80)); + return raw_pci_read(domain, bus, 0, (reg & 0x7f) | 0xf80, len, val); + } else if (busno < 32) { + raw_pci_write(domain, bus, 0, 0xd10, 4, busno == 1 ? 4 : 5); + raw_pci_write(domain, bus, 0, 0xd00, 4, (busno << 24) | (slot << 19) | (func << 16) | (reg & 0xf80)); + return raw_pci_read(domain, bus, 0, (reg & 0x7f) | 0xf00, len, val); + } else { + panic("wrong bus number"); + } +} + +static int sfc_write(unsigned int domain, unsigned int bus, unsigned int rid, + int reg, int len, u32 val) +{ + int busno; + int slot; + int func; + + busno = (rid >> 8) & 0xff; + slot = (rid & 0xff) >> 3; + func = rid & 0x07; + + if (busno == 0 || busno == 32) { + raw_pci_write(domain, bus, 0, 0xd90, 4, 4); + raw_pci_write(domain, bus, 0, 0xd80, 4, (32 << 24) | (slot << 19) | (func << 16) | (reg & 0xf80)); + return raw_pci_write(domain, bus, 0, (reg & 0x7f) | 0xf80, len, val); + } else if (busno < 32) { + raw_pci_write(domain, bus, 0, 0xd10, 4, busno == 1 ? 4 : 5); + raw_pci_write(domain, bus, 0, 0xd00, 4, (busno << 24) | (slot << 19) | (func << 16) | (reg & 0xf80)); + return raw_pci_write(domain, bus, 0, (reg & 0x7f) | 0xf00, len, val); + } else { + panic("wrong bus number"); + } +} +#endif + static int pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *value) { + int ret; + unsigned long flags; + +#ifdef CONFIG_X86_PS5 + if (pci_ari_enabled(bus)) { + u32 rid = 0; + raw_spin_lock_irqsave(&pci_lock, flags); + raw_pci_read(pci_domain_nr(bus), bus->number, devfn, 0x150, 2, &rid); + if (rid != 0 && rid != 0xffff) { + ret = sfc_read(pci_domain_nr(bus), bus->number, rid, where, size, value); + raw_spin_unlock_irqrestore(&pci_lock, flags); + return ret; + } + raw_spin_unlock_irqrestore(&pci_lock, flags); + } +#endif + return raw_pci_read(pci_domain_nr(bus), bus->number, devfn, where, size, value); } static int pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { + int ret; + unsigned long flags; + +#ifdef CONFIG_X86_PS5 + if (pci_ari_enabled(bus)) { + u32 rid = 0; + raw_spin_lock_irqsave(&pci_lock, flags); + raw_pci_read(pci_domain_nr(bus), bus->number, devfn, 0x150, 2, &rid); + if (rid != 0 && rid != 0xffff) { + ret = sfc_write(pci_domain_nr(bus), bus->number, rid, where, size, value); + raw_spin_unlock_irqrestore(&pci_lock, flags); + return ret; + } + raw_spin_unlock_irqrestore(&pci_lock, flags); + } +#endif + return raw_pci_write(pci_domain_nr(bus), bus->number, devfn, where, size, value); } diff --git a/arch/x86/pci/irq.c b/arch/x86/pci/irq.c index 0de436316a1d..dde625251c99 100644 --- a/arch/x86/pci/irq.c +++ b/arch/x86/pci/irq.c @@ -1720,6 +1720,11 @@ static int pirq_enable_irq(struct pci_dev *dev) { u8 pin = 0; +#ifdef CONFIG_X86_PS5 + /* Legacy IRQ is not available. */ + return 0; +#endif + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); if (pin && !pcibios_lookup_irq(dev, 1)) { char *msg = ""; @@ -1801,6 +1806,11 @@ bool mp_should_keep_irq(struct device *dev) static void pirq_disable_irq(struct pci_dev *dev) { +#ifdef CONFIG_X86_PS5 + /* Legacy IRQ is not available. */ + return; +#endif + if (io_apic_assign_pci_irqs && !mp_should_keep_irq(&dev->dev) && dev->irq_managed && dev->irq) { mp_unmap_irq(dev->irq); diff --git a/arch/x86/platform/Makefile b/arch/x86/platform/Makefile index 3ed03a2552d0..40ffa1a2156a 100644 --- a/arch/x86/platform/Makefile +++ b/arch/x86/platform/Makefile @@ -9,6 +9,7 @@ obj-y += intel/ obj-y += intel-mid/ obj-y += intel-quark/ obj-y += olpc/ +obj-y += ps5/ obj-y += scx200/ obj-y += ts5500/ obj-y += uv/ diff --git a/arch/x86/platform/ps5/Makefile b/arch/x86/platform/ps5/Makefile new file mode 100644 index 000000000000..5263181876f8 --- /dev/null +++ b/arch/x86/platform/ps5/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_X86_PS5) += ps5.o diff --git a/arch/x86/platform/ps5/ps5.c b/arch/x86/platform/ps5/ps5.c new file mode 100644 index 000000000000..731fed163a83 --- /dev/null +++ b/arch/x86/platform/ps5/ps5.c @@ -0,0 +1,51 @@ +#include +#include + +#include +#include +#include +#include + +#define PS5_DEFAULT_TSC_FREQ 1596300000 + +static __noreturn void ps5_power_off(void) { + icc_power_shutdown(); +} + +static __noreturn void ps5_emergency_restart(void) { + icc_power_reboot(); +} + +static __noreturn void ps5_restart(char *cmd) { + ps5_emergency_restart(); +} + +static unsigned long __init ps5_calibrate_tsc(void) +{ + return PS5_DEFAULT_TSC_FREQ / 1000; +} + +static void ps5_get_wallclock(struct timespec64 *now) +{ + now->tv_sec = now->tv_nsec = 0; +} + +static int ps5_set_wallclock(const struct timespec64 *now) +{ + return -ENODEV; +} + +void __init x86_ps5_early_setup(void) +{ + x86_platform.calibrate_tsc = ps5_calibrate_tsc; + x86_platform.get_wallclock = ps5_get_wallclock; + x86_platform.set_wallclock = ps5_set_wallclock; + x86_platform.legacy.rtc = 0; + + machine_ops.restart = ps5_restart; + machine_ops.power_off = ps5_power_off; + machine_ops.emergency_restart = ps5_emergency_restart; + pm_power_off = ps5_power_off; + + legacy_pic = &null_legacy_pic; +} diff --git a/block/partitions/efi.c b/block/partitions/efi.c index 75474fb3848e..44a0744533a0 100644 --- a/block/partitions/efi.c +++ b/block/partitions/efi.c @@ -90,6 +90,9 @@ #include "check.h" #include "efi.h" +#define PS5_M2_PART44_LBA_OFFSET 34224 +#define PS5_M2_MBR_LBA 65536 + /* This allows a kernel command line option 'gpt' to override * the test for invalid PMBR. Not __initdata because reloading * the partition tables happens after init too. @@ -133,6 +136,12 @@ efi_crc32(const void *buf, unsigned long len) */ static u64 last_lba(struct gendisk *disk) { +#ifdef CONFIG_X86_PS5 + if (strncmp(disk->disk_name, "nvme", 4) == 0) { + return div_u64(bdev_nr_bytes(disk->part0), + queue_logical_block_size(disk->queue)) - 1ULL - PS5_M2_PART44_LBA_OFFSET; + } else +#endif return div_u64(bdev_nr_bytes(disk->part0), queue_logical_block_size(disk->queue)) - 1ULL; } @@ -143,8 +152,14 @@ static inline int pmbr_part_valid(gpt_mbr_record *part) goto invalid; /* set to 0x00000001 (i.e., the LBA of the GPT Partition Header) */ +#ifdef CONFIG_X86_PS5 + if (le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA && + le32_to_cpu(part->starting_lba) != PS5_M2_MBR_LBA + GPT_PRIMARY_PARTITION_TABLE_LBA) + goto invalid; +#else if (le32_to_cpu(part->starting_lba) != GPT_PRIMARY_PARTITION_TABLE_LBA) goto invalid; +#endif return GPT_MBR_PROTECTIVE; invalid: @@ -599,6 +614,11 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, if (!legacymbr) goto fail; +#ifdef CONFIG_X86_PS5 + if (strncmp(state->disk->disk_name, "nvme", 4) == 0) { + read_lba(state, PS5_M2_MBR_LBA, (u8 *)legacymbr, sizeof(*legacymbr)); + } else +#endif read_lba(state, 0, (u8 *)legacymbr, sizeof(*legacymbr)); good_pmbr = is_pmbr_valid(legacymbr, total_sectors); kfree(legacymbr); @@ -611,6 +631,12 @@ static int find_valid_gpt(struct parsed_partitions *state, gpt_header **gpt, "protective" : "hybrid"); } +#ifdef CONFIG_X86_PS5 + if (strncmp(state->disk->disk_name, "nvme", 4) == 0) { + good_pgpt = is_gpt_valid(state, PS5_M2_MBR_LBA + GPT_PRIMARY_PARTITION_TABLE_LBA, + &pgpt, &pptes); + } else +#endif good_pgpt = is_gpt_valid(state, GPT_PRIMARY_PARTITION_TABLE_LBA, &pgpt, &pptes); if (good_pgpt) diff --git a/drivers/Makefile b/drivers/Makefile index 53fbd2e0acdd..d36c1909e0e6 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -199,3 +199,5 @@ obj-y += resctrl/ obj-$(CONFIG_DIBS) += dibs/ obj-$(CONFIG_S390) += s390/ + +obj-$(CONFIG_X86_PS5) += ps5/ diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 2349bca136e0..3efbb88fdc32 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -299,6 +299,18 @@ config AHCI_QORIQ If unsure, say N. +config AHCI_SALINA + tristate "Sony PlayStation 5 Salina SATA / BD-ROM AHCI support" + depends on PCI + depends on X86_PS5 || COMPILE_TEST + select SATA_HOST + help + This option enables support for the PlayStation 5 "Salina" SATA + AHCI controller (PCI 104d:9105 / 104d:9106) that fronts the + internal Blu-ray drive. + + If unsure, say N. + config SATA_FSL tristate "Freescale 3.0Gbps SATA support" depends on FSL_SOC || COMPILE_TEST diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile index 20e6645ab737..bc98a92325b7 100644 --- a/drivers/ata/Makefile +++ b/drivers/ata/Makefile @@ -27,6 +27,8 @@ obj-$(CONFIG_AHCI_ST) += ahci_st.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_TEGRA) += ahci_tegra.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_XGENE) += ahci_xgene.o libahci.o libahci_platform.o obj-$(CONFIG_AHCI_QORIQ) += ahci_qoriq.o libahci.o libahci_platform.o +obj-$(CONFIG_AHCI_SALINA) += ahci_salina_drv.o libahci.o +ahci_salina_drv-y := ahci_salina.o ahci_salina_phy.o # SFF w/ custom DMA obj-$(CONFIG_PDC_ADMA) += pdc_adma.o diff --git a/drivers/ata/ahci_salina.c b/drivers/ata/ahci_salina.c new file mode 100644 index 000000000000..c020194eb44a --- /dev/null +++ b/drivers/ata/ahci_salina.c @@ -0,0 +1,340 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PlayStation 5 Salina SATA / BD-ROM AHCI host driver + * + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ahci.h" +#include "ahci_salina_phy.h" + +#define PCI_DEVICE_ID_SPCIE 0x9107 + +#define SALINA_ICC_DEV_BD 0x01 + +struct salina_ahci { + struct salina_sata_phy phy; + struct pci_dev *glue; +}; + +static int salina_glue_map(struct salina_ahci *sa) +{ + struct pci_dev *glue; + + glue = pci_get_device(PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_SPCIE, NULL); + if (!glue) + return -ENODEV; + + if (!(pci_resource_flags(glue, 2) & IORESOURCE_MEM) || + !(pci_resource_flags(glue, 4) & IORESOURCE_MEM)) { + pci_dev_put(glue); + return -ENODEV; + } + + sa->phy.glue_phy = ioremap(pci_resource_start(glue, 2), + pci_resource_len(glue, 2)); + if (!sa->phy.glue_phy) { + pci_dev_put(glue); + return -ENOMEM; + } + + sa->phy.glue_pcs = ioremap(pci_resource_start(glue, 4), + pci_resource_len(glue, 4)); + if (!sa->phy.glue_pcs) { + iounmap(sa->phy.glue_phy); + sa->phy.glue_phy = NULL; + pci_dev_put(glue); + return -ENOMEM; + } + + sa->glue = glue; + return 0; +} + +static void salina_glue_unmap(struct salina_ahci *sa) +{ + if (sa->phy.glue_pcs) { + iounmap(sa->phy.glue_pcs); + sa->phy.glue_pcs = NULL; + } + if (sa->phy.glue_phy) { + iounmap(sa->phy.glue_phy); + sa->phy.glue_phy = NULL; + } + if (sa->glue) { + pci_dev_put(sa->glue); + sa->glue = NULL; + } +} + +static int salina_pick_bar(u16 devid, u32 chip_id, unsigned int *abar, + u32 *port_off) +{ + bool is_9106 = (devid == PCI_DEVICE_ID_AHCI_B); + + if (!is_9106 && chip_id == SALINA_CHIP_SALINA2) + return -ENODEV; + + *abar = 0; + *port_off = is_9106 ? 0x2000 : 0; + return 0; +} + +static struct ata_port_operations salina_ahci_ops = { + .inherits = &ahci_ops, +}; + +static const struct ata_port_info salina_port_info = { + .flags = AHCI_FLAG_COMMON, + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, + .port_ops = &salina_ahci_ops, +}; + +static const struct scsi_host_template salina_ahci_sht = { + AHCI_SHT(KBUILD_MODNAME), +}; + +static int salina_ahci_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct device *dev = &pdev->dev; + const struct ata_port_info *ppi[] = { &salina_port_info, NULL }; + struct ahci_host_priv *hpriv; + struct ata_host *host; + struct salina_ahci *sa; + unsigned int abar, n_ports; + u32 chip_id; + u8 state; + int rc; + + if (!spcie_is_initialized()) { + dev_warn(dev, "spcie not initialized yet, deferring\n"); + return -EPROBE_DEFER; + } + + rc = pcim_enable_device(pdev); + if (rc) + return rc; + + pci_set_master(pdev); + + rc = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); + if (rc) + return rc; + + sa = devm_kzalloc(dev, sizeof(*sa), GFP_KERNEL); + if (!sa) + return -ENOMEM; + + rc = salina_glue_map(sa); + if (rc) { + dev_err(dev, "glue (104d:9107) map failed: %d\n", rc); + return rc; + } + + chip_id = spcie_get_chip_id(); + if (chip_id != SALINA_CHIP_SALINA && chip_id != SALINA_CHIP_SALINA2) { + dev_err(dev, "unknown Salina chip id %#x\n", chip_id); + rc = -ENODEV; + goto err_glue; + } + + rc = salina_pick_bar(pdev->device, chip_id, &abar, &sa->phy.port_off); + if (rc) { + dev_info(dev, "SALINA2 SATA0 dummy device, claiming but not attaching\n"); + pci_set_drvdata(pdev, NULL); + salina_glue_unmap(sa); + return 0; + } + + rc = pcim_iomap_regions(pdev, BIT(abar), KBUILD_MODNAME); + if (rc) + goto err_glue; + + sa->phy.ctrl = pcim_iomap_table(pdev)[abar]; + sa->phy.chip_id = chip_id; + sa->phy.devid = (pdev->device << 16) | pdev->vendor; + sa->phy.is_bd = true; + sa->phy.rx_tracelen = 0xff; + sa->phy.tx_tracelen = 0xff; + + icc_device_power_get(SALINA_ICC_DEV_BD, &state); + if (state != 1) + icc_device_power_control(SALINA_ICC_DEV_BD, 1); + + rc = salina_sata_phy_init(&sa->phy); + if (rc) { + dev_err(dev, "Salina SATA PHY init failed: %d\n", rc); + goto err_glue; + } + + hpriv = devm_kzalloc(dev, sizeof(*hpriv), GFP_KERNEL); + if (!hpriv) { + rc = -ENOMEM; + goto err_glue; + } + + hpriv->mmio = sa->phy.ctrl + sa->phy.port_off; + hpriv->plat_data = sa; + hpriv->flags = AHCI_HFLAG_NO_PMP; + + ahci_save_initial_config(dev, hpriv); + + rc = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI | PCI_IRQ_INTX); + if (rc < 0) { + dev_err(dev, "irq alloc failed: %d\n", rc); + goto err_glue; + } + hpriv->irq = pci_irq_vector(pdev, 0); + + n_ports = max(ahci_nr_ports(hpriv->cap), fls(hpriv->port_map)); + + host = ata_host_alloc_pinfo(dev, ppi, n_ports); + if (!host) { + rc = -ENOMEM; + goto err_glue; + } + host->private_data = hpriv; + + if (!(hpriv->cap & HOST_CAP_SSS)) + host->flags |= ATA_HOST_PARALLEL_SCAN; + + rc = ahci_reset_controller(host); + if (rc) + goto err_glue; + + ahci_init_controller(host); + ahci_print_info(host, "Salina"); + + pci_set_drvdata(pdev, host); + + dev_info(dev, + "Salina SATA up (chip %#x, devid %#x, BAR%u, port_off %#x, %u ports)\n", + sa->phy.chip_id, sa->phy.devid, abar, sa->phy.port_off, n_ports); + + return ahci_host_activate(host, &salina_ahci_sht); + +err_glue: + salina_glue_unmap(sa); + return rc; +} + +static void salina_ahci_remove(struct pci_dev *pdev) +{ + struct ata_host *host = pci_get_drvdata(pdev); + struct ahci_host_priv *hpriv; + struct salina_ahci *sa; + + if (!host) + return; + + hpriv = host->private_data; + sa = hpriv->plat_data; + + ata_host_detach(host); + pci_free_irq_vectors(pdev); + salina_glue_unmap(sa); +} + +#ifdef CONFIG_PM_SLEEP +static int salina_ahci_suspend(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct ata_host *host = pci_get_drvdata(pdev); + struct ahci_host_priv *hpriv; + void __iomem *mmio; + u32 ctl; + int rc; + + if (!host) + return 0; + + hpriv = host->private_data; + mmio = hpriv->mmio; + + ctl = readl(mmio + HOST_CTL); + ctl &= ~HOST_IRQ_EN; + writel(ctl, mmio + HOST_CTL); + readl(mmio + HOST_CTL); + + rc = ata_host_suspend(host, PMSG_SUSPEND); + if (rc) + return rc; + + pci_save_state(pdev); + pci_set_power_state(pdev, PCI_D3hot); + return 0; +} + +static int salina_ahci_resume(struct device *dev) +{ + struct pci_dev *pdev = to_pci_dev(dev); + struct ata_host *host = pci_get_drvdata(pdev); + struct ahci_host_priv *hpriv; + struct salina_ahci *sa; + int rc; + + if (!host) + return 0; + + hpriv = host->private_data; + sa = hpriv->plat_data; + + rc = pci_set_power_state(pdev, PCI_D0); + if (rc) + return rc; + pci_restore_state(pdev); + pci_set_master(pdev); + + rc = salina_sata_phy_init(&sa->phy); + if (rc) { + dev_err(dev, "PHY re-init on resume failed: %d\n", rc); + return rc; + } + + rc = ahci_reset_controller(host); + if (rc) + return rc; + + ahci_init_controller(host); + ata_host_resume(host); + + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(salina_ahci_pm, salina_ahci_suspend, salina_ahci_resume); + +static const struct pci_device_id salina_ahci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_AHCI_A) }, + { PCI_DEVICE(PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_AHCI_B) }, + { } +}; +MODULE_DEVICE_TABLE(pci, salina_ahci_tbl); + +static struct pci_driver salina_ahci_driver = { + .name = KBUILD_MODNAME, + .id_table = salina_ahci_tbl, + .probe = salina_ahci_probe, + .remove = salina_ahci_remove, + .driver = { + .pm = &salina_ahci_pm, + }, +}; + +module_pci_driver(salina_ahci_driver); + +MODULE_AUTHOR("Armandas Kvietkus"); +MODULE_DESCRIPTION("PlayStation 5 Salina SATA / BD-ROM AHCI driver"); +MODULE_LICENSE("GPL"); +MODULE_SOFTDEP("pre: libahci spcie"); diff --git a/drivers/ata/ahci_salina_phy.c b/drivers/ata/ahci_salina_phy.c new file mode 100644 index 000000000000..c5e85ae102ea --- /dev/null +++ b/drivers/ata/ahci_salina_phy.c @@ -0,0 +1,183 @@ +// SPDX-License-Identifier: GPL-2.0-only +#include +#include +#include +#include "ahci_salina_phy.h" + +static inline u32 phy_rd(struct salina_sata_phy *p, u32 off) +{ + return readl(p->ctrl + off); +} + +static inline void phy_wr(struct salina_sata_phy *p, u32 off, u32 val) +{ + writel(val, p->ctrl + off); +} + +static inline void phy_rmw(struct salina_sata_phy *p, u32 off, u32 keep, u32 set) +{ + phy_wr(p, off, (phy_rd(p, off) & keep) | set); +} + +static inline u32 port_rd(struct salina_sata_phy *p, u32 off) +{ + return readl(p->ctrl + p->port_off + off); +} + +static inline void port_wr(struct salina_sata_phy *p, u32 off, u32 val) +{ + writel(val, p->ctrl + p->port_off + off); +} + +static inline void lane_sel(struct salina_sata_phy *p, u32 sel, u32 val) +{ + writel(val, p->glue_phy + SALINA_GLUE_PHY_BASE + sel); +} + +static inline u32 efuse_rd(struct salina_sata_phy *p, u32 off) +{ + return readl(p->glue_pcs + SALINA_GLUE_PCS_BASE + off); +} + +static u32 trace_len(struct salina_sata_phy *p, u32 raw) +{ + u32 def = p->is_bd ? 10 : 4; + + if (raw == 0 || raw > 0xfe) + return def; + return (raw >> 5 & 7) + (raw & 0x1f); +} + +int salina_sata_phy_init(struct salina_sata_phy *p) +{ + u32 trim[6]; + u32 efuse, valid, sel, lane; + u32 rx, tx; + u32 a, b, c, d, e, f, rc; + bool tx_hi; + + sel = (p->devid != SALINA_DEVID_A) ? SALINA_PHY_SEL_B : SALINA_PHY_SEL_A; + lane_sel(p, sel, 2); + lane_sel(p, sel, 3); + lane_sel(p, sel, 1); + + efuse = efuse_rd(p, SALINA_EFUSE_TRIM); + valid = efuse_rd(p, SALINA_EFUSE_VALID); + + trim[0] = trim[1] = trim[2] = trim[3] = 0x10; + trim[4] = trim[5] = 0x28; + + if (valid & SALINA_EFUSE_VALID_A) { + trim[4] = efuse & 0x3f; + trim[2] = efuse >> 6 & 0x1f; + trim[0] = efuse >> 0xb & 0x1f; + } + if (valid & SALINA_EFUSE_VALID_B) { + trim[5] = efuse >> 0x10 & 0x3f; + trim[3] = efuse >> 0x16 & 0x1f; + trim[1] = efuse >> 0x1b; + } + + lane = (p->devid != SALINA_DEVID_A) ? 1 : 0; + + phy_rmw(p, 0xa0, 0xfbff03ff, (trim[lane + 4] << 10) | 0x4000000); + phy_rmw(p, 0x14, ~0u, 0x100000); + phy_rmw(p, 0x54, 0xfffff07f, trim[lane + 2] << 7); + phy_rmw(p, 0x1c, ~0u, 4); + phy_rmw(p, 0x78, 0xfffffe0f, trim[lane] << 4); + + rx = trace_len(p, p->rx_tracelen); + tx = trace_len(p, p->tx_tracelen); + + tx_hi = tx > 5; + if (tx_hi) { + c = 0x2000; + if (tx < 9) { + b = 0x1000000; + a = 0x200000; + } else { + a = (tx <= 0xc) ? 0x230000 : 0x260000; + b = (tx > 0xc) ? 0x9000000 : 0x5000000; + } + } else { + b = 0; + a = (tx >= 3) ? 0x1e0000 : 0x1d0000; + c = (tx < 3) ? 0x4000 : 0x2000; + } + + e = (tx > 8) ? 0x4000 : 0; + f = (tx > 8) ? 0x80 : 0; + d = e | 0x12000; + rc = f | 0x900; + e += 0x6000; + f += 0x8c0; + if (tx < 6) { + u32 ge3 = (tx >= 3) ? 1 : 0; + + d = ge3 * 0x1000 + 0xd000; + rc = (ge3 * 0x40) | 0x880; + e = ge3 << 0xd; + f = ge3 * 0x40 + 0x800; + } + + phy_rmw(p, 0x4c, 0xffc0ffff, a); + phy_rmw(p, 0x4c, 0xc0ffffff, b); + phy_rmw(p, 0x54, 0xffff9fff, c); + phy_rmw(p, 0x7c, 0xfffff03f, f); + phy_rmw(p, 0x7c, 0xfffc0fff, e); + phy_rmw(p, 0x5c, 0x0fffffff, (tx < 3) ? 0x60000000 : 0x50000000); + phy_rmw(p, 0x80, 0xfffff03f, rc); + phy_rmw(p, 0x80, 0xfffc0fff, d); + phy_rmw(p, 0x4c, 0xfffffff0, tx_hi ? 5 : 3); + + { + u32 rx_coef, rx_amp, rx_eq; + + if (rx < 3) { + rx_coef = 0x100; + rx_amp = 0x40; + rx_eq = 2; + } else if (rx < 6) { + rx_coef = 0x100; + rx_amp = 0x50; + rx_eq = 3; + } else { + rx_amp = 0x60; + rx_coef = 0x200; + rx_eq = 5; + } + phy_rmw(p, 0x6c, 0xfffff0ff, rx_coef); + phy_rmw(p, 0x84, 0xffffff00, rx_amp | rx_eq); + } + + phy_rmw(p, 0x40, 0xffffffe0, 0x12); + phy_rmw(p, 0x40, 0xffffc0ff, 0x3100); + phy_rmw(p, 0x40, 0xffe0ffff, 0xe0000); + phy_rmw(p, 0x40, 0xffffff1f, 0x80); + phy_rmw(p, 0x3c, 0x1fffefff, 0xa0000000); + phy_rmw(p, 0x44, 0xffffef80, 0x23); + phy_rmw(p, 0x1c, 0xff0fffff, 0x200000); + phy_rmw(p, 0xdc, 0xffffe0ff, 0x400); + phy_rmw(p, 0x24, ~0u, 0x30); + + lane_sel(p, sel, 0); + + { + int i; + + for (i = 0; i < 100; i++) { + if (port_rd(p, SALINA_PHY_RDY_REG) & SALINA_PHY_RDY) + break; + udelay(10); + } + if (i == 100) + return -ETIMEDOUT; + } + + port_wr(p, 0, port_rd(p, 0) & 0xe7ffffff); + port_wr(p, 0xc, 1); + port_wr(p, 0xb8, port_rd(p, 0xb8) | 0x20000); + port_wr(p, 0x118, (port_rd(p, 0x118) & 0xffe3ffff) | 0x40000); + + return 0; +} diff --git a/drivers/ata/ahci_salina_phy.h b/drivers/ata/ahci_salina_phy.h new file mode 100644 index 000000000000..39cc76f39e06 --- /dev/null +++ b/drivers/ata/ahci_salina_phy.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef _SALINA_SATA_PHY_H +#define _SALINA_SATA_PHY_H + +#include +#include + +#define PCI_DEVICE_ID_AHCI_A 0x9105 +#define PCI_DEVICE_ID_AHCI_B 0x9106 + +#define SALINA_DEVID_A 0x9105104d +#define SALINA_DEVID_B 0x9106104d + +#define SALINA_CHIP_SALINA 0x110000 +#define SALINA_CHIP_SALINA2 0x120000 + +#define SALINA_GLUE_PHY_BASE 0x180000 +#define SALINA_GLUE_PCS_BASE 0x4000 + +#define SALINA_EFUSE_TRIM 0x48 +#define SALINA_EFUSE_VALID 0x6c +#define SALINA_EFUSE_VALID_A 0x40000 +#define SALINA_EFUSE_VALID_B 0x4000000 + +#define SALINA_PHY_SEL_A 0x2c +#define SALINA_PHY_SEL_B 0x30 + +#define SALINA_PHY_RDY BIT(0) +#define SALINA_PHY_RDY_REG 0xdc + +struct salina_sata_phy { + void __iomem *ctrl; + void __iomem *glue_phy; + void __iomem *glue_pcs; + u32 port_off; + u32 chip_id; + u32 devid; + u32 rx_tracelen; + u32 tx_tracelen; + bool is_bd; +}; + +int salina_sata_phy_init(struct salina_sata_phy *p); + +#endif diff --git a/drivers/firmware/dmi-id.c b/drivers/firmware/dmi-id.c index 477a37e2ef80..e1af70946c89 100644 --- a/drivers/firmware/dmi-id.c +++ b/drivers/firmware/dmi-id.c @@ -228,8 +228,16 @@ static int __init dmi_id_init(void) { int ret; +#ifdef CONFIG_X86_PS5 + dmi_set_system_info(DMI_SYS_VENDOR, "Sony Interactive Entertainment"); + dmi_set_system_info(DMI_PRODUCT_NAME, "PlayStation 5"); + /* Filled by spcie.c */ + dmi_set_system_info(DMI_PRODUCT_VERSION, "Unknown"); + dmi_set_system_info(DMI_PRODUCT_SERIAL, "Unknown"); +#else if (!dmi_available) return -ENODEV; +#endif dmi_id_init_attr_table(); diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 70d39adf50dc..5d283649817e 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -953,6 +953,14 @@ const char *dmi_get_system_info(int field) } EXPORT_SYMBOL(dmi_get_system_info); +#ifdef CONFIG_X86_PS5 +void dmi_set_system_info(int field, const char *str) +{ + dmi_ident[field] = str; +} +EXPORT_SYMBOL(dmi_set_system_info); +#endif + /** * dmi_name_in_serial - Check if string is in the DMI product serial information * @str: string to check for diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 447e734c362b..c52c81e084a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -271,6 +271,10 @@ extern int amdgpu_user_queue; extern uint amdgpu_hdmi_hpd_debounce_delay_ms; +#ifdef CONFIG_X86_PS5 +extern int amdgpu_force_1080p; +#endif + #define AMDGPU_VM_MAX_NUM_CTX 4096 #define AMDGPU_SG_THRESHOLD (256*1024*1024) #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index 35d04e69aec0..314ceaaaab9f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -221,8 +221,14 @@ static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev) static bool amdgpu_read_platform_bios(struct amdgpu_device *adev) { +#ifdef CONFIG_X86_PS5 + /* Hardcode vbios rom address. */ + phys_addr_t rom = 0xc0000; + size_t romlen = 0x10000; +#else phys_addr_t rom = adev->pdev->rom; size_t romlen = adev->pdev->romlen; +#endif void __iomem *bios; adev->bios = NULL; @@ -436,6 +442,7 @@ static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev) static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) { +#ifndef CONFIG_X86_PS5 if (amdgpu_acpi_vfct_bios(adev)) { dev_info(adev->dev, "Fetched VBIOS from VFCT\n"); goto success; @@ -450,6 +457,7 @@ static bool amdgpu_get_bios_apu(struct amdgpu_device *adev) dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n"); goto success; } +#endif if (amdgpu_read_platform_bios(adev)) { dev_info(adev->dev, "Fetched VBIOS from platform\n"); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index 2ec69fa05cb1..502b878373e0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -2512,6 +2512,26 @@ static int amdgpu_device_parse_gpu_info_fw(struct amdgpu_device *adev) case CHIP_CYAN_SKILLFISH: if (adev->discovery.bin) return 0; +#ifdef CONFIG_X86_PS5 + /* Hardcode gfxinfo. */ + adev->gfx.config.max_shader_engines = 2; + adev->gfx.config.max_cu_per_sh = 10; + adev->gfx.config.max_sh_per_se = 2; + adev->gfx.config.max_backends_per_se = 8; + adev->gfx.config.max_texture_channel_caches = 16; + adev->gfx.config.max_gprs = 1024; + adev->gfx.config.max_gs_threads = 32; + adev->gfx.config.gs_vgt_table_depth = 32; + adev->gfx.config.gs_prim_buffer_depth = 1792; + adev->gfx.config.double_offchip_lds_buf = 1; + adev->gfx.cu_info.wave_front_size = 32; + adev->gfx.cu_info.max_waves_per_simd = 20; + adev->gfx.cu_info.max_scratch_slots_per_cu = 32; + adev->gfx.cu_info.lds_size = 64; + adev->gfx.config.num_sc_per_sh = 1; + adev->gfx.config.num_packer_per_sc = 2; + return 0; +#endif chip_name = "cyan_skillfish"; break; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index 3459d356151e..f09233c05e04 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -2914,6 +2914,9 @@ int amdgpu_discovery_set_ip_blocks(struct amdgpu_device *adev) adev->ip_versions[SMUIO_HWIP][0] = IP_VERSION(11, 0, 8); adev->ip_versions[GC_HWIP][0] = IP_VERSION(10, 1, 3); adev->ip_versions[UVD_HWIP][0] = IP_VERSION(2, 0, 3); +#ifdef CONFIG_X86_PS5 + adev->ip_versions[DCE_HWIP][0] = IP_VERSION(2, 0, 3); +#endif } break; default: diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index c91638e65174..00618809031f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -41,6 +41,10 @@ #include #include +#ifdef CONFIG_X86_PS5 +#include +#endif + #include "amdgpu.h" #include "amdgpu_amdkfd.h" #include "amdgpu_dma_buf.h" @@ -1134,6 +1138,12 @@ module_param_named(user_queue, amdgpu_user_queue, int, 0444); MODULE_PARM_DESC(hdmi_hpd_debounce_delay_ms, "HDMI HPD disconnect debounce delay in milliseconds (0 to disable (by default), 1500 is common)"); module_param_named(hdmi_hpd_debounce_delay_ms, amdgpu_hdmi_hpd_debounce_delay_ms, uint, 0644); +#ifdef CONFIG_X86_PS5 +int amdgpu_force_1080p = 0; +MODULE_PARM_DESC(force_1080p, "Force 1080p (0 = disabled (default), 1 = enabled)"); +module_param_named(force_1080p, amdgpu_force_1080p, int, 0444); +#endif + /* These devices are not supported by amdgpu. * They are supported by the mach64, r128, radeon drivers */ @@ -2179,6 +2189,7 @@ static const struct pci_device_id pciidlist[] = { {0x1002, 0x7410, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_ALDEBARAN}, /* CYAN_SKILLFISH */ + {0x1002, 0x13DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU}, {0x1002, 0x13DB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU}, {0x1002, 0x13F9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU}, {0x1002, 0x13FA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_CYAN_SKILLFISH|AMD_IS_APU}, @@ -2393,6 +2404,11 @@ static int amdgpu_pci_probe(struct pci_dev *pdev, int ret, retry = 0, i; bool supports_atomic = false; +#ifdef CONFIG_X86_PS5 + if (!spcie_is_initialized()) + return -EPROBE_DEFER; +#endif + if ((pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA || (pdev->class >> 8) == PCI_CLASS_DISPLAY_OTHER) { if (drm_firmware_drivers_only() && amdgpu_modeset == -1) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index 77578ecc6782..b037a6f57a6d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -2344,6 +2344,11 @@ void amdgpu_gfx_profile_ring_begin_use(struct amdgpu_ring *ring) enum PP_SMC_POWER_PROFILE profile; int r; +#ifdef CONFIG_X86_PS5 + /* DPM is not supported. */ + return; +#endif + if (amdgpu_dpm_is_overdrive_enabled(adev)) return; @@ -2379,6 +2384,11 @@ void amdgpu_gfx_profile_ring_end_use(struct amdgpu_ring *ring) { struct amdgpu_device *adev = ring->adev; +#ifdef CONFIG_X86_PS5 + /* DPM is not supported. */ + return; +#endif + if (amdgpu_dpm_is_overdrive_enabled(adev)) return; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c index 321310ba2c08..764da52902ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c @@ -210,6 +210,9 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev, const struct sdma_firmware_header_v3_0 *sdma_hv3; uint16_t version_major; char ucode_prefix[30]; +#ifdef CONFIG_X86_PS5 + struct common_firmware_header *hdr; +#endif amdgpu_ucode_ip_version_decode(adev, SDMA0_HWIP, ucode_prefix, sizeof(ucode_prefix)); if (instance == 0) @@ -222,6 +225,11 @@ int amdgpu_sdma_init_microcode(struct amdgpu_device *adev, "amdgpu/%s%d.bin", ucode_prefix, instance); if (err) goto out; +#ifdef CONFIG_X86_PS5 + hdr = (struct common_firmware_header *)adev->sdma.instance[instance].fw->data; + hdr->ucode_array_offset_bytes = cpu_to_le32(le32_to_cpu(hdr->ucode_array_offset_bytes) + 0x100); + hdr->ucode_size_bytes = cpu_to_le32(le32_to_cpu(hdr->ucode_size_bytes) - 0x200); +#endif header = (const struct common_firmware_header *) adev->sdma.instance[instance].fw->data; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c index 8b60299b73ef..7ecf928cae8e 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c @@ -4202,6 +4202,14 @@ static void gfx_v10_0_check_gfxoff_flag(struct amdgpu_device *adev) } } +static void gfx_v10_0_patch_ucode(const u8 *data) +{ + struct common_firmware_header *hdr; + hdr = (struct common_firmware_header *)data; + hdr->ucode_array_offset_bytes = cpu_to_le32(le32_to_cpu(hdr->ucode_array_offset_bytes) + 0x100); + hdr->ucode_size_bytes = cpu_to_le32(le32_to_cpu(hdr->ucode_size_bytes) - 0x200); +} + static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) { char fw_name[53]; @@ -4224,6 +4232,9 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) "amdgpu/%s_pfp%s.bin", ucode_prefix, wks); if (err) goto out; +#ifdef CONFIG_X86_PS5 + gfx_v10_0_patch_ucode(adev->gfx.pfp_fw->data); +#endif amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_PFP); err = amdgpu_ucode_request(adev, &adev->gfx.me_fw, @@ -4231,6 +4242,9 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) "amdgpu/%s_me%s.bin", ucode_prefix, wks); if (err) goto out; +#ifdef CONFIG_X86_PS5 + gfx_v10_0_patch_ucode(adev->gfx.me_fw->data); +#endif amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_ME); err = amdgpu_ucode_request(adev, &adev->gfx.ce_fw, @@ -4238,6 +4252,9 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) "amdgpu/%s_ce%s.bin", ucode_prefix, wks); if (err) goto out; +#ifdef CONFIG_X86_PS5 + gfx_v10_0_patch_ucode(adev->gfx.ce_fw->data); +#endif amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_CE); if (!amdgpu_sriov_vf(adev)) { @@ -4245,6 +4262,9 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) err = request_firmware(&adev->gfx.rlc_fw, fw_name, adev->dev); if (err) goto out; +#ifdef CONFIG_X86_PS5 + gfx_v10_0_patch_ucode(adev->gfx.rlc_fw->data); +#endif /* don't validate this firmware. There are apparently firmwares * in the wild with incorrect size in the header @@ -4262,6 +4282,9 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) "amdgpu/%s_mec%s.bin", ucode_prefix, wks); if (err) goto out; +#ifdef CONFIG_X86_PS5 + gfx_v10_0_patch_ucode(adev->gfx.mec_fw->data); +#endif amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1); amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1_JT); @@ -4269,6 +4292,9 @@ static int gfx_v10_0_init_microcode(struct amdgpu_device *adev) AMDGPU_UCODE_REQUIRED, "amdgpu/%s_mec2%s.bin", ucode_prefix, wks); if (!err) { +#ifdef CONFIG_X86_PS5 + gfx_v10_0_patch_ucode(adev->gfx.mec2_fw->data); +#endif amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2); amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC2_JT); } else { @@ -10104,6 +10130,21 @@ static u32 gfx_v10_0_get_cu_active_bitmap_per_sh(struct amdgpu_device *adev) return cu_active_bitmap; } +/* PS5 harvested-CU unlock. + * 0 = disabled + * 1 = probe only (write then restore, log values) + * 2 = unlock SE0/SH0 only + * 3 = unlock all SE/SH (default) + * 4 = probe only, all SE/SH + * Override on the kernel command line, e.g.: + * amdgpu.ps5_cu_unlock=0 (disable) + * amdgpu.ps5_cu_unlock=1 (probe) + */ +static int ps5_cu_unlock = 0; +module_param(ps5_cu_unlock, int, 0444); +MODULE_PARM_DESC(ps5_cu_unlock, + "PS5 harvested-CU unlock (0=off (default), 1=probe, 2=SE0/SH0, 3=all, 4=probe-all)"); + static int gfx_v10_0_get_cu_info(struct amdgpu_device *adev, struct amdgpu_cu_info *cu_info) { @@ -10117,6 +10158,43 @@ static int gfx_v10_0_get_cu_info(struct amdgpu_device *adev, amdgpu_gfx_parse_disable_cu(adev, disable_masks, 4, 2); mutex_lock(&adev->grbm_idx_mutex); + /* PS5: unlock harvested CUs. CC alone updates enumeration but SPI + * still dispatches only to enabled WGPs; both writes are required + * (verified empirically on BC-250). */ + if (ps5_cu_unlock > 0) { + int ps5_se, ps5_sh; + for (ps5_se = 0; ps5_se < adev->gfx.config.max_shader_engines; ps5_se++) { + for (ps5_sh = 0; ps5_sh < adev->gfx.config.max_sh_per_se; ps5_sh++) { + u32 ps5_cc_orig, ps5_cc_after, ps5_spi_orig, ps5_spi_after; + if (ps5_cu_unlock == 2 && (ps5_se > 0 || ps5_sh > 0)) + continue; + gfx_v10_0_select_se_sh(adev, ps5_se, ps5_sh, 0xffffffff, 0); + ps5_cc_orig = RREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG); + WREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG, 0); + ps5_cc_after = RREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG); + ps5_spi_orig = RREG32_SOC15(GC, 0, mmSPI_PG_ENABLE_STATIC_WGP_MASK); + WREG32_SOC15(GC, 0, mmSPI_PG_ENABLE_STATIC_WGP_MASK, 0x1f); + ps5_spi_after = RREG32_SOC15(GC, 0, mmSPI_PG_ENABLE_STATIC_WGP_MASK); + WREG32_SOC15(GC, 0, mmRLC_PG_ALWAYS_ON_WGP_MASK, 0x1f); + if (ps5_cu_unlock == 1 || ps5_cu_unlock == 4) { + WREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG, ps5_cc_orig); + WREG32_SOC15(GC, 0, mmSPI_PG_ENABLE_STATIC_WGP_MASK, ps5_spi_orig); + dev_info(adev->dev, + "ps5-40cu-probe: se=%d sh=%d CC=0x%08x->0x%08x SPI=0x%08x->0x%08x (restored)", + ps5_se, ps5_sh, + ps5_cc_orig, ps5_cc_after, + ps5_spi_orig, ps5_spi_after); + } else { + dev_info(adev->dev, + "ps5-40cu-enable: mode=%d se=%d sh=%d CC=0x%08x->0x%08x SPI=0x%08x->0x%08x", + ps5_cu_unlock, ps5_se, ps5_sh, + ps5_cc_orig, ps5_cc_after, + ps5_spi_orig, ps5_spi_after); + } + } + } + gfx_v10_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff, 0); + } for (i = 0; i < adev->gfx.config.max_shader_engines; i++) { for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) { bitmap = i * adev->gfx.config.max_sh_per_se + j; diff --git a/drivers/gpu/drm/amd/amdgpu/nv.c b/drivers/gpu/drm/amd/amdgpu/nv.c index f17c3839aea1..a561038f3f79 100644 --- a/drivers/gpu/drm/amd/amdgpu/nv.c +++ b/drivers/gpu/drm/amd/amdgpu/nv.c @@ -868,6 +868,10 @@ static int nv_common_early_init(struct amdgpu_ip_block *ip_block) adev->cg_flags = 0; adev->pg_flags = 0; adev->external_rev_id = adev->rev_id + 0x82; +#ifdef CONFIG_X86_PS5 + /* Hardcode bc250's id. Remove when mesa's patch is widely available. */ + adev->external_rev_id = 0x84; +#endif break; case IP_VERSION(10, 3, 6): adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG | diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c index e3a035c9fece..6eb67dd7b52c 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c @@ -1362,6 +1362,12 @@ static int sdma_v5_0_early_init(struct amdgpu_ip_block *ip_block) struct amdgpu_device *adev = ip_block->adev; int r; +#ifdef CONFIG_X86_PS5 + /* Reset SDMA to prevent ring test failures after reload. */ + sdma_v5_0_soft_reset_engine(adev, 0); + sdma_v5_0_soft_reset_engine(adev, 1); +#endif + r = sdma_v5_0_init_microcode(adev); if (r) return r; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 0aee65503642..3ae712111a93 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -80,6 +80,10 @@ #include #include +#ifdef CONFIG_X86_PS5 +#include +#endif + #include #include #include @@ -3007,7 +3011,10 @@ static int dm_hw_init(struct amdgpu_ip_block *ip_block) r = amdgpu_dm_init(adev); if (r) return r; +#ifndef CONFIG_X86_PS5 + /* HPD is not supported. */ amdgpu_dm_hpd_init(adev); +#endif r = dm_oem_i2c_hw_init(adev); if (r) @@ -3028,7 +3035,10 @@ static int dm_hw_fini(struct amdgpu_ip_block *ip_block) { struct amdgpu_device *adev = ip_block->adev; +#ifndef CONFIG_X86_PS5 + /* HPD is not supported. */ amdgpu_dm_hpd_fini(adev); +#endif amdgpu_dm_irq_fini(adev); amdgpu_dm_fini(adev); @@ -6809,6 +6819,12 @@ static void fill_stream_properties_from_drm_display_mode( stream->output_color_space = get_output_color_space(timing_out, connector_state); stream->content_type = get_output_content_type(connector_state); + +#ifdef CONFIG_X86_PS5 + /* Hardcode RGB888. */ + // timing_out->pixel_encoding = PIXEL_ENCODING_RGB; + // timing_out->display_color_depth = COLOR_DEPTH_888; +#endif } static void fill_audio_info(struct audio_info *audio_info, @@ -8198,6 +8214,11 @@ enum drm_mode_status amdgpu_dm_connector_mode_valid(struct drm_connector *connec */ struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); +#ifdef CONFIG_X86_PS5 + if (!isHdmiModeValid(mode, amdgpu_force_1080p)) + return MODE_ERROR; +#endif + if ((mode->flags & DRM_MODE_FLAG_INTERLACE) || (mode->flags & DRM_MODE_FLAG_DBLSCAN)) return result; @@ -10889,12 +10910,58 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) drm_atomic_helper_update_legacy_modeset_state(dev, state); drm_dp_mst_atomic_wait_for_dependencies(state); +#ifdef CONFIG_X86_PS5 + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + + if ((new_crtc_state->active && + (!old_crtc_state->active || + drm_atomic_crtc_needs_modeset(new_crtc_state))) || + (old_crtc_state->active && + (!new_crtc_state->active || + drm_atomic_crtc_needs_modeset(new_crtc_state)))) { + if (dm_new_crtc_state->stream && dc_is_dp_signal(dm_new_crtc_state->stream->signal)) { + sceHdmiInitVideoConfig(); + } + } + } +#endif + dm_state = dm_atomic_get_new_state(state); if (dm_state && dm_state->context) { dc_state = dm_state->context; amdgpu_dm_commit_streams(state, dc_state); } +#ifdef CONFIG_X86_PS5 + for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, + new_crtc_state, i) { + dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); + dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); + + if (new_crtc_state->active && + (!old_crtc_state->active || + drm_atomic_crtc_needs_modeset(new_crtc_state))) { + if (dm_new_crtc_state->stream && dc_is_dp_signal(dm_new_crtc_state->stream->signal)) { + struct dc_stream_state *stream = dm_new_crtc_state->stream; + int channels = 0; + + for (i = 0; i < stream->audio_info.mode_count; i++) { + if (stream->audio_info.modes[i].channel_count > channels) + channels = stream->audio_info.modes[i].channel_count; + } + + sceHdmiSetVideoConfig(&new_crtc_state->mode); + sceHdmiDeviceSetVideoMute(0); + sceHdmiSetAudioConfig(channels); + sceHdmiSetAudioMute(0); + } + } + } +#endif + amdgpu_dm_update_hdcp(state); /* Handle connector state changes */ diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index 896f4719cf7b..0eb818421a50 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -204,6 +204,7 @@ enum dce_version resource_parse_asic_id(struct hw_asic_id asic_id) asic_id.chip_id == DEVICE_ID_NV_13FA || asic_id.chip_id == DEVICE_ID_NV_13FB || asic_id.chip_id == DEVICE_ID_NV_13FC || + asic_id.chip_id == DEVICE_ID_NV_13DA || asic_id.chip_id == DEVICE_ID_NV_13DB) { dc_version = DCN_VERSION_2_01; break; diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c index 9459e8f28338..063e4a4eefdd 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_link_encoder.c @@ -98,8 +98,11 @@ static const struct link_encoder_funcs dcn201_link_enc_funcs = { .disable_hpd = dcn10_link_encoder_disable_hpd, .is_dig_enabled = dcn10_is_dig_enabled, .destroy = dcn10_link_encoder_destroy, +#ifndef CONFIG_X86_PS5 + /* Ignore this to prevent blackscreen. */ .fec_set_enable = enc2_fec_set_enable, .fec_set_ready = enc2_fec_set_ready, +#endif .get_dig_frontend = dcn10_get_dig_frontend, .fec_is_active = enc2_fec_is_active, .is_in_alt_mode = dcn201_link_encoder_is_in_alt_mode, diff --git a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c index 13e14aad3daa..edc4b9ccfea4 100644 --- a/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c +++ b/drivers/gpu/drm/amd/display/dc/dio/dcn10/dcn10_link_encoder.c @@ -986,6 +986,11 @@ void dcn10_link_encoder_enable_dp_output( struct bp_transmitter_control cntl = { 0 }; enum bp_result result; +#ifdef CONFIG_X86_PS5 + /* Ignore this to prevent link training failure. */ + return; +#endif + /* Enable the PHY */ /* number_of_lanes is used for pixel clock adjust, @@ -1065,6 +1070,11 @@ void dcn10_link_encoder_disable_output( struct bp_transmitter_control cntl = { 0 }; enum bp_result result; +#ifdef CONFIG_X86_PS5 + /* Ignore this to prevent link training failure. */ + return; +#endif + if (enc->funcs->is_dig_enabled && !enc->funcs->is_dig_enabled(enc)) { /* OF_SKIP_POWER_DOWN_INACTIVE_ENCODER */ /*in DP_Alt_No_Connect case, we turn off the dig already, diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c index 699a756bbc40..4a9d4ba6abf4 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dce110/dce110_hwseq.c @@ -1753,6 +1753,11 @@ static void power_down_clock_sources(struct dc *dc) { int i; +#ifdef CONFIG_X86_PS5 + /* Ignore this to prevent blackscreen. */ + return; +#endif + if (dc->res_pool->dp_clock_source->funcs->cs_power_down( dc->res_pool->dp_clock_source) == false) dm_error("Failed to power down pll! (dp clk src)\n"); diff --git a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c index cdc7587cf0b6..7a7b17fe5a89 100644 --- a/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c +++ b/drivers/gpu/drm/amd/display/dc/link/protocols/link_dp_capability.c @@ -1015,6 +1015,12 @@ bool link_decide_link_settings(struct dc_stream_state *stream, decide_dp_link_settings(link, link_setting, req_bw); } +#ifdef CONFIG_X86_PS5 + /* Hardcode HBR3x4 link setting. */ + link_setting->link_rate = LINK_RATE_HIGH3; + link_setting->lane_count = LANE_COUNT_FOUR; +#endif + return link_setting->lane_count != LANE_COUNT_UNKNOWN && link_setting->link_rate != LINK_RATE_UNKNOWN; } @@ -1455,6 +1461,8 @@ void dpcd_set_source_specific_data(struct dc_link *link) (uint8_t *)(&amd_device_id), sizeof(amd_device_id)); +#ifndef CONFIG_X86_PS5 + /* Ignore unsupported dpcd address. */ if (link->ctx->dce_version >= DCN_VERSION_2_0 && link->dc->caps.min_horizontal_blanking_period != 0) { @@ -1464,6 +1472,7 @@ void dpcd_set_source_specific_data(struct dc_link *link) DP_SOURCE_MINIMUM_HBLANK_SUPPORTED, (uint8_t *)(&hblank_size), sizeof(hblank_size)); } +#endif DC_TRACE_LEVEL_MESSAGE(DAL_TRACE_LEVEL_INFORMATION, WPP_BIT_FLAG_DC_DETECTION_DP_CAPS, "result=%u link_index=%u enum dce_version=%d DPCD=0x%04X min_hblank=%u branch_dev_id=0x%x branch_dev_name='%c%c%c%c%c%c'", diff --git a/drivers/gpu/drm/amd/display/include/dal_asic_id.h b/drivers/gpu/drm/amd/display/include/dal_asic_id.h index 8aea50aa9533..8b647bd95691 100644 --- a/drivers/gpu/drm/amd/display/include/dal_asic_id.h +++ b/drivers/gpu/drm/amd/display/include/dal_asic_id.h @@ -217,6 +217,7 @@ enum { #define DEVICE_ID_NV_13FA 0x13FA #define DEVICE_ID_NV_13FB 0x13FB #define DEVICE_ID_NV_13FC 0x13FC +#define DEVICE_ID_NV_13DA 0x13DA #define DEVICE_ID_NV_13DB 0x13DB #define FAMILY_VGH 144 #define DEVICE_ID_VGH_163F 0x163F diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ff432ac6b569..2efeaec03ea1 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2219,6 +2219,10 @@ static void connector_bad_edid(struct drm_connector *connector, edid_block_dump(KERN_DEBUG, edid + i, i); } +#ifdef CONFIG_X86_PS5 +extern struct drm_edid *real_edid; +#endif + /* Get override or firmware EDID */ static const struct drm_edid *drm_edid_override_get(struct drm_connector *connector) { @@ -2234,6 +2238,11 @@ static const struct drm_edid *drm_edid_override_get(struct drm_connector *connec if (!override) override = drm_edid_load_firmware(connector); +#ifdef CONFIG_X86_PS5 + if (IS_ERR(override) && real_edid) + override = drm_edid_dup(real_edid); +#endif + return IS_ERR(override) ? NULL : override; } diff --git a/drivers/hwmon/k10temp.c b/drivers/hwmon/k10temp.c index a5d8f45b7881..3c7b76af13e4 100644 --- a/drivers/hwmon/k10temp.c +++ b/drivers/hwmon/k10temp.c @@ -476,6 +476,7 @@ static int k10temp_probe(struct pci_dev *pdev, const struct pci_device_id *id) break; case 0x31: /* Zen2 Threadripper */ case 0x47: /* Cyan Skillfish */ + case 0x48: /* PS5 */ case 0x60: /* Renoir */ case 0x68: /* Lucienne */ case 0x71: /* Zen2 */ diff --git a/drivers/iommu/amd/init.c b/drivers/iommu/amd/init.c index f3fd7f39efb4..7dd1b138ae78 100644 --- a/drivers/iommu/amd/init.c +++ b/drivers/iommu/amd/init.c @@ -3093,6 +3093,8 @@ static void __init free_iommu_resources(void) free_pci_segments(); } +#ifndef CONFIG_X86_PS5 + /* SB IOAPIC is always on this device in AMD systems */ #define IOAPIC_SB_DEVID ((0x00 << 8) | PCI_DEVFN(0x14, 0)) @@ -3145,6 +3147,8 @@ static bool __init check_ioapic_information(void) return ret; } +#endif + static void __init free_dma_resources(void) { amd_iommu_pdom_id_destroy(); @@ -3269,8 +3273,11 @@ static int __init early_amd_iommu_init(void) if (!is_kdump_kernel() || amd_iommu_disabled) disable_iommus(); +#ifndef CONFIG_X86_PS5 + /* IOAPIC is not available. */ if (amd_iommu_irq_remap) amd_iommu_irq_remap = check_ioapic_information(); +#endif if (amd_iommu_irq_remap) { struct amd_iommu_pci_seg *pci_seg; diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index 7b73332a13d9..b92217f5ef0e 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig @@ -471,3 +471,4 @@ config XILINX_GMII2RGMII Ethernet physical media devices and the Gigabit Ethernet controller. endif # PHYLIB +source "drivers/net/phy/mts/Kconfig" diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 3a34917adea7..2f0ec5e17d90 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o obj-$(CONFIG_MAXLINEAR_86110_PHY) += mxl-86110.o obj-y += mediatek/ +obj-$(CONFIG_MTS) += mts/ obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o obj-$(CONFIG_MICREL_PHY) += micrel.o obj-$(CONFIG_MICROCHIP_PHY) += microchip.o diff --git a/drivers/net/phy/mts/Kconfig b/drivers/net/phy/mts/Kconfig new file mode 100644 index 000000000000..94cb839814cb --- /dev/null +++ b/drivers/net/phy/mts/Kconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +config MTS + tristate "MediaTek Star Gigabit Ethernet" + depends on PCI && X86_PS5 + help + Driver for the MediaTek Star based Gigabit Ethernet controller + (104d:9104) found on the PlayStation 5. + + To compile this driver as a module, choose M here. The module + will be called mts. diff --git a/drivers/net/phy/mts/Makefile b/drivers/net/phy/mts/Makefile new file mode 100644 index 000000000000..e01771be845b --- /dev/null +++ b/drivers/net/phy/mts/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only +obj-$(CONFIG_MTS) += mts.o +mts-y := mts_main.o mts_phy.o diff --git a/drivers/net/phy/mts/mts.h b/drivers/net/phy/mts/mts.h new file mode 100644 index 000000000000..e846b6b0edbc --- /dev/null +++ b/drivers/net/phy/mts/mts.h @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PlayStation 5 Gigabit Ethernet driver + * + * Based on the MediaTek Star Ethernet MAC (mtk_star_emac). + */ + +#ifndef _MTS_H +#define _MTS_H + +#include +#include +#include +#include +#include +#include + +struct pci_dev; +struct sk_buff; + +#define GBE_REG_SMI 0x00 +#define GBE_REG_LINK 0x04 +#define GBE_REG_CLK_CTRL 0x08 +#define GBE_REG_CTRL 0x0c +#define GBE_REG_MODE 0x10 +#define GBE_REG_MAC_HI 0x14 +#define GBE_REG_MAC_LO 0x18 +#define GBE_REG_RXBUF 0x30 +#define GBE_REG_TX_DMA_CTRL 0x34 +#define GBE_REG_RX_DMA_CTRL 0x38 +#define GBE_REG_TX_RING_CUR 0x3c +#define GBE_REG_RX_RING_CUR 0x40 +#define GBE_REG_TX_RING_BASE 0x44 +#define GBE_REG_RX_RING_BASE 0x48 +#define GBE_REG_ISR 0x50 +#define GBE_REG_IER 0x54 +#define GBE_REG_SERDES 0x74 +#define GBE_REG_RX_PCODE 0x78 +#define GBE_REG_TXKICK 0x9c +#define GBE_REG_RESET 0xac +#define GBE_REG_TX_EN 0x1b8 +#define GBE_REG_FILT_CTRL 0x1c4 +#define GBE_REG_FILT_DATA 0x1c8 +#define GBE_REG_RX_EN 0x1d4 +#define GBE_REG_COAL 0x204 + +#define GBE_PCS_BASE 0x4000 + +#define GBE_CLK_ENABLE 0x7597c00 + +#define GBE_SERDES_1G 0x303277 +#define GBE_SERDES_OTHER 0x304277 + +#define GBE_ISR_LINK BIT(2) +#define GBE_ISR_TX_DONE BIT(7) +#define GBE_ISR_RX_DONE BIT(6) +#define GBE_ISR_ERRORS 0x7be600 +#define GBE_ISR_LSO_RECOVER 0x500000 + +#define GBE_ST_LSO_RECOVER 0 + +#define GBE_ERR_LSO_FIFO 0x200000 +#define GBE_ERR_LSO_PROTO 0x80000 +#define GBE_ERR_RX_AXI 0x20000 +#define GBE_ERR_IP_CKSUM 0x8000 +#define GBE_ERR_TCP_CKSUM 0x4000 +#define GBE_ERR_UDP_CKSUM 0x2000 +#define GBE_ERR_RX_PCODE 0x400 + +#define GBE_COAL_VAL 0x10001388 + +/* this chip has no intx pin and its msi sometimes never fires (cold boot). when + * we detect that, the link_poll work becomes the only way to service the rings, + * so it polls this often (ms) instead of once a second to stay responsive. */ +#define GBE_POLL_FALLBACK_MS 10 + +/* excludes bit2 (LINK) - polling link state avoids IRQ storm from autoneg pulses */ +#define GBE_IER_MASK 0x5014fa + +#define GBE_DMA_STOP BIT(1) +#define GBE_DMA_KICK BIT(2) + +struct gbe_desc { + __le32 flags; + __le32 buf_addr; + __le32 word2; + __le32 word3; +}; + +#define GBE_DESC_DONE BIT(31) +#define GBE_DESC_WRAP BIT(30) +#define GBE_DESC_SOP BIT(29) +#define GBE_DESC_EOP BIT(28) +#define GBE_DESC_LEN_MASK 0xffff +#define GBE_DESC_RX_LEN 0x600 +#define GBE_DESC_RX_LEN_MASK 0x7ff +/* idle TX descriptor word2 - chip treats anything >= 0xffff0000 as free */ +#define GBE_DESC_W2_ARM 0xffff0000 +/* active TX descriptor word2 */ +#define GBE_DESC_W2_TX 0x4 + +#define GBE_RING_SIZE 256 +#define GBE_DESC_RING_BYTES (GBE_RING_SIZE * sizeof(struct gbe_desc)) +#define GBE_RX_BUF_LEN 1536 + +#define GBE_TX_SCRATCH_SIZE 0xa0000 +#define GBE_RX_POOL_SIZE (GBE_RING_SIZE * GBE_DESC_RX_LEN) + +struct gbe_priv { + struct net_device *netdev; + struct pci_dev *pdev; + void __iomem *base; + /* PCS/SerDes regs live in Salina Glue (104d:9107) BAR4, not BAR0 */ + void __iomem *glue_base; + struct pci_dev *glue_pdev; + + /* tx goes through a bounce scratch region, the chip wants contiguous buffers */ + struct gbe_desc *tx_ring; + dma_addr_t tx_ring_dma; + void *tx_scratch; + dma_addr_t tx_scratch_dma; + unsigned int tx_scratch_off; + unsigned int tx_head; + unsigned int tx_tail; + + /* rx just has the chip dma straight into a slotted pool */ + struct gbe_desc *rx_ring; + dma_addr_t rx_ring_dma; + void *rx_pool; + dma_addr_t rx_pool_dma; + unsigned int rx_head; + + struct napi_struct napi; + int irq; + int link_up; + unsigned long state; + struct delayed_work link_poll; + spinlock_t lock; + + /* debug counters, dumped every now and then by the link poll work */ + u32 cnt_irq; + u32 cnt_irq_link; + u32 cnt_irq_tx; + u32 cnt_irq_rx; + u32 cnt_irq_err; + u32 cnt_irq_lso; + u32 cnt_tx_pkts; + u32 cnt_tx_busy; + u32 cnt_tx_drop_big; + u32 cnt_tx_completed; + u32 cnt_rx_pkts; + u32 cnt_rx_bcast; + u32 cnt_rx_mcast; + u32 cnt_rx_bad_len; + u32 cnt_rx_nomem; + u32 cnt_lso_recover; + u32 cnt_link_up; + u32 cnt_link_down; + unsigned int poll_tick; + /* used by link_poll_work to detect frozen IRQ delivery on cold boot */ + u32 irq_watchdog; +}; + +static inline u32 gbe_rd(struct gbe_priv *p, u32 reg) +{ + return readl(p->base + reg); +} + +static inline void gbe_wr(struct gbe_priv *p, u32 reg, u32 val) +{ + writel(val, p->base + reg); +} + +static inline void gbe_set(struct gbe_priv *p, u32 reg, u32 bits) +{ + gbe_wr(p, reg, gbe_rd(p, reg) | bits); +} + +static inline void gbe_clr(struct gbe_priv *p, u32 reg, u32 bits) +{ + gbe_wr(p, reg, gbe_rd(p, reg) & ~bits); +} + +int gbe_phy_init(struct gbe_priv *p); + +#endif /* _MTS_H */ diff --git a/drivers/net/phy/mts/mts_main.c b/drivers/net/phy/mts/mts_main.c new file mode 100644 index 000000000000..4250a25d7260 --- /dev/null +++ b/drivers/net/phy/mts/mts_main.c @@ -0,0 +1,823 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PlayStation 5 Gigabit Ethernet driver + * + * Based on the MediaTek Star Ethernet MAC (mtk_star_emac). + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mts.h" + +#define PCI_DEVICE_ID_GBE 0x9104 +#define PCI_DEVICE_ID_SPCIE 0x9107 + +static void gbe_write_mac(struct gbe_priv *p, const u8 *addr) +{ + gbe_wr(p, GBE_REG_MAC_HI, (addr[0] << 8) | addr[1]); + gbe_wr(p, GBE_REG_MAC_LO, + (addr[2] << 24) | (addr[3] << 16) | (addr[4] << 8) | addr[5]); +} + +/* the glue is a seperate pci function, grab it too :) */ +static int gbe_glue_map(struct gbe_priv *p) +{ + struct pci_dev *glue; + + glue = pci_get_device(PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_SPCIE, NULL); + if (!glue) + return -ENODEV; + + if (!(pci_resource_flags(glue, 4) & IORESOURCE_MEM)) { + pci_dev_put(glue); + return -ENODEV; + } + + p->glue_base = ioremap(pci_resource_start(glue, 4), + pci_resource_len(glue, 4)); + if (!p->glue_base) { + pci_dev_put(glue); + return -ENOMEM; + } + + p->glue_pdev = glue; + return 0; +} + +static void gbe_glue_unmap(struct gbe_priv *p) +{ + if (p->glue_base) { + iounmap(p->glue_base); + p->glue_base = NULL; + } + if (p->glue_pdev) { + pci_dev_put(p->glue_pdev); + p->glue_pdev = NULL; + } +} + +/* MAC address lives at offset 0x3000 in Salina Glue BAR4 scratchpad */ +static int gbe_read_glue_mac(struct gbe_priv *p, u8 *addr) +{ + int i; + + if (!p->glue_base) + return -ENODEV; + + for (i = 0; i < ETH_ALEN; i++) + addr[i] = readb(p->glue_base + 0x3000 + i); + return 0; +} + +/* writing 9 to the reset reg pulses the whole MAC, needs a short settle */ +static void gbe_reset(struct gbe_priv *p) +{ + gbe_wr(p, GBE_REG_RESET, 9); + usleep_range(680, 1000); +} + +/* mark every tx slot done+free so the chip leaves em alone till we arm one */ +static void gbe_init_tx_ring(struct gbe_priv *p) +{ + int i; + + for (i = 0; i < GBE_RING_SIZE; i++) { + p->tx_ring[i].flags = cpu_to_le32(GBE_DESC_DONE | + (i == GBE_RING_SIZE - 1 ? GBE_DESC_WRAP : 0)); + p->tx_ring[i].buf_addr = 0; + p->tx_ring[i].word2 = cpu_to_le32(GBE_DESC_W2_ARM); + p->tx_ring[i].word3 = 0; + } + p->tx_head = p->tx_tail = 0; + p->tx_scratch_off = 0; +} + +/* point each rx slot at its pool buffer and give it back to teh chip */ +static void gbe_rx_fill(struct gbe_priv *p) +{ + int i; + + for (i = 0; i < GBE_RING_SIZE; i++) { + p->rx_ring[i].buf_addr = cpu_to_le32(p->rx_pool_dma + + i * GBE_DESC_RX_LEN); + p->rx_ring[i].word2 = 0; + p->rx_ring[i].word3 = 0; + dma_wmb(); + p->rx_ring[i].flags = cpu_to_le32(GBE_DESC_RX_LEN | + (i == GBE_RING_SIZE - 1 ? GBE_DESC_WRAP : 0)); + } + p->rx_head = 0; +} + +static void gbe_init_rings_hw(struct gbe_priv *p) +{ + gbe_init_tx_ring(p); + + wmb(); + + gbe_wr(p, GBE_REG_TX_RING_BASE, p->tx_ring_dma); + gbe_wr(p, GBE_REG_TX_RING_CUR, p->tx_ring_dma); + gbe_wr(p, GBE_REG_RX_RING_BASE, p->rx_ring_dma); + gbe_wr(p, GBE_REG_RX_RING_CUR, p->rx_ring_dma); + + /* toggle bit6 to clear any stale LSO cause latched from before init */ + gbe_clr(p, GBE_REG_TXKICK, BIT(6)); + gbe_set(p, GBE_REG_TXKICK, BIT(6)); + + gbe_set(p, GBE_REG_TX_DMA_CTRL, BIT(0)); + gbe_set(p, GBE_REG_RX_DMA_CTRL, BIT(0)); + gbe_wr(p, GBE_REG_IER, GBE_IER_MASK); +} + +/* tell both dma engines to stop, then jsut spin till the bit clears */ +static void gbe_stop_dma(struct gbe_priv *p) +{ + int i; + + gbe_wr(p, GBE_REG_IER, 0); + + gbe_set(p, GBE_REG_TX_DMA_CTRL, GBE_DMA_STOP); + for (i = 0; i < 1000000 && + (gbe_rd(p, GBE_REG_TX_DMA_CTRL) & GBE_DMA_STOP); i++) + udelay(1); + + gbe_set(p, GBE_REG_RX_DMA_CTRL, GBE_DMA_STOP); + for (i = 0; i < 1000000 && + (gbe_rd(p, GBE_REG_RX_DMA_CTRL) & GBE_DMA_STOP); i++) + udelay(1); +} + +/* full bringup: reset, clocks, phy, then the magic mode/serdes vaules */ +static void gbe_init_hw(struct gbe_priv *p) +{ + gbe_reset(p); + gbe_set(p, GBE_REG_CLK_CTRL, GBE_CLK_ENABLE); + gbe_phy_init(p); + gbe_clr(p, GBE_REG_CTRL, BIT(7)); + gbe_wr(p, GBE_REG_SERDES, GBE_SERDES_1G); + gbe_wr(p, GBE_REG_MODE, (gbe_rd(p, GBE_REG_MODE) & 0xffffff6e) | 0x81); + gbe_wr(p, GBE_REG_RXBUF, 0x10100); + gbe_write_mac(p, p->netdev->dev_addr); + gbe_wr(p, GBE_REG_COAL, GBE_COAL_VAL); +} + +/* the two rings + tx bounce scratch + rx pool, all dma coherent */ +static int gbe_alloc_rings(struct gbe_priv *p) +{ + p->tx_ring = dma_alloc_coherent(&p->pdev->dev, GBE_DESC_RING_BYTES, + &p->tx_ring_dma, GFP_KERNEL); + if (!p->tx_ring) + return -ENOMEM; + + p->rx_ring = dma_alloc_coherent(&p->pdev->dev, GBE_DESC_RING_BYTES, + &p->rx_ring_dma, GFP_KERNEL); + if (!p->rx_ring) + goto err_rx; + + p->tx_scratch = dma_alloc_coherent(&p->pdev->dev, GBE_TX_SCRATCH_SIZE, + &p->tx_scratch_dma, GFP_KERNEL); + if (!p->tx_scratch) + goto err_scratch; + + p->rx_pool = dma_alloc_coherent(&p->pdev->dev, GBE_RX_POOL_SIZE, + &p->rx_pool_dma, GFP_KERNEL); + if (!p->rx_pool) + goto err_pool; + + return 0; + +err_pool: + dma_free_coherent(&p->pdev->dev, GBE_TX_SCRATCH_SIZE, + p->tx_scratch, p->tx_scratch_dma); +err_scratch: + dma_free_coherent(&p->pdev->dev, GBE_DESC_RING_BYTES, + p->rx_ring, p->rx_ring_dma); +err_rx: + dma_free_coherent(&p->pdev->dev, GBE_DESC_RING_BYTES, + p->tx_ring, p->tx_ring_dma); + return -ENOMEM; +} + +static void gbe_free_rings(struct gbe_priv *p) +{ + if (p->tx_ring) + dma_free_coherent(&p->pdev->dev, GBE_DESC_RING_BYTES, + p->tx_ring, p->tx_ring_dma); + if (p->rx_ring) + dma_free_coherent(&p->pdev->dev, GBE_DESC_RING_BYTES, + p->rx_ring, p->rx_ring_dma); + if (p->tx_scratch) + dma_free_coherent(&p->pdev->dev, GBE_TX_SCRATCH_SIZE, + p->tx_scratch, p->tx_scratch_dma); + if (p->rx_pool) + dma_free_coherent(&p->pdev->dev, GBE_RX_POOL_SIZE, + p->rx_pool, p->rx_pool_dma); +} + +/* clean up the tx descriptors the chip finished, wake the queue if we stopped it */ +static void gbe_tx_complete(struct gbe_priv *p) +{ + unsigned int tail = p->tx_tail; + + while (tail != p->tx_head) { + struct gbe_desc *d = &p->tx_ring[tail]; + u32 flags = le32_to_cpu(d->flags); + u32 w2 = le32_to_cpu(d->word2); + + if (!(flags & GBE_DESC_DONE)) + break; + + /* chip reuses word2 < 0xffff0000 as ownership sentinel on ring wrap */ + if (w2 >= 0xffff0000) + break; + + /* re-arm it so the slot reads free next time round the ring */ + d->word2 = cpu_to_le32(w2 | 0xffff0000); + + p->cnt_tx_completed++; + tail = (tail + 1) % GBE_RING_SIZE; + } + p->tx_tail = tail; + + if (netif_queue_stopped(p->netdev)) + netif_wake_queue(p->netdev); +} + +/* grab whatever rx slots are done up to budget, copy em out and re-arm */ +static int gbe_rx_poll(struct gbe_priv *p, int budget) +{ + struct net_device *dev = p->netdev; + unsigned int i = p->rx_head; + int done = 0; + + while (done < budget && + (le32_to_cpu(p->rx_ring[i].flags) & GBE_DESC_DONE)) { + u32 flags = le32_to_cpu(p->rx_ring[i].flags); + u32 len = flags & GBE_DESC_RX_LEN_MASK; + + netdev_dbg(dev, "rx[%u] len=%u flags=%#x w2=%#x\n", i, len, + flags, le32_to_cpu(p->rx_ring[i].word2)); + + if (len >= ETH_ZLEN && len <= GBE_DESC_RX_LEN) { + struct sk_buff *skb; + const u8 *src = (const u8 *)p->rx_pool + + i * GBE_DESC_RX_LEN; + + p->cnt_rx_pkts++; + if (is_broadcast_ether_addr(src)) + p->cnt_rx_bcast++; + else if (is_multicast_ether_addr(src)) + p->cnt_rx_mcast++; + + skb = netdev_alloc_skb_ip_align(dev, len); + if (skb) { + skb_put_data(skb, src, len); + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->stats.rx_packets++; + dev->stats.rx_bytes += len; + } else { + p->cnt_rx_nomem++; + dev->stats.rx_dropped++; + } + } else { + p->cnt_rx_bad_len++; + dev->stats.rx_errors++; + } + + /* hand the slot back to the chip */ + p->rx_ring[i].word2 = 0; + p->rx_ring[i].word3 = 0; + dma_wmb(); + p->rx_ring[i].flags = cpu_to_le32(GBE_DESC_RX_LEN | + (i == GBE_RING_SIZE - 1 ? GBE_DESC_WRAP : 0)); + + done++; + i = (i + 1) % GBE_RING_SIZE; + } + p->rx_head = i; + + if (done) + gbe_set(p, GBE_REG_RX_DMA_CTRL, GBE_DMA_KICK); + + return done; +} + +static netdev_tx_t gbe_xmit(struct sk_buff *skb, struct net_device *dev) +{ + struct gbe_priv *p = netdev_priv(dev); + unsigned int head, off, aligned; + unsigned int len = skb->len; + unsigned long flags; + + if (len < ETH_ZLEN) + len = ETH_ZLEN; + if (len > GBE_RX_BUF_LEN) { + p->cnt_tx_drop_big++; + dev->stats.tx_dropped++; + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + spin_lock_irqsave(&p->lock, flags); + + /* free up whatever the chip already finished before we go looking for room */ + gbe_tx_complete(p); + + head = p->tx_head; + if (((head + 1) % GBE_RING_SIZE) == p->tx_tail) { + p->cnt_tx_busy++; + netif_stop_queue(dev); + spin_unlock_irqrestore(&p->lock, flags); + return NETDEV_TX_BUSY; + } + + p->cnt_tx_pkts++; + + /* wrap scratch offset if packet doesn't fit at the end */ + aligned = (len + 0x7f) & ~0x7fu; + off = p->tx_scratch_off; + if (off + aligned > GBE_TX_SCRATCH_SIZE) + off = 0; + p->tx_scratch_off = off + aligned; + if (p->tx_scratch_off >= GBE_TX_SCRATCH_SIZE) + p->tx_scratch_off = 0; + + /* copy into the bounce region and zero-pad shrot frames */ + skb_copy_bits(skb, 0, (u8 *)p->tx_scratch + off, skb->len); + if (len > skb->len) + memset((u8 *)p->tx_scratch + off + skb->len, 0, len - skb->len); + + p->tx_ring[head].buf_addr = cpu_to_le32(p->tx_scratch_dma + off); + p->tx_ring[head].word2 = cpu_to_le32(GBE_DESC_W2_TX); + p->tx_ring[head].word3 = 0; + dma_wmb(); + p->tx_ring[head].flags = cpu_to_le32((len & GBE_DESC_LEN_MASK) | + GBE_DESC_SOP | GBE_DESC_EOP | + (head == GBE_RING_SIZE - 1 ? GBE_DESC_WRAP : 0)); + + netdev_dbg(dev, "tx[%u] len=%u off=%#x flags=%#x\n", head, len, + off, le32_to_cpu(p->tx_ring[head].flags)); + + p->tx_head = (head + 1) % GBE_RING_SIZE; + + /* if the ring is filling up clean it again so we dont wedge under load :C */ + if ((p->tx_head + GBE_RING_SIZE - p->tx_tail) % GBE_RING_SIZE > GBE_RING_SIZE / 2) + gbe_tx_complete(p); + + gbe_set(p, GBE_REG_TX_DMA_CTRL, GBE_DMA_KICK); + + dev->stats.tx_packets++; + dev->stats.tx_bytes += len; + + spin_unlock_irqrestore(&p->lock, flags); + dev_consume_skb_any(skb); + return NETDEV_TX_OK; +} + +static int gbe_set_mac_address(struct net_device *dev, void *addr) +{ + struct gbe_priv *p = netdev_priv(dev); + struct sockaddr *sa = addr; + + if (!is_valid_ether_addr(sa->sa_data)) + return -EADDRNOTAVAIL; + + eth_hw_addr_set(dev, sa->sa_data); + gbe_write_mac(p, dev->dev_addr); + return 0; +} + +/* no hw filter wired up yet, just log what got asked for */ +static void gbe_set_rx_mode(struct net_device *dev) +{ + struct gbe_priv *p = netdev_priv(dev); + struct netdev_hw_addr *ha; + int mc_count = 0; + + netdev_for_each_mc_addr(ha, dev) + mc_count++; + + netdev_info(dev, + "rx_mode: flags=%#x %s%s%s%s mc_count=%d\n", + dev->flags, + (dev->flags & IFF_PROMISC) ? "PROMISC " : "", + (dev->flags & IFF_ALLMULTI) ? "ALLMULTI " : "", + (dev->flags & IFF_MULTICAST) ? "MULTICAST " : "", + (dev->flags & IFF_BROADCAST) ? "BROADCAST " : "", + mc_count); + + (void)p; +} + +static void gbe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) +{ + strscpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); +} + +static const struct ethtool_ops gbe_ethtool_ops = { + .get_drvinfo = gbe_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + +/* bit0 of the link reg is carrier, just mirror it into netdev */ +static void gbe_link_change(struct gbe_priv *p) +{ + u32 link_reg = gbe_rd(p, GBE_REG_LINK); + int up = link_reg & BIT(0); + + if (up == p->link_up) + return; + + p->link_up = up; + if (up) { + p->cnt_link_up++; + netif_carrier_on(p->netdev); + netdev_info(p->netdev, "link up (reg=%#x)\n", link_reg); + } else { + p->cnt_link_down++; + netif_carrier_off(p->netdev); + netdev_info(p->netdev, "link down (reg=%#x)\n", link_reg); + } +} + +static void gbe_dump_stats(struct gbe_priv *p) +{ + netdev_dbg(p->netdev, + "stats: irq=%u (link=%u tx=%u rx=%u err=%u lso=%u) " + "tx=%u (busy=%u drop_big=%u done=%u) " + "rx=%u (bcast=%u mcast=%u badlen=%u nomem=%u) " + "link_up=%u link_down=%u lso_recover=%u link_reg=%#x\n", + p->cnt_irq, p->cnt_irq_link, p->cnt_irq_tx, p->cnt_irq_rx, + p->cnt_irq_err, p->cnt_irq_lso, + p->cnt_tx_pkts, p->cnt_tx_busy, p->cnt_tx_drop_big, + p->cnt_tx_completed, + p->cnt_rx_pkts, p->cnt_rx_bcast, p->cnt_rx_mcast, + p->cnt_rx_bad_len, p->cnt_rx_nomem, + p->cnt_link_up, p->cnt_link_down, p->cnt_lso_recover, + gbe_rd(p, GBE_REG_LINK)); +} + +/* link irq is masked off (autoneg pulses storm it lol), so poll it once a sec */ +static void gbe_link_poll_work(struct work_struct *work) +{ + struct gbe_priv *p = container_of(to_delayed_work(work), + struct gbe_priv, link_poll); + unsigned long delay = HZ; + + gbe_link_change(p); + + /* + * on a cold boot the chip sometimes just never fires its first irq and + * napi sits there doing nothing. if the irq count hasnt moved since last + * tick the msi is dead -- kick napi by hand and re-arm the mask. msi is the + * only irq source (no intx pin), so while it stays dead we keep polling fast + * (GBE_POLL_FALLBACK_MS) instead of once a second, or interactive rx lags by + * up to a second. as soon as real irqs start arriving we drop back to HZ. + */ + if (netif_running(p->netdev) && p->cnt_irq == p->irq_watchdog) { + napi_schedule(&p->napi); + gbe_wr(p, GBE_REG_IER, GBE_IER_MASK); + delay = max_t(unsigned long, 1, msecs_to_jiffies(GBE_POLL_FALLBACK_MS)); + } + p->irq_watchdog = p->cnt_irq; + + /* dump stats roughly every 10s regardless of the current poll cadence */ + if (++p->poll_tick >= 10 * HZ / delay) { + gbe_dump_stats(p); + p->poll_tick = 0; + } + + schedule_delayed_work(&p->link_poll, delay); +} + +/* + * the chip latches an lso error and then just sulks, wont tx until the + * ring gets rebuilt. so tear it down and stand it back up, same toggle as init. + */ +static void gbe_lso_recover(struct gbe_priv *p) +{ + p->cnt_lso_recover++; + netdev_warn(p->netdev, "LSO error, rebuilding TX ring (cnt=%u)\n", + p->cnt_lso_recover); + + spin_lock(&p->lock); + netif_stop_queue(p->netdev); + + gbe_clr(p, GBE_REG_TXKICK, BIT(6)); + gbe_set(p, GBE_REG_TXKICK, BIT(6)); + + gbe_init_tx_ring(p); + dma_wmb(); + + gbe_wr(p, GBE_REG_TX_RING_BASE, p->tx_ring_dma); + gbe_wr(p, GBE_REG_TX_RING_CUR, p->tx_ring_dma); + gbe_set(p, GBE_REG_TX_DMA_CTRL, BIT(0)); + + netif_wake_queue(p->netdev); + spin_unlock(&p->lock); +} + +/* napi: do tx, then rx, turn irqs back on once we drop under budget */ +static int gbe_poll(struct napi_struct *napi, int budget) +{ + struct gbe_priv *p = container_of(napi, struct gbe_priv, napi); + int rx_done; + + /* isr flags this when it sees an lso cause, deal with it out of hardirq */ + if (test_and_clear_bit(GBE_ST_LSO_RECOVER, &p->state)) + gbe_lso_recover(p); + + spin_lock(&p->lock); + gbe_tx_complete(p); + gbe_set(p, GBE_REG_TX_DMA_CTRL, GBE_DMA_KICK); + spin_unlock(&p->lock); + + rx_done = gbe_rx_poll(p, budget); + + if (rx_done < budget) { + u32 isr; + + napi_complete_done(napi, rx_done); + gbe_wr(p, GBE_REG_IER, GBE_IER_MASK); + /* chip wont send a fresh msi for stuff that landed while ier was + off, so re-check isr and re-kick or interrupts just freeze. + ACK the causes (W1C) first: otherwise a latched/undelivered + cause (the msi-silent cold-boot case) keeps this condition + permanently true and spins napi at ~30k polls/s, pinning a cpu. */ + isr = gbe_rd(p, GBE_REG_ISR) & GBE_IER_MASK; + if (isr) { + gbe_wr(p, GBE_REG_ISR, isr); + if (napi_schedule_prep(&p->napi)) { + gbe_wr(p, GBE_REG_IER, 0); + __napi_schedule(&p->napi); + } + } + } + return rx_done; +} + +static irqreturn_t gbe_isr(int irq, void *data) +{ + struct gbe_priv *p = data; + u32 status; + + status = gbe_rd(p, GBE_REG_ISR); + if (!status) + return IRQ_NONE; + + /* ack everyhting we just read off */ + gbe_wr(p, GBE_REG_ISR, status); + + p->cnt_irq++; + if (status & GBE_ISR_LINK) + p->cnt_irq_link++; + if (status & GBE_ISR_TX_DONE) + p->cnt_irq_tx++; + if (status & GBE_ISR_RX_DONE) + p->cnt_irq_rx++; + if (status & GBE_ISR_ERRORS) + p->cnt_irq_err++; + if (status & GBE_ISR_LSO_RECOVER) + p->cnt_irq_lso++; + + if (status & GBE_ISR_LINK) + gbe_link_change(p); + + if (status & GBE_ISR_ERRORS) { + u32 err = status & GBE_ISR_ERRORS; + + net_err_ratelimited("%s: HW error %#x%s%s%s%s%s%s%s\n", + netdev_name(p->netdev), err, + err & GBE_ERR_LSO_FIFO ? " lso-fifo-empty" : "", + err & GBE_ERR_LSO_PROTO ? " lso-proto" : "", + err & GBE_ERR_RX_AXI ? " rx-axi" : "", + err & GBE_ERR_IP_CKSUM ? " ip-cksum" : "", + err & GBE_ERR_TCP_CKSUM ? " tcp-cksum" : "", + err & GBE_ERR_UDP_CKSUM ? " udp-cksum" : "", + err & GBE_ERR_RX_PCODE ? " rx-pcode" : ""); + p->netdev->stats.rx_errors++; + } + + if (status & GBE_ISR_LSO_RECOVER) + set_bit(GBE_ST_LSO_RECOVER, &p->state); + + /* mask irqs and let napi do the ring work out of hardirq */ + if (napi_schedule_prep(&p->napi)) { + gbe_wr(p, GBE_REG_IER, 0); + __napi_schedule(&p->napi); + } + + return IRQ_HANDLED; +} + +static int gbe_open(struct net_device *dev) +{ + struct gbe_priv *p = netdev_priv(dev); + int ret; + + ret = request_irq(p->irq, gbe_isr, IRQF_SHARED, dev->name, p); + if (ret) + return ret; + + p->link_up = 0; + netif_carrier_off(dev); + + gbe_init_hw(p); + gbe_rx_fill(p); + gbe_init_rings_hw(p); + napi_enable(&p->napi); + netif_start_queue(dev); + + gbe_link_change(p); + schedule_delayed_work(&p->link_poll, HZ); + + return 0; +} + +static int gbe_stop(struct net_device *dev) +{ + struct gbe_priv *p = netdev_priv(dev); + + netif_stop_queue(dev); + netif_carrier_off(dev); + + cancel_delayed_work_sync(&p->link_poll); + + gbe_stop_dma(p); + + free_irq(p->irq, p); + napi_disable(&p->napi); + return 0; +} + +/* stack gave up on us, stop tx dma and stand the ring back up */ +static void gbe_tx_timeout(struct net_device *dev, unsigned int txqueue) +{ + struct gbe_priv *p = netdev_priv(dev); + int i; + + spin_lock_bh(&p->lock); + + gbe_set(p, GBE_REG_TX_DMA_CTRL, GBE_DMA_STOP); + for (i = 0; i < 1000 && (gbe_rd(p, GBE_REG_TX_DMA_CTRL) & GBE_DMA_STOP); i++) + ; + + gbe_init_tx_ring(p); + dma_wmb(); + + gbe_wr(p, GBE_REG_TX_RING_BASE, p->tx_ring_dma); + gbe_wr(p, GBE_REG_TX_RING_CUR, p->tx_ring_dma); + + gbe_clr(p, GBE_REG_TXKICK, BIT(6)); + gbe_set(p, GBE_REG_TXKICK, BIT(6)); + + gbe_set(p, GBE_REG_TX_DMA_CTRL, BIT(0) | GBE_DMA_KICK); + + netif_wake_queue(dev); + spin_unlock_bh(&p->lock); +} + +static const struct net_device_ops gbe_netdev_ops = { + .ndo_open = gbe_open, + .ndo_stop = gbe_stop, + .ndo_start_xmit = gbe_xmit, + .ndo_tx_timeout = gbe_tx_timeout, + .ndo_set_mac_address = gbe_set_mac_address, + .ndo_set_rx_mode = gbe_set_rx_mode, + .ndo_validate_addr = eth_validate_addr, +}; + +static int gbe_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct net_device *netdev; + struct gbe_priv *p; + u8 mac[ETH_ALEN]; + int ret; + + if (!spcie_is_initialized()) + return -EPROBE_DEFER; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + /* GBE registers are in BAR0 */ + ret = pcim_iomap_regions(pdev, BIT(0), KBUILD_MODNAME); + if (ret) + return ret; + + pci_set_master(pdev); + + ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + netdev = alloc_etherdev(sizeof(*p)); + if (!netdev) + return -ENOMEM; + + SET_NETDEV_DEV(netdev, &pdev->dev); + + p = netdev_priv(netdev); + p->netdev = netdev; + p->pdev = pdev; + p->base = pcim_iomap_table(pdev)[0]; + spin_lock_init(&p->lock); + + ret = gbe_alloc_rings(p); + if (ret) + goto err_free; + + ret = gbe_glue_map(p); + if (ret) { + dev_err(&pdev->dev, "probe: glue BAR4 map failed: %d\n", ret); + goto err_rings; + } + + if (gbe_read_glue_mac(p, mac) == 0 && is_valid_ether_addr(mac)) { + eth_hw_addr_set(netdev, mac); + } else { + eth_hw_addr_random(netdev); + dev_warn(&pdev->dev, "no MAC from Salina Glue, using random %pM\n", + netdev->dev_addr); + } + + netdev->netdev_ops = &gbe_netdev_ops; + netdev->ethtool_ops = &gbe_ethtool_ops; + netdev->watchdog_timeo = 5 * HZ; + + netif_napi_add(netdev, &p->napi, gbe_poll); + INIT_DELAYED_WORK(&p->link_poll, gbe_link_poll_work); + + /* device has no intx pin so msi is the only optoin here */ + ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI | PCI_IRQ_INTX); + if (ret < 0) { + dev_err(&pdev->dev, "probe: no IRQ vectors: %d\n", ret); + goto err_napi; + } + p->irq = pci_irq_vector(pdev, 0); + + pci_set_drvdata(pdev, netdev); + + ret = register_netdev(netdev); + if (ret) + goto err_irq; + + netif_carrier_off(netdev); + + dev_info(&pdev->dev, "Salina GBE (chip %#x)\n", spcie_get_chip_id()); + return 0; + +err_irq: + pci_free_irq_vectors(pdev); +err_napi: + netif_napi_del(&p->napi); + gbe_glue_unmap(p); +err_rings: + gbe_free_rings(p); +err_free: + free_netdev(netdev); + return ret; +} + +static void gbe_remove(struct pci_dev *pdev) +{ + struct net_device *netdev = pci_get_drvdata(pdev); + struct gbe_priv *p = netdev_priv(netdev); + + unregister_netdev(netdev); + netif_napi_del(&p->napi); + pci_free_irq_vectors(pdev); + gbe_glue_unmap(p); + gbe_free_rings(p); + free_netdev(netdev); +} + +static const struct pci_device_id gbe_pci_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_GBE) }, + { } +}; +MODULE_DEVICE_TABLE(pci, gbe_pci_tbl); + +static struct pci_driver gbe_driver = { + .name = KBUILD_MODNAME, + .id_table = gbe_pci_tbl, + .probe = gbe_probe, + .remove = gbe_remove, +}; + +module_pci_driver(gbe_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Armandas Kvietkus"); +MODULE_DESCRIPTION("PlayStation 5 Gigabit Ethernet driver"); diff --git a/drivers/net/phy/mts/mts_phy.c b/drivers/net/phy/mts/mts_phy.c new file mode 100644 index 000000000000..91fedcca4589 --- /dev/null +++ b/drivers/net/phy/mts/mts_phy.c @@ -0,0 +1,404 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PlayStation 5 Gigabit Ethernet driver + * + * Based on the MediaTek Star Ethernet MAC (mtk_star_emac). + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include "mts.h" + +/* bit 15 is write-arm on write and done-flag on read */ +#define SMI_ARM BIT(15) +#define SMI_DONE BIT(15) +#define SMI_BUSY BIT(15) +#define SMI_TIMEOUT 10000 + +static int gbe_smi_wait(struct gbe_priv *p) +{ + int i; + + for (i = 0; i < SMI_TIMEOUT; i++) { + if (gbe_rd(p, GBE_REG_SMI) & SMI_DONE) + return 0; + udelay(1); + } + return -ETIMEDOUT; +} + +/* plain clause-22 mii read */ +static u16 gbe_cl22_read(struct gbe_priv *p, u8 reg) +{ + gbe_wr(p, GBE_REG_SMI, SMI_BUSY); + gbe_wr(p, GBE_REG_SMI, ((reg & 0x1f) << 8) | 0x4000); + if (gbe_smi_wait(p)) + return 0; + return gbe_rd(p, GBE_REG_SMI) >> 16; +} + +static void gbe_smi_write(struct gbe_priv *p, u8 reg, u16 val) +{ + gbe_wr(p, GBE_REG_SMI, SMI_BUSY); + gbe_wr(p, GBE_REG_SMI, ((u32)val << 16) | ((reg & 0x1f) << 8) | 0x2000); + gbe_smi_wait(p); +} + +/* clause-45 is indirect, set the adress first then read/write the data */ +static int gbe_cl45_addr(struct gbe_priv *p, u32 sel) +{ + gbe_wr(p, GBE_REG_SMI, SMI_BUSY); + gbe_wr(p, GBE_REG_SMI, (sel & 0xffff0000) | ((sel & 0x1f) << 8) | 0x20); + return gbe_smi_wait(p); +} + +static void gbe_cl45_write(struct gbe_priv *p, u32 sel, u16 val) +{ + if (gbe_cl45_addr(p, sel)) + return; + gbe_wr(p, GBE_REG_SMI, SMI_BUSY); + gbe_wr(p, GBE_REG_SMI, ((u32)val << 16) | ((sel & 0x1f) << 8) | 0x60); + gbe_smi_wait(p); +} + +static u16 gbe_cl45_read(struct gbe_priv *p, u32 sel) +{ + if (gbe_cl45_addr(p, sel)) + return 0; + gbe_wr(p, GBE_REG_SMI, SMI_BUSY); + gbe_wr(p, GBE_REG_SMI, ((sel & 0x1f) << 8) | 0xe0); + if (gbe_smi_wait(p)) + return 0; + return gbe_rd(p, GBE_REG_SMI) >> 16; +} + +/* PCS/SerDes regs live in Salina Glue BAR4 at offset GBE_PCS_BASE */ +static u32 gbe_pcs_rd(struct gbe_priv *p, u32 off) +{ + return readl(p->glue_base + GBE_PCS_BASE + off); +} + +/* maps a measured serdes field to its analog setting */ +static const u8 gbe_cal_lut[64] = { + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, + 0x7b, 0x7a, 0x75, 0x73, 0x70, 0x67, 0x64, 0x62, + 0x57, 0x55, 0x53, 0x51, 0x48, 0x46, 0x44, 0x42, + 0x40, 0x37, 0x35, 0x34, 0x32, 0x31, 0x30, 0x26, + 0x24, 0x23, 0x22, 0x21, 0x20, 0x16, 0x15, 0x14, + 0x13, 0x12, 0x11, 0x10, 0x07, 0x06, 0x05, 0x04, + 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +static u8 gbe_cal_lut_idx(u32 field) +{ + field &= 0x7f; + if (field < 2) + field = 1; + if (field >= 0x40) + field = 0x40; + return gbe_cal_lut[field - 1]; +} + +/* shove a cal value into the high or low byte of a lane reg */ +static void gbe_cal_lane(struct gbe_priv *p, u32 sel, u8 cal, bool high) +{ + u16 cur = gbe_cl45_read(p, sel); + + if (high) + gbe_cl45_write(p, sel, (cur & 0x00ff) | (cal << 8) | 0x8000); + else + gbe_cl45_write(p, sel, (cur & 0xff00) | cal | 0x80); +} + +static u16 gbe_eq_preset(u32 field) +{ + return (min_t(u32, field & 0x3f, 0x3c) + 3) & 0xff; +} + +/* feed the measured serdes status back into the analog tunning regs :) */ +static void gbe_phy_calibrate(struct gbe_priv *p) +{ + u32 v; + + v = gbe_pcs_rd(p, 0x68); + gbe_cl45_write(p, 0x000e001e, (v & 0x3f) << 8); + v = gbe_pcs_rd(p, 0x68); + gbe_cl45_write(p, 0x0115001f, (v >> 6) & 7); + + v = gbe_pcs_rd(p, 0x60); + gbe_cal_lane(p, 0x0174001e, gbe_cal_lut_idx(v), true); + v = gbe_pcs_rd(p, 0x60); + gbe_cal_lane(p, 0x0174001e, gbe_cal_lut_idx(v >> 0x13), false); + v = gbe_pcs_rd(p, 0x64); + gbe_cal_lane(p, 0x0175001e, gbe_cal_lut_idx(v >> 6), true); + v = gbe_pcs_rd(p, 0x64); + gbe_cal_lane(p, 0x0175001e, gbe_cal_lut_idx(v >> 0x19), false); + + v = gbe_pcs_rd(p, 0x5c); + gbe_cl45_write(p, 0x0172001e, + (gbe_cl45_read(p, 0x0172001e) & 0xc0ff) | ((v >> 0xc) & 0x3f00)); + v = gbe_pcs_rd(p, 0x60); + gbe_cl45_write(p, 0x0172001e, + (gbe_cl45_read(p, 0x0172001e) & 0xffc0) | ((v >> 7) & 0x3f)); + v = gbe_pcs_rd(p, 0x60); + gbe_cl45_write(p, 0x0173001e, + (gbe_cl45_read(p, 0x0173001e) & 0xc0ff) | ((v >> 0x12) & 0x3f00)); + v = gbe_pcs_rd(p, 0x64); + gbe_cl45_write(p, 0x0173001e, + (gbe_cl45_read(p, 0x0173001e) & 0xffc0) | ((v >> 0xd) & 0x3f)); + + v = gbe_pcs_rd(p, 0x5c) >> 0x1a; + gbe_cl45_write(p, 0x0012001e, (v << 0xa) | v); + gbe_cl45_write(p, 0x0016001e, (gbe_eq_preset(v) << 0xa) | v); + v = gbe_pcs_rd(p, 0x60) >> 0xd; + gbe_cl45_write(p, 0x0017001e, ((v & 0x3f) << 8) | (v & 0x3f)); + gbe_cl45_write(p, 0x0018001e, (gbe_eq_preset(v) << 8) | (v & 0x3f)); + v = gbe_pcs_rd(p, 0x64); + gbe_cl45_write(p, 0x0019001e, ((v & 0x3f) << 8) | (v & 0x3f)); + gbe_cl45_write(p, 0x0020001e, (gbe_eq_preset(v) << 8) | (v & 0x3f)); + v = gbe_pcs_rd(p, 0x64) >> 0x13; + gbe_cl45_write(p, 0x0021001e, ((v & 0x3f) << 8) | (v & 0x3f)); + gbe_cl45_write(p, 0x0022001e, (gbe_eq_preset(v) << 8) | (v & 0x3f)); + + gbe_cl45_write(p, 0x0096001e, 0x8000); + gbe_cl45_write(p, 0x0037001e, 0x0033); + gbe_cl45_write(p, 0x0039001e, gbe_cl45_read(p, 0x0039001e) & 0xb7ff); + gbe_cl45_write(p, 0x0107001f, gbe_cl45_read(p, 0x0107001f) & 0xefff); + gbe_cl45_write(p, 0x0171001e, gbe_cl45_read(p, 0x0171001e) | 0x0180); + gbe_cl45_write(p, 0x0039001e, gbe_cl45_read(p, 0x0039001e) | 0x2000); + gbe_cl45_write(p, 0x0039001e, gbe_cl45_read(p, 0x0039001e) & 0xdfff); + udelay(50); + gbe_cl45_write(p, 0x0171001e, gbe_cl45_read(p, 0x0171001e) & 0xfe7f); +} + +/* poking a paged register block needs this 3-write form, comes up alot */ +static void gbe_smi_paged(struct gbe_priv *p, u16 a, u16 b, u16 c) +{ + u16 page = gbe_cl22_read(p, 0x1f); + + gbe_smi_write(p, 0x1f, 0x52b5); + gbe_smi_write(p, 0x11, a); + gbe_smi_write(p, 0x12, b); + gbe_smi_write(p, 0x10, c); + gbe_smi_write(p, 0x1f, page); +} + +/* split version of the above for when the final reg 0x10 write is conditional */ +static u16 gbe_paged_begin(struct gbe_priv *p, u16 r11, u16 r12) +{ + u16 page = gbe_cl22_read(p, 0x1f); + + gbe_smi_write(p, 0x1f, 0x52b5); + gbe_smi_write(p, 0x11, r11); + gbe_smi_write(p, 0x12, r12); + return page; +} + +static void gbe_paged_finish(struct gbe_priv *p, u16 r10, u16 page) +{ + gbe_smi_write(p, 0x10, r10); + gbe_smi_write(p, 0x1f, page); +} + +/* + * Analog PHY tuning sequence - pile of magic values that make link work. + * 4-way branch on (chip_id, revision_id), not sure which ps5 rev is which: + * 0x110000 / 0x0100 path A PS5 + * 0x110000 / 0x0200 path C PS5 + * 0x110000 / other path B PS5 (other rev) + * != 0x110000 path D other chip + */ +static void gbe_phy_static_init(struct gbe_priv *p) +{ + u32 chip, rev; + + gbe_cl45_write(p, 0x003e001e, 0xf8f8); + gbe_cl45_write(p, 0x0189001e, 0x0110); + gbe_smi_paged(p, 0xb90a, 0x006f, 0x8f82); + gbe_smi_paged(p, 0xbaef, 0x002e, 0x968c); + + /* page-3 LED config */ + gbe_smi_write(p, 0x1f, 0x0003); + gbe_smi_write(p, 0x1c, 0x0c92); + gbe_smi_write(p, 0x1f, 0x0000); + + gbe_wr(p, GBE_REG_RX_PCODE + 4, 25000000); + + gbe_cl45_write(p, 0x0122001e, 0xffff); + gbe_cl45_write(p, 0x0234001e, 0x0180); + gbe_smi_paged(p, 0x2e00, 0x000e, 0x8fb0); + + gbe_cl45_write(p, 0x0238001e, 0x0120); + if (spcie_get_chip_id() == 0x110000) + gbe_cl45_write(p, 0x0120001e, 0x9014); + gbe_cl45_write(p, 0x0239001e, 0x0117); + gbe_smi_paged(p, 0x0001, 0x0004, 0x96a2); + + gbe_clr(p, GBE_REG_RX_PCODE, BIT(0)); + + gbe_cl45_write(p, 0x003c0007, 0x0000); + gbe_cl45_write(p, 0x0033001e, gbe_cl45_read(p, 0x0033001e) & 0xefff); + gbe_cl45_write(p, 0x0268001f, 0x07f4); + + gbe_smi_paged(p, 0x0004, 0x0000, 0x9686); + gbe_smi_paged(p, 0x0671, 0x0006, 0x8fae); + gbe_smi_paged(p, 0x55a0, 0x0000, 0x83aa); + + gbe_cl45_write(p, 0x0123001e, 0xffff); + + gbe_smi_paged(p, 0x8670, 0x0001, 0x96a6); + gbe_smi_paged(p, 0x0072, 0x0000, 0x96b6); + gbe_smi_paged(p, 0x3210, 0x0000, 0x96b8); + gbe_smi_paged(p, 0x024a, 0x0000, 0x96a8); + + chip = spcie_get_chip_id(); + rev = spcie_get_revision_id(); + netdev_info(p->netdev, "PHY tune: chip=%#x rev=%#x\n", chip, rev); + + if (chip == 0x110000) { + if (rev == 0x0100) { + u16 page; + + netdev_info(p->netdev, "PHY tune: path A (0x110100)\n"); + gbe_smi_paged(p, 0x704d, 0x0000, 0x9698); + gbe_smi_paged(p, 0x314f, 0x0002, 0x969a); + page = gbe_paged_begin(p, 0x4444, 0x0044); + gbe_paged_finish(p, 0x8ecc, page); + } else if (rev == 0x0200) { + u16 page; + + netdev_info(p->netdev, "PHY tune: path C (0x110200)\n"); + gbe_smi_paged(p, 0x5010, 0x0000, 0x96a0); + gbe_smi_paged(p, 0x3028, 0x0000, 0x969e); + gbe_smi_paged(p, 0x504d, 0x0000, 0x9698); + page = gbe_paged_begin(p, 0x194f, 0x0002); + gbe_paged_finish(p, 0x969a, page); + } else { + /* path B: PS5 - this rev skips the final reg 0x10 write */ + netdev_info(p->netdev, "PHY tune: path B (subsys %#x)\n", rev); + gbe_smi_paged(p, 0x5010, 0x0000, 0x96a0); + gbe_smi_paged(p, 0x3028, 0x0000, 0x969e); + gbe_smi_paged(p, 0x504d, 0x0000, 0x9698); + gbe_smi_paged(p, 0x194f, 0x0002, 0x969a); + gbe_cl45_write(p, 0x014a001e, 0xee20); + gbe_cl45_write(p, 0x019b001e, 0x0111); + goto skip_path_d_continuation; + } + } else { + u16 page; + + netdev_info(p->netdev, "PHY tune: path D (chip %#x)\n", chip); + gbe_smi_paged(p, 0x5010, 0x0000, 0x96a0); + gbe_smi_paged(p, 0x3028, 0x0000, 0x969e); + gbe_smi_paged(p, 0x504d, 0x0000, 0x9698); + gbe_smi_paged(p, 0x194f, 0x0002, 0x969a); + + gbe_cl45_write(p, 0x014a001e, 0xee20); + gbe_cl45_write(p, 0x019b001e, 0x0111); + gbe_cl45_write(p, 0x0144001e, 0x0200); + + gbe_smi_write(p, 0x1f, 0x0003); + gbe_smi_write(p, 0x1d, 0x03fb); + gbe_smi_write(p, 0x1f, 0x0000); + + gbe_cl45_write(p, 0x0323001e, 0x0011); + gbe_smi_paged(p, 0x0036, 0x0000, 0x8f80); + + gbe_cl45_write(p, 0x0120001e, 0x8014); + + page = gbe_paged_begin(p, 0xff3f, 0x0000); + gbe_paged_finish(p, 0x83ae, page); + + gbe_cl45_write(p, 0x0000001e, 0x0186); + gbe_cl45_write(p, 0x0001001e, 0x01c5); + gbe_cl45_write(p, 0x0002001e, 0x01c8); + gbe_cl45_write(p, 0x0003001e, 0x010e); + gbe_cl45_write(p, 0x0004001e, 0x0202); + gbe_cl45_write(p, 0x0005001e, 0x0207); + gbe_cl45_write(p, 0x0006001e, 0x0386); + gbe_cl45_write(p, 0x0007001e, 0x03c5); + gbe_cl45_write(p, 0x0008001e, 0x03c8); + gbe_cl45_write(p, 0x0009001e, 0x030a); + gbe_cl45_write(p, 0x000a001e, 0x0005); + gbe_cl45_write(p, 0x000b001e, 0x0008); + } + +skip_path_d_continuation: + gbe_cl45_write(p, 0x003e001e, 0x0000); +} + +int gbe_phy_init(struct gbe_priv *p) +{ + u16 bmcr; + + gbe_cl22_read(p, MII_PHYSID1); + gbe_cl22_read(p, MII_PHYSID2); + + gbe_wr(p, GBE_REG_RESET, 9); + usleep_range(680, 1000); + + /* both SerDes lanes must be locked before calibraton is valid */ + if (~gbe_pcs_rd(p, 0x6c) & 0x80800000) + netdev_info(p->netdev, "SerDes not locked, skipping calibration\n"); + else + gbe_phy_calibrate(p); + + gbe_phy_static_init(p); + + { + u16 adv = gbe_cl22_read(p, MII_ADVERTISE); + + gbe_smi_write(p, MII_ADVERTISE, adv & 0xf3ff); + } + + /* clear bits 12-13 and bit 31 in LINK reg to let the link state machien settle */ + { + u32 v = gbe_rd(p, GBE_REG_LINK); + + gbe_wr(p, GBE_REG_LINK, v & 0x7fffcfff); + } + + gbe_cl22_read(p, MII_ADVERTISE); + gbe_cl22_read(p, MII_CTRL1000); + gbe_smi_write(p, MII_BMCR, BMCR_PDOWN); + + { + u16 adv = gbe_cl22_read(p, MII_ADVERTISE); + + adv = (adv & 0xfe1f) | 0x01e0; + gbe_smi_write(p, MII_ADVERTISE, adv); + } + { + u16 c1000 = gbe_cl22_read(p, MII_CTRL1000); + + c1000 = (c1000 & 0xfcff) | 0x0200; + gbe_smi_write(p, MII_CTRL1000, c1000); + } + gbe_smi_write(p, MII_BMCR, 0x1340); + + bmcr = gbe_cl22_read(p, MII_BMCR); + gbe_smi_write(p, MII_BMCR, bmcr | (BMCR_ANENABLE | BMCR_ANRESTART)); + + { + u16 id1 = gbe_cl22_read(p, MII_PHYSID1); + u16 id2 = gbe_cl22_read(p, MII_PHYSID2); + u16 b_bmcr = gbe_cl22_read(p, MII_BMCR); + u16 b_bmsr = gbe_cl22_read(p, MII_BMSR); + u16 b_adv = gbe_cl22_read(p, MII_ADVERTISE); + u16 b_c1k = gbe_cl22_read(p, MII_CTRL1000); + + netdev_info(p->netdev, + "phy id=%04x:%04x bmcr=%04x bmsr=%04x adv=%04x ctrl1000=%04x link_reg=%08x\n", + id1, id2, b_bmcr, b_bmsr, b_adv, b_c1k, + gbe_rd(p, GBE_REG_LINK)); + } + + return 0; +} diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index b4707640e102..7b854e5bb8ff 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -2801,6 +2801,14 @@ static int next_ari_fn(struct pci_bus *bus, struct pci_dev *dev, int fn) u16 cap = 0; unsigned int next_fn; +#ifdef CONFIG_X86_PS5 + /* ARI capability is broken, so we just assume contiguous functions until 45. */ + if (fn < 45) + return fn + 1; + else + return -ENODEV; +#endif + if (!dev) return -ENODEV; diff --git a/drivers/ps5/Makefile b/drivers/ps5/Makefile new file mode 100644 index 000000000000..ff1bbbbf219c --- /dev/null +++ b/drivers/ps5/Makefile @@ -0,0 +1 @@ +obj-y += spcie.o tpcie.o hdmi.o mp1.o buzzer.o diff --git a/drivers/ps5/autoservo_param.h b/drivers/ps5/autoservo_param.h new file mode 100644 index 000000000000..d2c25e461bf7 --- /dev/null +++ b/drivers/ps5/autoservo_param.h @@ -0,0 +1,1902 @@ +#ifndef _AUTOSERVO_PARAM_H +#define _AUTOSERVO_PARAM_H + +static const u8 autoservo_param_sancarlo[] = { + 0x00, 0x04, 0x33, 0x01, 0x33, 0x01, 0xe1, 0x00, 0x33, 0x01, 0xe1, 0x00, + 0x00, 0x04, 0x33, 0x01, 0x00, 0x04, 0x33, 0x01, 0x33, 0x01, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, + 0x82, 0x16, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x3b, 0x00, 0x00, 0x82, 0x16, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, + 0xf4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x33, 0x01, 0x33, 0x01, 0xe1, 0x00, + 0x33, 0x01, 0xe1, 0x00, 0x00, 0x04, 0x33, 0x01, 0x00, 0x04, 0x33, 0x01, + 0x33, 0x01, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x45, 0x00, 0x00, 0x82, 0x16, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, + 0xf4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x3b, 0x00, 0x00, 0x82, 0x16, 0x00, 0x00, + 0x69, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x48, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x33, 0x01, + 0x33, 0x01, 0xe1, 0x00, 0x33, 0x01, 0xe1, 0x00, 0x00, 0x04, 0x33, 0x01, + 0x00, 0x04, 0x33, 0x01, 0x33, 0x01, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, 0x82, 0x16, 0x00, 0x00, + 0xc8, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x48, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x3b, 0x00, 0x00, + 0x82, 0x16, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0x33, 0x01, 0x33, 0x01, 0xe1, 0x00, 0x33, 0x01, 0xe1, 0x00, + 0x00, 0x04, 0x33, 0x01, 0x00, 0x04, 0x33, 0x01, 0x33, 0x01, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, + 0x82, 0x16, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, + 0x14, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x3b, 0x00, 0x00, 0x82, 0x16, 0x00, 0x00, 0x69, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, + 0xf4, 0x01, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xe1, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0xc1, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_a_eiger_samsung[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xd5, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4c, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x7f, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x4c, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xd5, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x4a, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x7f, 0x0b, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_a_eiger_hynix[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x4e, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xd5, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x4e, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x7f, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x4e, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xd5, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x4c, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x7f, 0x0b, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_a_eiger_micron[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x52, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xd5, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x52, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x7f, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x52, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xd5, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x13, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x7f, 0x0b, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_a_denali_samsung[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x4c, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xd5, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x4c, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x7f, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x4c, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xd5, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x4a, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x16, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x7f, 0x0b, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_a_denali_hynix[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xd5, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x7f, 0x0b, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x50, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xd5, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x4e, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x16, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x7f, 0x0b, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_a_denali_micron[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x40, 0x53, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xe3, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x40, 0x53, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x84, 0x12, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x40, 0x53, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x45, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xe3, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x40, 0x51, 0x00, 0x00, 0x3b, 0x0a, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x13, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x84, 0x12, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x40, 0x00, 0x00, + 0x3b, 0x0a, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_b_eiger_denali_samsung_d1x[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xce, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x04, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x48, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x56, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xce, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x51, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x43, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_b_eiger_denali_hynix_1x_micron_120s[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x58, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x4b, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xce, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x58, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x04, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x4b, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x58, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x4b, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xce, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x53, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x46, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_b_eiger_denali_hynix_1y_micron_130s[] = { + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x54, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, + 0xce, 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x54, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, + 0x04, 0x10, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x48, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x05, 0x17, 0x00, 0x00, + 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x54, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xcd, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x48, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0xbe, 0x00, + 0x00, 0x04, 0xbe, 0x00, 0x00, 0x04, 0x00, 0x04, 0xce, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x4f, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x27, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x27, 0x00, 0x00, + 0x00, 0x17, 0x00, 0x00, 0xa5, 0x21, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x43, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; + +static const u8 autoservo_param_d_eiger_denali_samsung_d1z[] = { + 0x00, 0x04, 0x83, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x9f, 0x1b, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x55, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x49, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0x00, 0x04, + 0x1a, 0x01, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x9f, 0x1b, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x55, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x49, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x83, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x9f, 0x1b, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x55, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x49, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0x00, 0x04, 0xce, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x50, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x44, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x64, 0x00, 0x63, 0x00, 0x02, 0x00, + 0x64, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, + 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x36, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, + 0x63, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, + 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, + 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 autoservo_param_d_eiger_denali_hynix_1y[] = { + 0x00, 0x04, 0x83, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x9f, 0x1b, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x56, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x49, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0x00, 0x04, + 0x1a, 0x01, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x9f, 0x1b, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x56, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x49, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x83, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x9f, 0x1b, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x56, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x49, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0x00, 0x04, 0xce, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x51, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x44, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x64, 0x00, 0x63, 0x00, 0x02, 0x00, + 0x64, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, + 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x36, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, + 0x63, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, + 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, + 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const u8 autoservo_param_d_eiger_denali_micron_130s_y31j[] = { + 0x00, 0x04, 0x83, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, + 0x9f, 0x1b, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x55, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x47, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0x00, 0x04, + 0x1a, 0x01, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x5b, 0x00, 0x00, 0x9f, 0x1b, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, + 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x55, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x47, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x83, 0x00, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x67, 0x00, + 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x5b, 0x00, 0x00, 0x9f, 0x1b, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xe8, 0x5d, 0x00, 0x00, + 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, 0xe0, 0x9c, 0x41, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x55, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x47, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0xec, 0x00, + 0x00, 0x04, 0xec, 0x00, 0x00, 0x04, 0x00, 0x04, 0xce, 0x00, 0x00, 0x04, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x56, 0x00, 0x00, + 0x05, 0x17, 0x00, 0x00, 0x25, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xe8, 0x5d, 0x00, 0x00, 0x50, 0x46, 0x00, 0x00, 0x00, 0x80, 0x02, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, + 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, + 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x42, 0x00, 0x00, + 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x50, 0x00, 0x00, + 0xfa, 0x2d, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, + 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x64, 0x00, 0x63, 0x00, 0x02, 0x00, + 0x64, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x04, 0x67, + 0x00, 0x00, 0x04, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x80, 0x36, 0x00, 0x00, 0xb1, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, + 0xff, 0xff, 0xff, 0x0f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, + 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x64, 0x00, + 0x63, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0x00, 0x04, 0x67, 0x00, 0x00, 0x04, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, + 0xff, 0x0f, 0x01, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, + 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, + 0xd8, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +#endif /* _AUTOSERVO_PARAM_H */ diff --git a/drivers/ps5/buzzer.c b/drivers/ps5/buzzer.c new file mode 100644 index 000000000000..f48ad6f92534 --- /dev/null +++ b/drivers/ps5/buzzer.c @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BUZZER_IOC_MAGIC 'B' + +#define PS5_BUZZ_SILENT 0 +#define PS5_BUZZ_SHORT 1 +#define PS5_BUZZ_ERROR 2 +#define PS5_BUZZ_LONG 3 + +struct ps5_buzzer_step { + __u8 value; + __u16 hold_ms; +} __attribute__((packed)); + +struct ps5_buzzer_pattern { + __u32 nsteps; + struct ps5_buzzer_step steps[]; +}; + +#define PS5_BUZZER_BEEP _IOW(BUZZER_IOC_MAGIC, 1, __u8) +#define PS5_BUZZER_PLAY _IOW(BUZZER_IOC_MAGIC, 2, struct ps5_buzzer_pattern) +#define PS5_BUZZER_STOP _IO(BUZZER_IOC_MAGIC, 3) + +#define MAX_PATTERN_STEPS 1024 + +static struct input_dev *snd_idev; +static struct task_struct *play_thread; +static DEFINE_MUTEX(play_lock); + +static int ps5_buzz_raw(u8 level) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + if (level > PS5_BUZZ_LONG) + return -EINVAL; + + msg->service_id = ICC_SERVICE_ID_INDICATOR; + msg->msg_type = 0x00; + msg->length = 0x20; + msg->data[0] = level; + + return icc_query(buf, buf); +} + +struct play_ctx { + struct ps5_buzzer_step *steps; + u32 nsteps; +}; + +static int play_fn(void *data) +{ + struct play_ctx *ctx = data; + u32 i; + + for (i = 0; i < ctx->nsteps && !kthread_should_stop(); i++) { + ps5_buzz_raw(ctx->steps[i].value); + if (ctx->steps[i].hold_ms) + msleep_interruptible(ctx->steps[i].hold_ms); + } + + kfree(ctx->steps); + kfree(ctx); + + mutex_lock(&play_lock); + play_thread = NULL; + mutex_unlock(&play_lock); + return 0; +} + +static int play_start(struct ps5_buzzer_step *steps, u32 nsteps) +{ + struct play_ctx *ctx; + struct task_struct *t; + + mutex_lock(&play_lock); + if (play_thread) { + mutex_unlock(&play_lock); + return -EBUSY; + } + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) { + mutex_unlock(&play_lock); + return -ENOMEM; + } + ctx->steps = steps; + ctx->nsteps = nsteps; + + t = kthread_run(play_fn, ctx, "ps5_buzz_play"); + if (IS_ERR(t)) { + kfree(ctx); + mutex_unlock(&play_lock); + return PTR_ERR(t); + } + play_thread = t; + mutex_unlock(&play_lock); + return 0; +} + +static int play_stop(void) +{ + mutex_lock(&play_lock); + if (play_thread) { + kthread_stop(play_thread); + play_thread = NULL; + } + mutex_unlock(&play_lock); + return 0; +} + +static ssize_t buzz_write(struct file *f, const char __user *ubuf, + size_t n, loff_t *pos) +{ + char c; + int ret; + + if (n < 1) + return -EINVAL; + if (get_user(c, ubuf)) + return -EFAULT; + if (c < '0' || c > '3') + return -EINVAL; + + ret = ps5_buzz_raw(c - '0'); + return ret ? ret : n; +} + +static long buzz_ioctl(struct file *f, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case PS5_BUZZER_BEEP: { + u8 level; + if (get_user(level, (u8 __user *)arg)) + return -EFAULT; + return ps5_buzz_raw(level); + } + case PS5_BUZZER_PLAY: { + struct ps5_buzzer_pattern hdr; + struct ps5_buzzer_step *steps; + size_t bytes; + int ret; + + if (copy_from_user(&hdr, (void __user *)arg, sizeof(hdr))) + return -EFAULT; + if (!hdr.nsteps || hdr.nsteps > MAX_PATTERN_STEPS) + return -EINVAL; + + bytes = hdr.nsteps * sizeof(struct ps5_buzzer_step); + steps = kmalloc(bytes, GFP_KERNEL); + if (!steps) + return -ENOMEM; + if (copy_from_user(steps, + (void __user *)(arg + sizeof(hdr)), bytes)) { + kfree(steps); + return -EFAULT; + } + ret = play_start(steps, hdr.nsteps); + if (ret) + kfree(steps); + return ret; + } + case PS5_BUZZER_STOP: + return play_stop(); + } + return -ENOTTY; +} + +static const struct file_operations buzz_fops = { + .owner = THIS_MODULE, + .write = buzz_write, + .unlocked_ioctl = buzz_ioctl, + .llseek = noop_llseek, +}; + +static struct miscdevice buzz_misc = { + .minor = MISC_DYNAMIC_MINOR, + .name = "ps5_buzzer", + .fops = &buzz_fops, + .mode = 0660, +}; + +static int snd_event(struct input_dev *dev, unsigned int type, + unsigned int code, int value) +{ + if (type == EV_SND && code == SND_BELL) + ps5_buzz_raw(value ? PS5_BUZZ_SHORT : PS5_BUZZ_SILENT); + return 0; +} + +static ssize_t beep_store(struct device *d, struct device_attribute *a, + const char *buf, size_t n) +{ + u8 level; + int ret; + + if (kstrtou8(buf, 0, &level)) + return -EINVAL; + ret = ps5_buzz_raw(level); + return ret ? ret : n; +} +static DEVICE_ATTR_WO(beep); + +static ssize_t stop_store(struct device *d, struct device_attribute *a, + const char *buf, size_t n) +{ + play_stop(); + return n; +} +static DEVICE_ATTR_WO(stop); + +static struct attribute *buzz_attrs[] = { + &dev_attr_beep.attr, + &dev_attr_stop.attr, + NULL, +}; + +static const struct attribute_group buzz_attr_group = { + .attrs = buzz_attrs, +}; + +static int __init ps5_buzzer_init(void) +{ + int ret; + + ret = misc_register(&buzz_misc); + if (ret) + return ret; + + ret = sysfs_create_group(&buzz_misc.this_device->kobj, &buzz_attr_group); + if (ret) + goto err_misc; + + snd_idev = input_allocate_device(); + if (!snd_idev) { + ret = -ENOMEM; + goto err_sysfs; + } + snd_idev->name = "PS5 Chassis Buzzer"; + snd_idev->phys = "ps5_buzzer/input0"; + snd_idev->id.bustype = BUS_VIRTUAL; + snd_idev->event = snd_event; + input_set_capability(snd_idev, EV_SND, SND_BELL); + + ret = input_register_device(snd_idev); + if (ret) + goto err_input; + + return 0; + +err_input: + input_free_device(snd_idev); + snd_idev = NULL; +err_sysfs: + sysfs_remove_group(&buzz_misc.this_device->kobj, &buzz_attr_group); +err_misc: + misc_deregister(&buzz_misc); + return ret; +} + +static void __exit ps5_buzzer_exit(void) +{ + play_stop(); + if (snd_idev) + input_unregister_device(snd_idev); + sysfs_remove_group(&buzz_misc.this_device->kobj, &buzz_attr_group); + misc_deregister(&buzz_misc); +} + +module_init(ps5_buzzer_init); +module_exit(ps5_buzzer_exit); + +MODULE_AUTHOR("Armandas Kvietkus"); +MODULE_DESCRIPTION("PlayStation 5 chassis piezo buzzer"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ps5/hdmi.c b/drivers/ps5/hdmi.c new file mode 100644 index 000000000000..8f094490d677 --- /dev/null +++ b/drivers/ps5/hdmi.c @@ -0,0 +1,1237 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include + +#define HDMI_IC_TYPE_FLAVA3 2 +#define HDMI_IC_TYPE_VERDE 3 + +struct icc_i2c_msg { + u8 code; + u16 length; + u8 count; + u8 data[]; +} __packed; + +struct i2c_cmd_hdr { + u8 major; + u8 length; + u8 minor; + u8 count; + u8 data[]; +} __packed; + +struct i2c_cmd_2_1 { + u8 length; + u8 reg_high; + u8 reg_low; + u8 data[]; +} __packed; + +struct i2c_cmd_write { + u8 length; + u8 reg_high; + u8 reg_low; + u8 data[]; +} __packed; + +struct i2c_cmd_mask { + u8 length; + u8 reg_high; + u8 reg_low; + u8 value; + u8 mask[]; +} __packed; + +struct i2c_cmd_delay { + u8 length; + u8 time_low; + u8 time_high; + u8 unk_03; +} __packed; + +struct i2c_cmd_waitset { + u8 length; + u8 reg_high; + u8 reg_low; + u8 value; +} __packed; + +struct i2c_cmd_waitclear { + u8 length; + u8 reg_high; + u8 reg_low; + u8 value; +} __packed; + +struct i2c_cmd_3_5 { + u8 length; + u8 reg_high; + u8 reg_low; + u8 value; +} __packed; + +struct i2c_cmd_5_3 { + u8 value; +} __packed; + +struct i2c_cmd_5_4 { + u8 value; +} __packed; + +struct i2c_cmd_5_5 { + u8 value; +} __packed; + +struct i2c_block { + u8 length; + u16 reg; + u8 data[32]; +}; + +struct i2c_context { + struct i2c_block blocks[128]; + int block_index; + u8 msg_buf[ICC_MSG_MAX_SIZE - sizeof(struct icc_msg)]; + u8 *msg_cur; + struct icc_i2c_msg *msg_hdr; +}; + +static struct i2c_context i2c_ctx; + +static u8 hdmi_ic_type; +static u8 tmds_polarity; +static u8 tmds_ch_swap; +static u8 dp_polarity; +static u8 dp_ch_swap; + +static void i2c_init(u8 code) +{ + i2c_ctx.msg_cur = i2c_ctx.msg_buf; + i2c_ctx.msg_hdr = (struct icc_i2c_msg *)i2c_ctx.msg_cur; + + i2c_ctx.msg_hdr->code = code; + i2c_ctx.msg_hdr->length = 0; + i2c_ctx.msg_hdr->count = 0; + i2c_ctx.block_index = -1; + + i2c_ctx.msg_cur += sizeof(*i2c_ctx.msg_hdr); +} + +static int i2c_exec(void) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + int ret; + + i2c_ctx.msg_hdr->length = i2c_ctx.msg_cur - i2c_ctx.msg_buf; + + msg->service_id = ICC_SERVICE_ID_HDMI; + msg->msg_type = 0; + msg->length = sizeof(*msg) + i2c_ctx.msg_hdr->length; + memcpy(msg->data, i2c_ctx.msg_hdr, i2c_ctx.msg_hdr->length); + + ret = icc_query(buf, buf); + if (ret) + return ret; + + return 0; +} + +static void i2c_write_block(struct i2c_block *block, size_t count) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + int i; + + hdr->major = 2; + hdr->minor = 2; + hdr->count = count; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + for (i = 0; i < count; i++) { + struct i2c_cmd_write *cmd = (struct i2c_cmd_write *)i2c_ctx.msg_cur; + + cmd->length = block[i].length; + cmd->reg_low = block[i].reg & 0xff; + cmd->reg_high = block[i].reg >> 8; + memcpy(cmd->data, block[i].data, block[i].length); + + i2c_ctx.msg_cur += sizeof(*cmd) + cmd->length; + hdr->length += sizeof(*cmd) + cmd->length; + } + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_begin_block(void) +{ + i2c_ctx.block_index = 0; +} + +static void i2c_end_block(void) +{ + if (i2c_ctx.block_index > 0) + i2c_write_block(i2c_ctx.blocks, i2c_ctx.block_index); + i2c_ctx.block_index = -1; +} + +static void i2c_write_data(u16 reg, u8 value[], size_t count) +{ + struct i2c_block *block; + bool new_block = i2c_ctx.block_index == -1; + + if (new_block) + i2c_begin_block(); + + block = &i2c_ctx.blocks[i2c_ctx.block_index++]; + block->reg = reg; + block->length = count; + memcpy(block->data, value, count); + + if (new_block) + i2c_end_block(); +} + +static void i2c_write(u16 reg, u8 value) +{ + i2c_write_data(reg, &value, 1); +} + +static void i2c_cmd_2_1(u16 reg, u8 unk) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 2; + hdr->minor = 1; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_2_1 *cmd = (struct i2c_cmd_2_1 *)i2c_ctx.msg_cur; + cmd->length = 1; + cmd->reg_low = reg & 0xff; + cmd->reg_high = reg >> 8; + cmd->data[0] = unk; + i2c_ctx.msg_cur += sizeof(*cmd) + cmd->length; + hdr->length += sizeof(*cmd) + cmd->length; + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_delay(u16 time) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 3; + hdr->minor = 1; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_delay *cmd = (struct i2c_cmd_delay *)i2c_ctx.msg_cur; + cmd->length = 0; + cmd->time_low = time & 0xff; + cmd->time_high = time >> 8; + cmd->unk_03 = 0; + i2c_ctx.msg_cur += sizeof(*cmd) + cmd->length; + hdr->length += sizeof(*cmd) + cmd->length; + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_mask(u16 reg, u8 value, u8 mask) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 2; + hdr->minor = 3; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_mask *cmd = (struct i2c_cmd_mask *)i2c_ctx.msg_cur; + cmd->length = 1; + cmd->reg_low = reg & 0xff; + cmd->reg_high = reg >> 8; + cmd->value = value; + cmd->mask[0] = mask; + i2c_ctx.msg_cur += sizeof(*cmd) + cmd->length; + hdr->length += sizeof(*cmd) + cmd->length; + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_waitset(u16 reg, u8 value) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 3; + hdr->minor = 2; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_waitset *cmd = (struct i2c_cmd_waitset *)i2c_ctx.msg_cur; + cmd->length = 0; + cmd->reg_low = reg & 0xff; + cmd->reg_high = reg >> 8; + cmd->value = value; + i2c_ctx.msg_cur += sizeof(*cmd) + cmd->length; + hdr->length += sizeof(*cmd) + cmd->length; + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_waitclear(u16 reg, u8 value) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 3; + hdr->minor = 3; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_waitclear *cmd = (struct i2c_cmd_waitclear *)i2c_ctx.msg_cur; + cmd->length = 0; + cmd->reg_low = reg & 0xff; + cmd->reg_high = reg >> 8; + cmd->value = value; + i2c_ctx.msg_cur += sizeof(*cmd) + cmd->length; + hdr->length += sizeof(*cmd) + cmd->length; + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_cmd_3_5(u16 reg, u8 value) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 3; + hdr->minor = 5; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_3_5 *cmd = (struct i2c_cmd_3_5 *)i2c_ctx.msg_cur; + cmd->length = 0; + cmd->reg_low = reg & 0xff; + cmd->reg_high = reg >> 8; + cmd->value = value; + i2c_ctx.msg_cur += sizeof(*cmd) + cmd->length; + hdr->length += sizeof(*cmd) + cmd->length; + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_cmd_4_16(void *data, size_t size) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 4; + hdr->minor = 16; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + memcpy(i2c_ctx.msg_cur, data, size); + i2c_ctx.msg_cur += size; + hdr->length += size; + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_cmd_5_3(u8 unk) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 5; + hdr->minor = 3; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_5_3 *cmd = (struct i2c_cmd_5_3 *)i2c_ctx.msg_cur; + cmd->value = unk; + i2c_ctx.msg_cur += sizeof(*cmd); + hdr->length += sizeof(*cmd); + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_cmd_5_4(u8 event) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 5; + hdr->minor = 4; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_5_4 *cmd = (struct i2c_cmd_5_4 *)i2c_ctx.msg_cur; + cmd->value = event; + i2c_ctx.msg_cur += sizeof(*cmd); + hdr->length += sizeof(*cmd); + + i2c_ctx.msg_hdr->count++; +} + +static void i2c_cmd_5_5(u8 event) +{ + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 5; + hdr->minor = 5; + hdr->count = 1; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + struct i2c_cmd_5_5 *cmd = (struct i2c_cmd_5_5 *)i2c_ctx.msg_cur; + cmd->value = event; + i2c_ctx.msg_cur += sizeof(*cmd); + hdr->length += sizeof(*cmd); + + i2c_ctx.msg_hdr->count++; +} + +static int stopHdcpHw(void) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_GENERAL; + msg->msg_type = 0x1f; + msg->length = ICC_MSG_MIN_SIZE; + + return icc_query(buf, buf); +} + +static void sceSetBackToUnpluggedSequence(void) +{ + static u8 data[] = {0x11, 0x51, 0x09, 0x00, 0x02, 0x09, 0x03, 0x01, 0x01, 0x70, 0x5f, 0x80, 0x80, 0x03, 0x08, 0x01, 0x01, 0x00, 0x32, 0x00, 0x00, 0x02, 0x09, 0x03, 0x01, 0x01, 0x7a, 0x88, 0xff, 0xff, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x09, 0x03, 0x01, 0x01, 0x74, 0x0a, 0xff, 0xff, 0x03, 0x08, 0x03, 0x01, 0x00, 0x74, 0x0a, 0xff, 0x02, 0x09, 0x03, 0x01, 0x01, 0x74, 0x19, 0x05, 0x07, 0x02, 0x09, 0x03, 0x01, 0x01, 0x7a, 0x8b, 0x00, 0x07, 0x03, 0x08, 0x01, 0x01, 0x00, 0x32, 0x00, 0x00}; + i2c_init(0); + i2c_cmd_4_16(data, sizeof(data)); + i2c_exec(); +} + +static void sceSetBackToWaitResolutionSequence(void) +{ + static u8 data[] = {0x12, 0x47, 0x08, 0x00, 0x02, 0x09, 0x03, 0x01, 0x01, 0x70, 0x5f, 0x80, 0x80, 0x02, 0x08, 0x02, 0x01, 0x01, 0x7a, 0x88, 0xff, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x08, 0x02, 0x01, 0x01, 0x74, 0x0a, 0xff, 0x03, 0x08, 0x03, 0x01, 0x00, 0x74, 0x0a, 0xff, 0x02, 0x09, 0x03, 0x01, 0x01, 0x74, 0x19, 0x05, 0x07, 0x02, 0x09, 0x03, 0x01, 0x01, 0x7a, 0x8b, 0x00, 0x07, 0x03, 0x08, 0x01, 0x01, 0x00, 0x64, 0x00, 0x00}; + i2c_init(0); + i2c_cmd_4_16(data, sizeof(data)); + i2c_exec(); +} + +static void i2c_cmd_4_2(void) +{ + static u8 data[] = {0x31, 0x7a, 0xb8, 0x08, 0x32, 0x7a, 0xb0, 0x05, 0x33, 0x7a, 0xa0, 0x05, 0x34, 0x7a, 0xe1, 0x01, 0x35, 0x7a, 0xe2, 0x01, 0x36, 0x7a, 0xe0, 0x01, 0x37, 0x7c, 0x00, 0x05}; + + i2c_init(0); + + struct i2c_cmd_hdr *hdr = (struct i2c_cmd_hdr *)i2c_ctx.msg_cur; + hdr->major = 4; + hdr->minor = 2; + hdr->count = 7; + hdr->length = sizeof(*hdr); + i2c_ctx.msg_cur += sizeof(*hdr); + + memcpy(i2c_ctx.msg_cur, data, sizeof(data)); + i2c_ctx.msg_cur += sizeof(data); + hdr->length += sizeof(data); + + i2c_ctx.msg_hdr->count++; + + i2c_exec(); +} + +static void sceSetHdcpSequence1st(void) +{ + static u8 data[] = {0x0b, 0x91, 0x0f, 0x00, 0x02, 0x0c, 0x02, 0x02, 0x01, 0x7a, 0x8b, 0x05, 0x01, 0x7a, 0x88, 0xff, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x11, 0x02, 0x03, 0x02, 0x10, 0xe5, 0xff, 0xff, 0x01, 0x7a, 0x85, 0x00, 0x01, 0x7a, 0x83, 0x84, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x08, 0x01, 0x01, 0x01, 0x7a, 0x83, 0x83, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x03, 0x08, 0x01, 0x01, 0x00, 0x0f, 0x00, 0x00, 0x02, 0x08, 0x01, 0x01, 0x01, 0x7a, 0x83, 0x84, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x10, 0x02, 0x03, 0x01, 0x10, 0xe6, 0xff, 0x01, 0x7a, 0x85, 0x00, 0x01, 0x7a, 0x83, 0xe3, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01}; + + i2c_init(0); + i2c_cmd_4_16(data, sizeof(data)); + i2c_exec(); +} + +static void sceSetHdcpSequence2nd(void) +{ + static u8 data[] = {0x0c, 0x39, 0x06, 0x00, 0x02, 0x0d, 0x02, 0x02, 0x02, 0x10, 0xe5, 0xff, 0xff, 0x01, 0x7a, 0x83, 0xdc, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x08, 0x01, 0x01, 0x01, 0x7a, 0x83, 0xc4, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01}; + i2c_init(0); + i2c_cmd_4_16(data, sizeof(data)); + i2c_exec(); +} + +static void sceSetHdcpSequence3rd(void) +{ + static u8 data[] = {0x0d, 0x21, 0x01, 0x00, 0x02, 0x1d, 0x02, 0x06, 0x01, 0x10, 0xe7, 0xff, 0x01, 0x7a, 0x8b, 0x03, 0x02, 0x10, 0xe5, 0xff, 0xff, 0x01, 0x7a, 0x9d, 0x4f, 0x01, 0x7a, 0x83, 0x8e, 0x01, 0x7e, 0x03, 0x10}; + i2c_init(0); + i2c_cmd_4_16(data, sizeof(data)); + i2c_exec(); +} + +static void sceSetEdidSequence(int sequence) +{ + static u8 seq_0[] = {0x04, 0x3f, 0x06, 0x00, 0x02, 0x0c, 0x02, 0x02, 0x01, 0x7a, 0x88, 0xff, 0x01, 0x7a, 0x83, 0x88, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x0f, 0x02, 0x02, 0x01, 0x7a, 0x9c, 0x0e, 0x04, 0x7a, 0x80, 0x00, 0x00, 0x7f, 0x82, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01}; + static u8 seq_1[] = {0x05, 0x3f, 0x06, 0x00, 0x02, 0x0c, 0x02, 0x02, 0x01, 0x7a, 0x88, 0xff, 0x01, 0x7a, 0x83, 0x88, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x0f, 0x02, 0x02, 0x01, 0x7a, 0x9c, 0x0e, 0x04, 0x7a, 0x80, 0x00, 0x80, 0x7f, 0x82, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01}; + static u8 seq_2[] = {0x06, 0x3f, 0x06, 0x00, 0x02, 0x0c, 0x02, 0x02, 0x01, 0x7a, 0x88, 0xff, 0x01, 0x7a, 0x83, 0x88, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x0f, 0x02, 0x02, 0x01, 0x7a, 0x9c, 0x0e, 0x04, 0x7a, 0x80, 0x01, 0x00, 0x7f, 0x82, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01}; + static u8 seq_3[] = {0x07, 0x3f, 0x06, 0x00, 0x02, 0x0c, 0x02, 0x02, 0x01, 0x7a, 0x88, 0xff, 0x01, 0x7a, 0x83, 0x88, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01, 0x02, 0x0f, 0x02, 0x02, 0x01, 0x7a, 0x9c, 0x0e, 0x04, 0x7a, 0x80, 0x01, 0x80, 0x7f, 0x82, 0x03, 0x08, 0x02, 0x01, 0x00, 0x7a, 0x84, 0xa0, 0x03, 0x08, 0x03, 0x01, 0x00, 0x7a, 0x84, 0x01}; + + i2c_init(0); + if (sequence == 0) { + i2c_cmd_4_16(seq_0, sizeof(seq_0)); + } else if (sequence == 1) { + i2c_cmd_4_16(seq_1, sizeof(seq_1)); + } else if (sequence == 2) { + i2c_cmd_4_16(seq_2, sizeof(seq_2)); + } else if (sequence == 3) { + i2c_cmd_4_16(seq_3, sizeof(seq_3)); + } + i2c_exec(); +} + +static void sceSetWaitPllSequence(void) +{ + static u8 data[] = {0x0a, 0x15, 0x02, 0x00, 0x02, 0x09, 0x03, 0x01, 0x01, 0x70, 0x21, 0xff, 0xff, 0x03, 0x08, 0x01, 0x01, 0x00, 0x64, 0x00, 0x00}; + i2c_init(0); + i2c_cmd_4_16(data, sizeof(data)); + i2c_exec(); +} + +static void unk_akv(void) +{ + i2c_init(4); + i2c_begin_block(); + i2c_write(0x7006, 0x12); + i2c_write(0x7a88, 0xff); + i2c_end_block(); + i2c_waitclear(0x7a84, 0x01); + i2c_cmd_2_1(0x7a83, 0x88); + i2c_waitset(0x7a84, 0xa0); + i2c_waitclear(0x7a84, 0x01); + i2c_begin_block(); + i2c_write(0x7a8b, 0x05); + i2c_write(0x7a89, 0x01); + i2c_end_block(); + i2c_delay(20); + i2c_cmd_2_1(0x7a83, 0x0e); + i2c_waitset(0x7a84, 0xa0); + i2c_exec(); +} + +static void sceControlHdmiEvent(u8 enable) +{ + i2c_init(4); + i2c_cmd_5_4(enable); + i2c_exec(); +} + +void hdmiSystemResume(void) +{ + // sceSetBackToUnpluggedSequence(); + // sceSetBackToWaitResolutionSequence(); + if (hdmi_ic_type == HDMI_IC_TYPE_FLAVA3) { + i2c_cmd_4_2(); + // sceSetHdcpSequence1st(); + // sceSetHdcpSequence2nd(); + // sceSetHdcpSequence3rd(); + sceSetEdidSequence(0); + sceSetEdidSequence(1); + sceSetEdidSequence(2); + sceSetEdidSequence(3); + sceSetWaitPllSequence(); + unk_akv(); + } + sceControlHdmiEvent(1); +} +EXPORT_SYMBOL(hdmiSystemResume); + +static void sceDisableEncode(void) +{ + i2c_init(4); + i2c_mask(0x705f, 0x80, 0x80); + i2c_cmd_5_3(0x00); + i2c_mask(0x7021, 0x00, 0xf0); + i2c_cmd_2_1(0x7a88, 0xff); + i2c_waitclear(0x7a84, 0x01); + i2c_cmd_2_1(0x740a, 0xff); + i2c_waitclear(0x740a, 0xff); + i2c_mask(0x7419, 0x05, 0x07); + i2c_mask(0x7a8b, 0x00, 0x07); + i2c_delay(100); + i2c_exec(); +} + +static void initIsrForFlava3(void) +{ + i2c_init(0); + i2c_begin_block(); + i2c_write(0x705f, 0x12); + i2c_write(0x6004, 0x80); + i2c_write(0x6020, 0x00); + i2c_write(0x7007, 0xff); + i2c_write(0x100c, 0x01); + i2c_write(0x6008, 0xc0); + i2c_write(0x6207, 0x00); + i2c_write(0x621b, 0x00); + i2c_write_data(0x6080, (u8[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 6); + i2c_write_data(0x6090, (u8[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 8); + i2c_write_data(0x10e7, (u8[]){0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 8); + i2c_write_data(0x10e9, (u8[]){0xff, 0xff}, 2); + i2c_write_data(0x10f0, (u8[]){0xff, 0x07, 0x00, 0x0f, 0x00, 0x56, 0x00, 0x00, 0xd0, 0x00}, 10); + i2c_write(0x7018, (tmds_polarity == 1) << 1); + i2c_end_block(); + if (tmds_ch_swap == 1) { + i2c_mask(0x701a, 0xb1, 0xff); + } + i2c_exec(); +} + +static void initDpForFlava3(void) +{ + i2c_init(0); + i2c_begin_block(); + i2c_write(0x6a03, 0x04); + i2c_write(0x60a2, 0xf1); + i2c_write(0x60bf, 0x03); + i2c_write(0x60c0, 0xef); + i2c_write(0x60c3, 0x4d); + i2c_write(0x60c7, 0x85); + i2c_write(0x60bf, 0x04); + i2c_write(0x60c7, 0x84); + if (dp_polarity != 0xff) { + i2c_write(0x600e, dp_polarity << 4); + } + if (dp_ch_swap != 0xff) { + i2c_write(0x600b, dp_ch_swap); + } + i2c_write_data(0x6220, (u8[]){0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x02}, 7); + i2c_write_data(0x6028, (u8[]){0x01, 0x02}, 2); + i2c_write_data(0x6058, (u8[]){0x01, 0x02, 0x03, 0x04}, 4); + i2c_write(0x62af, 0x01); + i2c_write(0x6207, 0x00); + i2c_write(0x621b, 0x00); + i2c_write(0x60e0, 0x1e); + i2c_write(0x603c, 0x04); + i2c_write(0x100e, 0x10); + i2c_end_block(); + i2c_delay(2); + i2c_write(0x6005, 0x01); + i2c_delay(2); + i2c_write(0x6008, 0x00); + i2c_exec(); +} + +static void configVSyncSettingFlava3(void) +{ + i2c_init(1); + i2c_begin_block(); + i2c_write(0x1047, 0x00); + i2c_write(0x6064, 0x01); + i2c_write_data(0x600c, (u8[]){0x01, 0x00}, 2); + i2c_write(0x6c07, 0x00); + i2c_write_data(0x7214, (u8[]){0x00, 0x00}, 2); + i2c_end_block(); + i2c_exec(); +} + +static void configParamFlava3Pre(void) +{ + i2c_init(1); + i2c_begin_block(); + i2c_write_data(0x6224, (u8[]){0x00, 0x01}, 2); + i2c_write_data(0x1047, (u8[]){0x00}, 1); + i2c_write_data(0x1050, (u8[]){0x00, 0x00, 0x00, 0x00}, 4); + i2c_write(0x7215, 0x00); + i2c_write(0x7077, 0x00); + i2c_write(0x7079, 0x80); + i2c_end_block(); + i2c_exec(); +} + +static void configLinkTrainingFlava3(void) +{ + i2c_init(1); + i2c_begin_block(); + i2c_write_data(0x600c, (u8[]){0x01, 0x00}, 2); + i2c_write_data(0x6c00, (u8[]){0x1e, 0x84, 0x00}, 3); + i2c_end_block(); + i2c_mask(0x6005, 0x01, 0x01); + i2c_delay(2); + i2c_mask(0x6006, 0x04, 0x04); + i2c_delay(2); + i2c_write(0x6a03, 0x47); + i2c_delay(10); + i2c_waitset(0x60f8, 0xff); + i2c_waitset(0x60f9, 0x01); + i2c_write(0x6a01, 0x4d); + i2c_waitset(0x60f9, 0x1a); + i2c_waitset(0x6083, 0x02); + i2c_exec(); +} + +static void initHdmiPhyForFlava3_1st(void) +{ + i2c_init(0); + i2c_begin_block(); + i2c_write(0x7022, 0x03); + i2c_write(0x7030, 0x40); + i2c_write_data(0x7024, (u8[]){0x04, 0x54}, 2); + i2c_write(0x7030, 0x41); + i2c_write_data(0x7024, (u8[]){0x04, 0x54}, 2); + i2c_write(0x7030, 0x42); + i2c_write_data(0x7024, (u8[]){0x04, 0x34}, 2); + i2c_write(0x7030, 0x43); + i2c_write_data(0x7024, (u8[]){0x04, 0x34}, 2); + i2c_write(0x7030, 0x04); + i2c_write_data(0x7024, (u8[]){0x04, 0x71}, 2); + i2c_write(0x7030, 0x14); + i2c_write(0x7025, 0x71); + i2c_write(0x7030, 0x24); + i2c_write(0x7025, 0x70); + i2c_write(0x7030, 0x34); + i2c_write(0x7025, 0x77); + i2c_write(0x7030, 0x05); + i2c_write_data(0x7024, (u8[]){0x04, 0x71}, 2); + i2c_write(0x7030, 0x15); + i2c_write(0x7025, 0x71); + i2c_write(0x7030, 0x25); + i2c_write(0x7025, 0x70); + i2c_write(0x7030, 0x35); + i2c_write(0x7025, 0x77); + i2c_write(0x7030, 0x06); + i2c_write_data(0x7024, (u8[]){0x04, 0x71}, 2); + i2c_write(0x7030, 0x16); + i2c_write(0x7025, 0x70); + i2c_write(0x7030, 0x26); + i2c_write(0x7025, 0x70); + i2c_write(0x7030, 0x36); + i2c_write(0x7025, 0x77); + i2c_end_block(); + i2c_exec(); +} + +static void initHdmiPhyForFlava3_2nd(void) +{ + i2c_init(0); + i2c_begin_block(); + i2c_write(0x7030, 0x47); + i2c_write(0x7024, 0x04); + i2c_write(0x7025, 0x37); + i2c_write(0x7027, 0x17); + i2c_write(0x7030, 0x37); + i2c_write(0x7025, 0x71); + i2c_write(0x7027, 0x14); + i2c_write(0x7030, 0x48); + i2c_write(0x7024, 0x04); + i2c_write(0x7025, 0x37); + i2c_write(0x7027, 0x17); + i2c_write(0x7030, 0x38); + i2c_write(0x7025, 0x77); + i2c_write(0x7027, 0x14); + i2c_write(0x7030, 0x49); + i2c_write(0x7024, 0x01); + i2c_write(0x7030, 0x19); + i2c_write(0x7026, 0xcc); + i2c_write(0x7030, 0x29); + i2c_write(0x7026, 0xdd); + i2c_write(0x7030, 0x39); + i2c_write(0x7026, 0xef); + i2c_write(0x7030, 0x4a); + i2c_write(0x7024, 0x01); + i2c_write(0x7030, 0x1a); + i2c_write(0x7026, 0xcc); + i2c_write(0x7030, 0x2a); + i2c_write(0x7026, 0xdd); + i2c_write(0x7030, 0x3a); + i2c_write(0x7026, 0xef); + i2c_write(0x7030, 0x4b); + i2c_write(0x7024, 0x01); + i2c_write(0x7030, 0x1b); + i2c_write(0x7026, 0xcc); + i2c_write(0x7030, 0x2b); + i2c_write(0x7026, 0xdd); + i2c_write(0x7030, 0x3b); + i2c_write(0x7026, 0xef); + i2c_end_block(); + i2c_exec(); +} + +static void mask_7203(void) +{ + i2c_init(1); + i2c_mask(0x7203, 0x00, 0x80); + i2c_exec(); +} + +static void setHdmiBasicVideoConfigFlava3(const struct drm_display_mode *mode) +{ + u8 vic = drm_match_cea_mode(mode); + int hz = drm_mode_vrefresh(mode); + + i2c_init(1); + i2c_mask(0x7021, 0x00, 0xf0); + i2c_delay(500); + i2c_begin_block(); + i2c_write(0x100c, 0x01); + i2c_write_data(0x68a0, (u8[]){0x96, 0x04}, 2); + i2c_write(0x7005, 0x80); + i2c_write(0x7019, 0x00); + i2c_write(0x100c, 0x01); + i2c_write(0x7005, 0x80); + i2c_write(0x7009, 0x00); + i2c_write(0x7040, 0x42); + i2c_write(0x7225, 0x28); + if (vic == 16 || vic == 63) { + /* Set VIC and content type */ + i2c_write_data(0x7227, (u8[]){vic, 0x00}, 2); + i2c_write_data(0x7070, (u8[]){vic, vic, 0x00, 0x00, 0x00, 0x00}, 6); + } else if (mode->hdisplay == 2560 && mode->vdisplay == 1440) { + /* Set VIC and content type */ + i2c_write_data(0x7227, (u8[]){0x04, 0x00}, 2); + i2c_write_data(0x7070, (u8[]){0x00, 0x00, 0x00, 0x00, 0x00, 0xfb}, 6); + } else if (vic == 97) { + /* Set VIC and content type */ + i2c_write_data(0x7227, (u8[]){0x06, 0x00}, 2); + i2c_write_data(0x7070, (u8[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 6); + } + i2c_write(0x70c0, 0xdc); + i2c_write(0x621b, 0x00); + i2c_write(0x629a, 0x00); + i2c_write_data(0x70c4, (u8[]){0x08, 0x08}, 2); + i2c_write(0x70c2, 0x00); + i2c_write(0x70fe, 0x02); + i2c_write(0x70c3, 0x00); + i2c_write(0x7018, (tmds_polarity == 1) << 1); + if (tmds_ch_swap == 1) { + i2c_end_block(); + i2c_mask(0x701a, 0xb1, 0xff); + i2c_begin_block(); + } + i2c_write(0x10e7, 0xff); + i2c_write(0x7202, 0x20); + if (vic == 97) { + i2c_write(0x7072, 0x01); + i2c_write(0x7074, 0x07); + i2c_write(0x7206, 0x80); + i2c_write(0x7203, 0x60); + i2c_write(0x7011, 0xff); + } else { + i2c_write(0x7203, 0x60); + i2c_write(0x7011, 0xd5); + } + i2c_end_block(); + i2c_waitclear(0x7011, 0xff); + i2c_exec(); +} + +static void setVideoAdditionalConfigFlava3(const struct drm_display_mode *mode) +{ + u8 vic = drm_match_cea_mode(mode); + + i2c_init(1); + i2c_waitset(0x10e7, 0x80); + if (vic == 97) { + /* Set VIC */ + i2c_mask(0x7227, vic, 0xff); + } + /* Enable IT content */ + i2c_mask(0x7226, 1 << 7, 0x80); + /* Set content type (game) */ + i2c_mask(0x7228, 3 << 4, 0x30); + i2c_write(0x7204, 0x40); + i2c_waitclear(0x7204, 0x40); + i2c_delay(10); + i2c_begin_block(); + if (vic == 97) { + i2c_write(0x7019, 0x01); + } else { + i2c_write(0x7019, 0x00); + } + i2c_write(0x7419, 0x05); + i2c_write(0x740a, 0xff); + i2c_end_block(); + i2c_waitclear(0x740a, 0xff); + i2c_begin_block(); + i2c_write(0x7404, 0x00); + i2c_write(0x7a88, 0xff); + i2c_end_block(); + i2c_waitclear(0x7a84, 0x01); + i2c_begin_block(); + i2c_write(0x7a8b, 0x05); + if (vic == 97) { + i2c_write(0x7c00, 0x03); + i2c_write_data(0x7a80, (u8[]){0xa8, 0x20, 0x00, 0x80}, 4); + } + i2c_end_block(); + if (vic == 97) { + i2c_waitclear(0x7a84, 0x01); + } + i2c_begin_block(); + i2c_write(0x7021, 0xff); + i2c_write(0x700a, 0x02); + i2c_write(0x705f, 0x80); + i2c_end_block(); + i2c_delay(700); + i2c_write(0x7a8b, 0x00); + i2c_cmd_5_3(0x01); + i2c_exec(); +} + +static void setHdmiVideoConfigFlava3(const struct drm_display_mode *mode) +{ + configParamFlava3Pre(); + configLinkTrainingFlava3(); + setHdmiBasicVideoConfigFlava3(mode); + initHdmiPhyForFlava3_1st(); + initHdmiPhyForFlava3_2nd(); + mask_7203(); + setVideoAdditionalConfigFlava3(mode); +} + +static void setHdmiAudioConfigBasic(int channels) +{ + i2c_init(2); + i2c_begin_block(); + i2c_write(0x62a0, 0x06); + i2c_write(0x62a7, 0x13); + i2c_write(0x62ac, 0x82); + i2c_write(0x62cb, 0x02); + i2c_write(0x62cb, 0x03); + i2c_write(0x62cb, 0x00); + i2c_write(0x70ad, 0x00); + i2c_write(0x70af, 0x07); + i2c_write(0x70a9, 0x5e); + i2c_end_block(); + i2c_mask(0x70af, 0x06, 0x06); + i2c_mask(0x70b3, 0x02, 0x0f); + i2c_mask(0x70ae, 0x80, 0xe0); + i2c_mask(0x70ae, max(1, channels - 1), 0x07); + i2c_mask(0x70ac, 0x01, 0x21); + i2c_mask(0x70ab, 0x81, 0x89); + i2c_mask(0x70a9, 0x08, 0x08); + i2c_exec(); +} + +static void setAudioConfigAdditional(int channels) +{ + u8 val = 0x00; + switch (channels) { + case 3: val = 0x02; break; + case 4: val = 0x03; break; + case 5: val = 0x09; break; + case 6: val = 0x0b; break; + case 7: val = 0x11; break; + case 8: val = 0x13; break; + } + i2c_init(2); + i2c_mask(0x70b0, 0x00, 0xff); + i2c_mask(0x70b1, 0x79, 0xff); + i2c_mask(0x70b2, 0x00, 0xff); + i2c_mask(0x70b3, 0x02, 0xff); + i2c_mask(0x70b4, 0x0b, 0x0f); + i2c_mask(0x70b5, 0x00, 0xff); + i2c_mask(0x70b6, 0x00, 0xff); + i2c_begin_block(); + i2c_write(0x10e7, 0xff); + i2c_write(0x7011, 0xa2); + i2c_end_block(); + i2c_waitset(0x10e7, 0xa2); + i2c_mask(0x7267, val, 0xff); + i2c_write(0x7204, 0x10); + i2c_waitclear(0x7204, 0x10); + i2c_write(0x10e7, 0xff); + i2c_mask(0x7203, 0x10, 0x10); + i2c_delay(30); + i2c_write(0x70a8, 0xc0); + i2c_exec(); +} + +static void sceHdmiSetAudioConfigFlava3(int channels) +{ + setHdmiAudioConfigBasic(channels); + setAudioConfigAdditional(channels); +} + +static void initVerde(void) +{ + i2c_init(0); + i2c_mask(0x105, 0x00, 0x03); + i2c_mask(0x104, 0x00, 0x02); + i2c_cmd_2_1(0x400, 0x00); + i2c_cmd_2_1(0x3261, 0x02); + i2c_begin_block(); + i2c_write(0x11, 0x03); + i2c_write(0x13, 0xff); + i2c_write_data(0x8000, (u8[]){0x00, 0x01, 0x07, 0x00}, 4); + i2c_write(0x108, 0x80); + i2c_write(0x9000, 0x01); + i2c_end_block(); + i2c_cmd_5_3(0x00); + i2c_exec(); +} + +static void linkConfigVerde(const struct drm_display_mode *mode) +{ + i2c_init(0); + i2c_mask(0x105, 0x00, 0x40); + if (mode->hdisplay == 2560 && mode->vdisplay == 1440) { + i2c_cmd_2_1(0x400, 0x03); + } + i2c_begin_block(); + i2c_write_data(0x9003, (u8[]){0x1e, 0x04, 0x01, 0x01, 0x00, 0x00, 0x00}, 7); + i2c_write(0x4002, 0x03); + i2c_end_block(); + i2c_exec(); +} + +static void configDpLinkTrainingVerde(void) +{ + i2c_init(0); + i2c_cmd_2_1(0x9002, 0x01); + i2c_waitset(0x4001, 0x02); + i2c_cmd_2_1(0x11, 0x01); + i2c_exec(); +} + +static void setTmdsConfigVerde(void) +{ + i2c_init(0); + i2c_cmd_2_1(0x9200, 0x00); + i2c_begin_block(); + i2c_write(0x9800, 0x00); + i2c_write(0x33b3, 0x1a); + i2c_write(0x9831, 0x80); + i2c_write_data(0x9810, (u8[]){0x00, 0x79, 0x00, 0x02, 0x0b, 0x00, 0x00}, 7); + i2c_end_block(); + i2c_waitclear(0x9830, 0x80); + i2c_cmd_2_1(0x9830, 0x80); + i2c_waitclear(0x9830, 0x80); + i2c_cmd_2_1(0x9830, 0x81); + i2c_waitclear(0x9830, 0x80); + i2c_waitclear(0x108, 0x10); + i2c_mask(0x108, 0x11, 0x17); + i2c_waitset(0x13, 0x40); + i2c_cmd_2_1(0x13, 0x40); + i2c_cmd_3_5(0x4001, 0x03); + i2c_cmd_2_1(0x11, 0x01); + i2c_exec(); +} + +static void setHdmiBasicVideoConfigVerde(const struct drm_display_mode *mode) +{ + u8 vic = drm_match_cea_mode(mode); + + i2c_init(0); + i2c_begin_block(); + if (vic == 16) { + i2c_write_data(0x3058, (u8[]){0x02, 0x0d, 0xef, 0x00, 0x28, 0x08, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 18); + } else if (mode->hdisplay == 2560 && mode->vdisplay == 1440) { + i2c_write_data(0x3058, (u8[]){0x02, 0x0d, 0xff, 0x00, 0x28, 0x08, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 18); + } else if (vic == 97) { + i2c_write_data(0x3058, (u8[]){0x02, 0x0d, 0x9e, 0x00, 0x28, 0x08, 0x61, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 18); + } + i2c_write_data(0x31d0, (u8[]){0x01, 0x19, 0x5f, 0x53, 0x43, 0x45, 0x49, 0x00, 0x00, 0x00, 0x00, 0x50, 0x53, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08}, 28); + i2c_end_block(); + i2c_begin_block(); + i2c_write_data(0x3033, (u8[]){0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 9); + i2c_write_data(0x307a, (u8[]){0x01, 0x0a, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00}, 8); + i2c_write_data(0x3000, (u8[]){0x56, 0xaa, 0x00, 0x24, 0x00, 0xa8, 0x00, 0x00, 0x08, 0x80}, 10); + i2c_end_block(); + i2c_cmd_2_1(0x300a, 0x01); + i2c_waitclear(0x300c, 0xf3); + i2c_waitclear(0x300d, 0xff); + i2c_waitclear(0x300e, 0xff); + i2c_waitclear(0x300f, 0xff); + i2c_waitclear(0x3010, 0xff); + i2c_waitclear(0x3011, 0xff); + i2c_waitset(0x13, 0x80); + i2c_cmd_2_1(0x13, 0x80); + i2c_mask(0x105, 0x01, 0x03); + i2c_delay(700); + i2c_cmd_5_3(0x01); + i2c_exec(); +} + +static void setHdmiVideoConfigVerde(const struct drm_display_mode *mode) +{ + linkConfigVerde(mode); + configDpLinkTrainingVerde(); + setTmdsConfigVerde(); + setHdmiBasicVideoConfigVerde(mode); +} + +static void setAudioConfigForVerde(int channels) +{ + i2c_init(2); + i2c_waitclear(0x102, 0x80); + i2c_cmd_2_1(0xf1, 0x01); + i2c_waitset(0xf2, 0x01); + i2c_waitset(0x16, 0x08); + i2c_cmd_2_1(0x16, 0x08); + i2c_begin_block(); + i2c_write(0x9800, 0x00); + i2c_write(0x33b3, 0x1a); + i2c_write(0x9831, 0x80); + i2c_write_data(0x9810, (u8[]){0x00, 0x79, 0x00, 0x02, 0x0b, 0x00, 0x00}, 7); + i2c_end_block(); + i2c_waitclear(0x9830, 0x80); + i2c_cmd_2_1(0x9830, 0x80); + i2c_waitclear(0x9830, 0x80); + i2c_cmd_2_1(0x9830, 0x81); + i2c_waitclear(0x9830, 0x80); + i2c_waitclear(0x108, 0x10); + i2c_mask(0x108, 0x10, 0x10); + i2c_waitclear(0x108, 0x10); + i2c_write_data(0x307a, (u8[]){0x01, 0x0a, 0x70, 0x01, 0x00, 0x00, 0x00, 0x00}, 8); + i2c_mask(0x3000, 0x40, 0xc0); + i2c_mask(0x3005, 0x80, 0xc0); + i2c_cmd_2_1(0x300a, 0x01); + i2c_waitset(0x13, 0x80); + i2c_cmd_2_1(0x13, 0x80); + i2c_exec(); +} + +static void sceHdmiSetAudioConfigVerde(int channels) +{ + setAudioConfigForVerde(channels); +} + +void sceHdmiInitVideoConfig(void) +{ + stopHdcpHw(); + if (hdmi_ic_type == HDMI_IC_TYPE_FLAVA3) { + sceDisableEncode(); + initIsrForFlava3(); + initDpForFlava3(); + configVSyncSettingFlava3(); + } else { + initVerde(); + } +} +EXPORT_SYMBOL(sceHdmiInitVideoConfig); + +void sceHdmiSetVideoConfig(const struct drm_display_mode *mode) +{ + if (hdmi_ic_type == HDMI_IC_TYPE_FLAVA3) { + setHdmiVideoConfigFlava3(mode); + } else { + setHdmiVideoConfigVerde(mode); + } +} +EXPORT_SYMBOL(sceHdmiSetVideoConfig); + +void sceHdmiDeviceSetVideoMute(int mute) +{ + i2c_init(4); + if (hdmi_ic_type == HDMI_IC_TYPE_FLAVA3) { + i2c_write(0x705f, (mute == 1) << 7); + } else { + i2c_mask(0x105, mute != 1, 0x03); + } + i2c_exec(); +} +EXPORT_SYMBOL(sceHdmiDeviceSetVideoMute); + +void sceHdmiSetAudioConfig(int channels) +{ + if (hdmi_ic_type == HDMI_IC_TYPE_FLAVA3) { + sceHdmiSetAudioConfigFlava3(channels); + } else { + sceHdmiSetAudioConfigVerde(channels); + } +} +EXPORT_SYMBOL(sceHdmiSetAudioConfig); + +void sceHdmiSetAudioMute(int mute) +{ + i2c_init(4); + if (hdmi_ic_type == HDMI_IC_TYPE_FLAVA3) { + i2c_mask(0x70a8, (mute == 1) << 2, 0x04); + } else { + i2c_cmd_5_5(mute == 1); + } + i2c_exec(); +} +EXPORT_SYMBOL(sceHdmiSetAudioMute); + +void sceHdmiOutputMode(void) +{ + i2c_init(4); + if (hdmi_ic_type == HDMI_IC_TYPE_FLAVA3) { + i2c_write(0x7005, 0x80); + } + i2c_exec(); +} +EXPORT_SYMBOL(sceHdmiOutputMode); + +int getHdmiConfiguration(void) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + int ret; + + msg->service_id = ICC_SERVICE_ID_GENERAL; + msg->msg_type = 0x16; + msg->length = ICC_MSG_MIN_SIZE; + msg->data[0] = 0x10; + + ret = icc_query(buf, buf); + if (ret) + return ret; + + hdmi_ic_type = (msg->data[0x3] == 1) | 2; + tmds_polarity = msg->data[0x4] == 1; + tmds_ch_swap = msg->data[0x5] == 1; + dp_polarity = msg->data[0x6]; + dp_ch_swap = msg->data[0x7]; + + pr_info("HDMI IC Type [%s]\n", hdmi_ic_type == HDMI_IC_TYPE_FLAVA3 ? "FLAVA3" : "VERDE"); + pr_info("TMDS Polarity [%s]\n", tmds_polarity ? "Reverse" : "Normal"); + pr_info("TMDS Ch Swap [%s]\n", tmds_ch_swap ? "Swap" : "Normal"); + pr_info("DP Polarity [0x%x]\n", dp_polarity); + pr_info("DP Ch Swap [0x%x]\n", dp_ch_swap); + + return 0; +} +EXPORT_SYMBOL(getHdmiConfiguration); + +bool isHdmiModeValid(const struct drm_display_mode *mode, int force_1080p) +{ + u8 vic = drm_match_cea_mode(mode); + + if (force_1080p) + return vic == 16; /* 1080p60 */ + + /* 1440p */ + if (mode->hdisplay == 2560 && mode->vdisplay == 1440) { + return mode->clock == 241500 || mode->clock == 241700; + } + + switch (vic) { + case 16: /* 1080p60 */ + case 63: /* 1080p120 */ + case 97: /* 2160p60 */ + return true; + } + + return false; +} +EXPORT_SYMBOL(isHdmiModeValid); + +const struct drm_edid *real_edid = NULL; + +static void fix_edid(u8 *edid) +{ + int i; + u32 sum = 0; + + /* For some reason, PS5 sets 0x01. */ + edid[0] = 0x00; + for (i = 0; i < 0x7f; i++) + sum += edid[i]; + edid[0x7f] = -sum & 0xff; +} + +void hdmi_notification_handler(struct icc_msg *msg) +{ + if (msg->data[1] == 0x02) { + fix_edid(&msg->data[4]); + real_edid = drm_edid_alloc(&msg->data[4], *(u16 *)&msg->data[2]); + pr_info("got real edid\n"); + sceHdmiOutputMode(); + } +} +EXPORT_SYMBOL(hdmi_notification_handler); diff --git a/drivers/ps5/mp1.c b/drivers/ps5/mp1.c new file mode 100644 index 000000000000..4af890c842a7 --- /dev/null +++ b/drivers/ps5/mp1.c @@ -0,0 +1,488 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include + +#define MP1_IOC_MAGIC 'M' + +#define MP1_BOOST_ENTER _IO(MP1_IOC_MAGIC, 1) +#define MP1_BOOST_EXIT _IO(MP1_IOC_MAGIC, 2) + +#define CPU_MHZ_MIN 3200 +#define CPU_MHZ_MAX 3500 + +#define GPU_MHZ_MIN 2000 +#define GPU_MHZ_MAX 2230 + +#define MSR_ACCESS_DIS BIT_ULL(62) + +#define MSR_DPM_CFG 0xC0011074 +#define MSR_DPM_WAC_ACC_INDEX 0xC0011076 +#define MSR_DPM_WAC_DATA 0xC0011077 + +#define MP1_C2PMSG_56 0x3b109e0 +#define MP1_C2PMSG_57 0x3b109e4 +#define MP1_C2PMSG_58 0x3b109e8 +#define MP1_C2PMSG_59 0x3b109ec +#define MP1_C2PMSG_66 0x3b10a08 +#define MP1_C2PMSG_72 0x3b10a20 +#define MP1_C2PMSG_81 0x3b10a44 +#define MP1_C2PMSG_82 0x3b10a48 +#define MP1_C2PMSG_90 0x3b10a68 +#define MP1_C2PMSG_96 0x3b10a80 +#define MP1_C2PMSG_98 0x3b10a88 + +#define PPSMC_MSG_ConfigureS3PwrOffRegisterAddressHigh 0x16 +#define PPSMC_MSG_ConfigureS3PwrOffRegisterAddressLow 0x17 +#define PPSMC_MSG_UniversalModeEntry 0x22 +#define PPSMC_MSG_UniversalModeExit 0x23 +#define PPSMC_MSG_SleepEntry 0x24 +#define PPSMC_MSG_GfxCacWeightOperation 0x2F +#define PPSMC_MSG_L3CacWeightOperation 0x30 + +struct mp1_msg { + u32 arg; + u32 resp; + u32 resp_val; + u32 extra_arg; + u32 extra; +}; + +struct bapm_param_set { + u64 dpm_wac[21]; + u32 l3_cacw[80]; + u32 gfx_cacw[88]; + u64 gfx_cacw_len; + u32 bapm_param[176][2]; +}; + +static const struct bapm_param_set bapm_param_set_1 = { + .dpm_wac = { + 0x0000bca79c8d0000, 0x0097000000000000, 0x007f0000000000ad, + 0x00930000c700bb00, 0x000000e0cad5ee00, 0x0000c60099ca00d1, + 0x00bab80000d8ff00, 0x000000000000a689, 0x0000b59d007300b1, + 0x0000009600ad0000, 0x00a000b1f8000000, 0x00000000d400b200, + 0x00a5000000980000, 0x0000969f00b49a00, 0xa48761a100b30000, + 0x8500869500008f00, 0x7a009700008400a1, 0x00000000a90031ac, + 0x00b7bd00a10000b5, 0xb000b2c8c3b1a500, 0xa600000000000000 + }, + .l3_cacw = { + [71] = 0x3ff80000 + }, + .gfx_cacw = { + [0] = 0x17, 0x0, 0xa1, + [5] = 0x3f0000, + [14] = 0x1c80000, + [19] = 0x22, 0x12, + [23] = 0x7019d, 0x28001e, + [28] = 0x35, 0x15d, 0x1ab, 0x7f0000, + [35] = 0xc4, + [49] = 0x310000, + [54] = 0x76 + }, + .gfx_cacw_len = 64, + .bapm_param = { + {1, 0x3d14a6f2}, {1, 0x00000000}, {1, 0x3ed4eb53}, {1, 0x3e16ae78}, + {1, 0xbe4d4746}, {1, 0x3f34470b}, {1, 0x37178941}, {1, 0x3f726e59}, + {1, 0x3f3ebeef}, {1, 0x00000000}, {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, + {1, 0x3d1582c2}, {1, 0x35937309}, {1, 0x3f0f45c5}, {1, 0x3ee17477}, + {1, 0x00000000}, {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x387ba882}, {1, 0x40b1089a}, {1, 0x41751b15}, {1, 0x4287d1bc}, + {1, 0x3fb89949}, {1, 0x411eefdf}, {1, 0xbc816b59}, {1, 0x3d41513a}, + [49] = + {1, 0x41751b15}, {1, 0x4287d1bc}, {1, 0x3fb89949}, {1, 0x412d973c}, + {1, 0xbc816b59}, {1, 0x3d41513a}, {1, 0x3e0654c8}, {1, 0xbe27b465}, + {1, 0x3f2d3daa}, {1, 0x41751b15}, {1, 0x4287d1bc}, {1, 0x3fb89949}, + {1, 0x4061d4cc}, {1, 0xbc816b59}, {1, 0x3d41513a}, {1, 0x3e97c980}, + {1, 0xbf1d9856}, {1, 0x3f828e45}, {1, 0x41751b15}, {1, 0x4287d1bc}, + {1, 0x3fb89949}, {1, 0x409c4b3c}, {1, 0xbc816b59}, {1, 0x3d41513a}, + {1, 0x3e7a6107}, {1, 0xbeedd766}, {1, 0x3f67aa70}, {1, 0x41751b15}, + {1, 0x4287d1bc}, {1, 0x3fb89949}, {1, 0x40ccf558}, {1, 0xbc816b59}, + {1, 0x3d41513a}, {1, 0x3e600a8a}, {1, 0xbecbe79c}, {1, 0x3f5b627c}, + {1, 0x41751b15}, {1, 0x4287d1bc}, {1, 0x3fb89949}, {1, 0x41050555}, + {1, 0xbc816b59}, {1, 0x3d41513a}, {1, 0x3e379205}, {1, 0xbe94367e}, + {1, 0x3f46233f}, {1, 0x3f726e59}, {1, 0x3f3ebeef}, {1, 0x00000000}, + {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0x3d14a6f2}, + {1, 0x00000000}, {1, 0x3ed4eb53}, {1, 0x3f726e59}, {1, 0x3f3ebeef}, + {1, 0x00000000}, {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x3d14a6f2}, {1, 0x00000000}, {1, 0x3ed4eb53}, {1, 0x3f726e59}, + {1, 0x3f3ebeef}, {1, 0x00000000}, {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, + {1, 0x3d1582c2}, {1, 0x3d14a6f2}, {1, 0x00000000}, {1, 0x3ed4eb53}, + {1, 0x3f726e59}, {1, 0x3f3ebeef}, {1, 0x00000000}, {1, 0x3f8e9ad0}, + {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0x3d14a6f2}, {1, 0x00000000}, + {1, 0x3ed4eb53}, {1, 0x3f726e59}, {1, 0x3f3ebeef}, {1, 0x00000000}, + {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0x3d14a6f2}, + {1, 0x00000000}, {1, 0x3ed4eb53}, {1, 0x3f0f45c5}, {1, 0x3ee17477}, + {1, 0x00000000}, {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x3f0f45c5}, {1, 0x3ee17477}, {1, 0x00000000}, {1, 0x3f8e9ad0}, + {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0x3f0f45c5}, {1, 0x3ee17477}, + {1, 0x00000000}, {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x3f0f45c5}, {1, 0x3ee17477}, {1, 0x00000000}, {1, 0x3f8e9ad0}, + {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0x3f0f45c5}, {1, 0x3ee17477}, + {1, 0x00000000}, {1, 0x3f8e9ad0}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x3c437be5}, {1, 0x00000000}, {1, 0x00000000}, {1, 0x00000000}, + {1, 0x00000000}, {1, 0x00000000}, {1, 0x00000000} + } +}; + +static const struct bapm_param_set bapm_param_set_2 = { + .dpm_wac = { + 0x0000c3adb08d0000, 0x00a800008d000000, 0xa000008e000000a6, + 0x00000000c900a500, 0xc8d000d3b8daea00, 0x0000d000a3d200dc, + 0x00bfc80000c6f100, 0x00fe00000000ad00, 0x0000abb300000000, + 0x00008600000000cf, 0x00ae0095ff000000, 0x000000000000ac00, + 0x00b00000008500ad, 0x0098849600b18000, 0xa2a38bac00b00000, + 0x97007479000092ab, 0x0095a30000008f00, 0x000000b5000000a0, + 0x0000c200a80000bd, 0x0000bcc1c4b2a300, 0xa700000000000000 + }, + .l3_cacw = { + [71] = 0x3ff80000, + }, + .gfx_cacw = { + [2] = 0xefa, + [6] = 0x7bf, + [12] = 0x14d10000, + [14] = 0x287b0000, + [20] = 0x2f2, + [22] = 0x1085ffff, 0xcd80e51, 0x4b86145a, + [27] = 0x15a7, + [29] = 0x13c2, 0x2d02, + [34] = 0x78ad0000, 0x2ea0, + [54] = 0x257d, 0x8c8, + [58] = 0x799e, + [63] = 0x152, + }, + .gfx_cacw_len = 64, + .bapm_param = { + {1, 0xbc22f028}, {1, 0x3e113314}, {1, 0xbe8d0750}, {1, 0x3e16ae78}, + {1, 0xbe4d4746}, {1, 0x3f34470b}, {1, 0x3704564c}, {1, 0x3f516a34}, + {1, 0x3f3fdd1c}, {1, 0x3f74f5de}, {1, 0x3dec9763}, {1, 0xbc2c0ab6}, + {1, 0x3d1582c2}, {1, 0x367468e6}, {1, 0x3f059935}, {1, 0x3ef4cd95}, + {1, 0x3f74f5de}, {1, 0x3d524dae}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x357db71b}, {1, 0x40b1089a}, {1, 0x41751b15}, {1, 0x4287d1bc}, + {1, 0x3fb89949}, {1, 0x411eefdf}, {1, 0xbc816b59}, {1, 0x3d41513a}, + [49] = + {1, 0x41751b15}, {1, 0x4287d1bc}, {1, 0x3fb89949}, {1, 0x412d973c}, + {1, 0xbc816b59}, {1, 0x3d41513a}, {1, 0x3e0654c8}, {1, 0xbe27b465}, + {1, 0x3f2d3daa}, {1, 0x41751b15}, {1, 0x4287d1bc}, {1, 0x3fb89949}, + {1, 0x4061d4cc}, {1, 0xbc816b59}, {1, 0x3d41513a}, {1, 0x3e97c980}, + {1, 0xbf1d9856}, {1, 0x3f828e45}, {1, 0x41751b15}, {1, 0x4287d1bc}, + {1, 0x3fb89949}, {1, 0x409c4b3c}, {1, 0xbc816b59}, {1, 0x3d41513a}, + {1, 0x3e7a6107}, {1, 0xbeedd766}, {1, 0x3f67aa70}, {1, 0x41751b15}, + {1, 0x4287d1bc}, {1, 0x3fb89949}, {1, 0x40ccf558}, {1, 0xbc816b59}, + {1, 0x3d41513a}, {1, 0x3e600a8a}, {1, 0xbecbe79c}, {1, 0x3f5b627c}, + {1, 0x41751b15}, {1, 0x4287d1bc}, {1, 0x3fb89949}, {1, 0x41050555}, + {1, 0xbc816b59}, {1, 0x3d41513a}, {1, 0x3e379205}, {1, 0xbe94367e}, + {1, 0x3f46233f}, {1, 0x3f96c5af}, {1, 0x3eb99add}, {1, 0x3f85bb54}, + {1, 0x3e6a30f6}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0xbbda394d}, + {1, 0x3dff4eb1}, {1, 0xbe8b186c}, {1, 0x3f8fbf3f}, {1, 0x3ee87500}, + {1, 0x3f7c5aff}, {1, 0x3e92470e}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x396640ab}, {1, 0x3dad4b04}, {1, 0xbe6283c5}, {1, 0x3f8051ba}, + {1, 0x3f13f766}, {1, 0x3f87a42b}, {1, 0x3e52acf5}, {1, 0xbc2c0ab6}, + {1, 0x3d1582c2}, {1, 0xbbd8e837}, {1, 0x3e005ec6}, {1, 0xbe8c6197}, + {1, 0x3f61d86e}, {1, 0x3f276f79}, {1, 0x3f7b0bf0}, {1, 0x3e25ca59}, + {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0xbbc01a0e}, {1, 0x3dfb13b3}, + {1, 0xbe84dd83}, {1, 0x3fa32142}, {1, 0x3ea341fd}, {1, 0x3f85d724}, + {1, 0x3e8c3c1d}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0xbaa01624}, + {1, 0x3dbebfaf}, {1, 0xbe6f57f4}, {1, 0x3f43c147}, {1, 0x3e70fae5}, + {1, 0x3f85bb54}, {1, 0x3dd02b85}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x3f364cb6}, {1, 0x3e936695}, {1, 0x3f7c5aff}, {1, 0x3e020645}, + {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0x3f226119}, {1, 0x3ebb3dcd}, + {1, 0x3f87a42b}, {1, 0x3dbb4468}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x3f1302b3}, {1, 0x3ed9fa9b}, {1, 0x3f7b0bf0}, {1, 0x3d935e88}, + {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, {1, 0x3f4cc495}, {1, 0x3e4cedab}, + {1, 0x3f85d724}, {1, 0x3df94e6d}, {1, 0xbc2c0ab6}, {1, 0x3d1582c2}, + {1, 0x3c437be5}, {1, 0x3f3de47f}, {1, 0x3f40c129}, {1, 0x3f3cc9e7}, + {1, 0x3f41350f}, {1, 0x3f3dcec6}, {1, 0x3f3e1c51} + } +}; + +static u32 pcirc_smn_read(u32 reg) +{ + u32 val = 0; + if (amd_smn_read(0, reg, &val)) { + panic("amd_smn_read failed"); + } + return val; +} + +static void pcirc_smn_write(u32 reg, u32 val) +{ + if (amd_smn_write(0, reg, val)) { + panic("amd_smn_write failed"); + } +} + +static int mp1fw_waitmsg(u32 reg, u8 msgid) +{ + int timeout = 0; + + while (!pcirc_smn_read(reg)) { + udelay(10); + if (++timeout == 200000) { + return 1; + } + } + + if (timeout >= 10000) { + pr_err("[MP1] wait %d msec (msgid=0x%X)\n", timeout / 100, msgid); + return 0; + } + + return 0; +} + +static int mp1fw_sendmsg(struct mp1_msg *msg, u8 msgid) +{ + if (mp1fw_waitmsg(MP1_C2PMSG_90, msgid)) { + pr_err("[MP1ERROR] : %s: Error : busy msgid=0x%X, arg=0x%08X\n", __func__, msgid, msg->arg); + return -EBUSY; + } + + pcirc_smn_write(MP1_C2PMSG_90, 0); + pcirc_smn_write(MP1_C2PMSG_82, msg->arg); + if (msg->extra == 1) + pcirc_smn_write(MP1_C2PMSG_81, msg->extra_arg); + pcirc_smn_write(MP1_C2PMSG_66, msgid); + + if (mp1fw_waitmsg(MP1_C2PMSG_90, msgid)) { + pr_err("[MP1ERROR] : %s: Error : retry over msgid=0x%X, arg=0x%08X\n", __func__, msgid, msg->arg); + return -EBUSY; + } + + u32 resp = pcirc_smn_read(MP1_C2PMSG_90); + u32 resp_val = pcirc_smn_read(MP1_C2PMSG_82); + if (resp != 1) { + pr_err("[MP1ERROR] : %s: invalid response msgid=0x%X, resp=0x%08X\n", __func__, msgid, resp); + return -EINVAL; + } + + msg->resp = resp; + msg->resp_val = resp_val; + + return 0; +} + +static int mp1fw_test_sendmsg(struct mp1_msg *msg, uint8_t msgid) +{ + if (mp1fw_waitmsg(MP1_C2PMSG_96, msgid)) { + printk("[MP1ERROR] : %s: Error : busy msgid=0x%X, arg=0x%08X\n", __func__, msgid, msg->arg); + return -EBUSY; + } + pcirc_smn_write(MP1_C2PMSG_96, 0); + pcirc_smn_write(MP1_C2PMSG_98, msg->arg); + pcirc_smn_write(MP1_C2PMSG_72, msgid); + if (mp1fw_waitmsg(MP1_C2PMSG_96, msgid)) { + printk("[MP1ERROR] : %s: retry over msgid=0x%X, arg=0x%08X\n", __func__, msgid, msg->arg); + return -EBUSY; + } + u32 resp = pcirc_smn_read(MP1_C2PMSG_96); + u32 resp_val = pcirc_smn_read(MP1_C2PMSG_98); + if ((msgid != 0x75 && resp != 1) || (msgid == 0x75 && resp != 1 && resp != 0xf8)) { + printk("[MP1ERROR] : %s: invalid response msgid=0x%X, resp=0x%08X\n", __func__, msgid, resp); + return -EINVAL; + } + + msg->resp = resp; + msg->resp_val = resp_val; + + return 0; +} + +static int mp1_set_wc_cpu(int mode) +{ + struct mp1_msg msg = {}; + msg.arg = mode; + return mp1fw_test_sendmsg(&msg, 0x9b); +} + +static int mp1_get_wc_cpu(int *mode) +{ + struct mp1_msg msg = {}; + int ret; + ret = mp1fw_test_sendmsg(&msg, 0x9c); + *mode = msg.resp_val; + return ret; +} + +static int mp1_configure_s3_pwr_off_reg_addr_high(u64 addr) +{ + struct mp1_msg msg = {}; + msg.arg = addr >> 32; + return mp1fw_sendmsg(&msg, PPSMC_MSG_ConfigureS3PwrOffRegisterAddressHigh); +} + +static int mp1_configure_s3_pwr_off_reg_addr_low(u64 addr) +{ + struct mp1_msg msg = {}; + msg.arg = addr & 0xffffffff; + return mp1fw_sendmsg(&msg, PPSMC_MSG_ConfigureS3PwrOffRegisterAddressLow); +} + +void mp1_set_pm1_addr(u64 addr) +{ + mp1_configure_s3_pwr_off_reg_addr_high(addr); + mp1_configure_s3_pwr_off_reg_addr_low(addr); +} +EXPORT_SYMBOL(mp1_set_pm1_addr); + +int mp1_set_sleep_entry(void) +{ + struct mp1_msg msg = {}; + msg.arg = 3; /* S3 */ + return mp1fw_sendmsg(&msg, PPSMC_MSG_SleepEntry); +} +EXPORT_SYMBOL(mp1_set_sleep_entry); + +static int mp1_universal_mode_enter(u32 *params) +{ + struct mp1_msg msg = {}; + + pcirc_smn_write(MP1_C2PMSG_56, params[1]); + pcirc_smn_write(MP1_C2PMSG_57, params[2]); + pcirc_smn_write(MP1_C2PMSG_58, params[3]); + pcirc_smn_write(MP1_C2PMSG_59, params[4]); + + msg.arg = params[0]; + return mp1fw_sendmsg(&msg, PPSMC_MSG_UniversalModeEntry); +} + +static int mp1_universal_mode_exit(void) +{ + struct mp1_msg msg = {}; + return mp1fw_sendmsg(&msg, PPSMC_MSG_UniversalModeExit); +} + +static int mp1_bapm_set_gfx_cacw(int index, int weight) +{ + struct mp1_msg msg = {}; + msg.arg = index | 0x20000; + msg.extra_arg = weight; + msg.extra = 1; + return mp1fw_sendmsg(&msg, PPSMC_MSG_GfxCacWeightOperation); +} + +static int mp1_bapm_set_l3_cacw(int index, int weight) +{ + struct mp1_msg msg = {}; + msg.arg = index | 0x20000; + msg.extra_arg = weight; + msg.extra = 1; + return mp1fw_sendmsg(&msg, PPSMC_MSG_L3CacWeightOperation); +} + +static int mp1_bapm_write_param(int index, int param) +{ + struct mp1_msg msg = {}; + msg.arg = index; + msg.extra_arg = param; + msg.extra = 1; + return mp1fw_sendmsg(&msg, 0x33); +} + +static void update_bapm_weights_smp(void *info) +{ + u64 msr_dpm_cfg; + int i; + + rdmsrq(MSR_DPM_CFG, msr_dpm_cfg); + wrmsrq(MSR_DPM_CFG, msr_dpm_cfg & ~MSR_ACCESS_DIS); + + for (i = 0; i < 21; i++) { + wrmsrq(MSR_DPM_WAC_ACC_INDEX, i); + wrmsrq(MSR_DPM_WAC_DATA, bapm_param_set_2.dpm_wac[i]); + } + + wrmsrq(MSR_DPM_CFG, msr_dpm_cfg); +} + +static void mp1_set_bapm_param_set_all(void) +{ + int i; + + on_each_cpu(update_bapm_weights_smp, NULL, 1); + + for (i = 0; i < 80; i++) { + mp1_bapm_set_l3_cacw(i, bapm_param_set_2.l3_cacw[i]); + } + + for (i = 0; i < bapm_param_set_2.gfx_cacw_len; i++) { + mp1_bapm_set_gfx_cacw(i, bapm_param_set_2.gfx_cacw[i]); + } + + for (i = 0; i < 176; i++) { + if (bapm_param_set_2.bapm_param[i][0]) + mp1_bapm_write_param(i, bapm_param_set_2.bapm_param[i][1]); + } +} + +static long mp1_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case MP1_BOOST_ENTER: + { + u32 params[5]; + params[0] = 0x0; + params[1] = 0x449cd; + params[2] = (GPU_MHZ_MIN << 16) | CPU_MHZ_MIN; + params[3] = (GPU_MHZ_MAX << 16) | CPU_MHZ_MAX; + params[4] = 0x25c6a3c8; + return mp1_universal_mode_enter(params); + } + + case MP1_BOOST_EXIT: + return mp1_universal_mode_exit(); + + default: + return -ENOTTY; + } +} + +static const struct file_operations mp1_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = mp1_ioctl, +}; + +static struct miscdevice mp1_misc_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "mp1", + .fops = &mp1_fops, +}; + +static int __init mp1_init(void) +{ + int ret; + int mode = 0; + + mp1_universal_mode_exit(); + + pr_info("Set BAPM params\n"); + mp1_get_wc_cpu(&mode); + if (mode != 1) { + mp1_set_wc_cpu(1); + } + mp1_set_bapm_param_set_all(); + + ret = misc_register(&mp1_misc_device); + if (ret) + return ret; + + return 0; +} + +static void __exit mp1_exit(void) +{ + misc_deregister(&mp1_misc_device); + mp1_universal_mode_exit(); +} + +module_init(mp1_init); +module_exit(mp1_exit); + +MODULE_AUTHOR("Andy Nguyen"); +MODULE_DESCRIPTION("PlayStation 5 MP1 SMU driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ps5/spcie.c b/drivers/ps5/spcie.c new file mode 100644 index 000000000000..e02c074ee0b1 --- /dev/null +++ b/drivers/ps5/spcie.c @@ -0,0 +1,1149 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include "autoservo_param.h" + +#define PCI_DEVICE_ID_SPCIE 0x9107 +#define SPCIE_SUBFUNC_ICC 12 +#define NUM_IRQS 16 + +#define ICC_QUERY_OFFSET 0 +#define ICC_REPLY_OFFSET 0x800 + +#define ICC_DOORBELL_OFFSET 0x108000 + +#define ICC_REG_SOW 0x7f0 +#define ICC_REG_SOR 0x7f4 +#define ICC_REG_EMW 0xff0 +#define ICC_REG_EMR 0xff4 + +#define ICC_REG_DOORBELL 0x04 +#define ICC_REG_INTR_STATUS 0x14 +#define ICC_REG_INTR_MASK 0x24 + +#define ICC_SEND 0x01 +#define ICC_ACK 0x02 + +#define ICC_MSG_TYPE_REPLY 0x4000 +#define ICC_MSG_TYPE_NOTIF 0x8000 + +#define ICC_TIMEOUT_MSECS 12000 + +#define ICC_IOC_MAGIC 'I' + +#define ICC_FAN_CHANGE_SERVO_PATTERN _IOW(ICC_IOC_MAGIC, 1, u8) + +#define GDDR6_SAMSUNG 0x01 +#define GDDR6_HYNIX 0x06 +#define GDDR6_MICRON 0x0f + +#define BOARD_MASK_A 0xffffffffffffff00 +#define BOARD_MASK_B 0xffffffffff00ff00 + +#define BOARD_SANCARLO_1 0x2001010104010400 +#define BOARD_SANCARLO_2 0x2001010104010500 +#define BOARD_A_EIGER_1 0x3002010104010400 +#define BOARD_A_EIGER_2 0x3002010104010500 +#define BOARD_A_DENALI_1 0x3002010104030400 +#define BOARD_A_DENALI_2 0x3002010104030500 +#define BOARD_B_EIGER_DENALI_1 0x3002020101000400 +#define BOARD_B_EIGER_DENALI_2 0x3002020101000500 +#define BOARD_D_EIGER_DENALI_1 0x3002040101000400 +#define BOARD_D_EIGER_DENALI_2 0x3002040101000500 + +struct spcie_dev; + +struct spcie_icc_dev { + struct pci_dev *pdev; + struct spcie_dev *sdev; + struct input_dev *idev; + struct mutex lock; + wait_queue_head_t wq; + void __iomem *icc_doorbell_base; + void __iomem *icc_base; + u16 icc_send_xtn_id; + u8 notification[ICC_MSG_MAX_SIZE]; + u16 notification_length; + u8 reply[ICC_MSG_MAX_SIZE]; + u16 reply_length; + bool reply_ready; +}; + +struct spcie_dev { + struct pci_dev *pdev; + struct spcie_icc_dev *icc_dev; + void __iomem *bar2; + void __iomem *pervasive0; +}; + +struct icc_notification { + u8 service_id; + u8 notification[ICC_MSG_MAX_SIZE]; +}; + +#define ICC_NOTIFICATION_FIFO_SIZE 32 +static DEFINE_KFIFO(icc_notification_fifo, struct icc_notification, ICC_NOTIFICATION_FIFO_SIZE); +static DEFINE_SPINLOCK(icc_notification_lock); +static struct work_struct icc_notification_work; + +static struct spcie_dev *sdev; +static struct spcie_icc_dev *icc_dev; + +static bool spcie_initialized = false; +static u32 spcie_chip_revision_id = 0; + +static const u8 indicator_white_dim[] = { + 0x03, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x11, + 0x01, 0x00, 0x20, 0x00, 0x01, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00 +}; + +static const u8 indicator_white_medium[] = { + 0x03, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x11, + 0x01, 0x00, 0x5F, 0x00, 0x01, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00 +}; + +static const u8 indicator_white_bright[] = { + 0x03, 0x00, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x11, + 0x01, 0x00, 0xFF, 0x00, 0x01, 0x00, 0x12, 0x01, 0x00, 0x00, 0x00, 0x02, + 0x00 +}; + +static void bootparam_get_config_board_id(u64 *board_id) +{ + void __iomem *bootparam = ioremap(0x9b000, 0x2000); + *board_id = readq(bootparam + 0x328); + iounmap(bootparam); +} + +static void bootparam_get_config_gddr6_id(u16 *gddr6_id) +{ + void __iomem *bootparam = ioremap(0x9b000, 0x2000); + *gddr6_id = readw(bootparam + 0x1184); + iounmap(bootparam); +} + +static u16 icc_checksum(struct icc_msg *msg) +{ + u16 i; + u16 checksum = 0; + for (i = 0; i < msg->length; i++) + checksum += ((u8 *)msg)[i]; + return checksum; +} + +static int icc_send(u8 *query) +{ + struct icc_msg *msg; + + msg = (struct icc_msg *)query; + if (msg->length < ICC_MSG_MIN_SIZE) + msg->length = ICC_MSG_MIN_SIZE; + msg->magic = 0x42; + msg->unk_04 = 3; + msg->id = icc_dev->icc_send_xtn_id++; + msg->checksum = icc_checksum(msg); + + writew(0, icc_dev->icc_base + ICC_REG_SOR); + + for (u16 i = 0; i < msg->length; i++) + writeb(query[i], icc_dev->icc_base + ICC_QUERY_OFFSET + i); + + writew(1, icc_dev->icc_base + ICC_REG_SOW); + + writel(ICC_SEND, icc_dev->icc_doorbell_base + ICC_REG_DOORBELL); + + return 0; +} + +int icc_query(u8 *query, u8 *reply) +{ + struct icc_msg *msg; + u16 checksum, expected; + int ret; + + mutex_lock(&icc_dev->lock); + + icc_dev->reply_ready = false; + + icc_send(query); + + ret = wait_event_timeout(icc_dev->wq, icc_dev->reply_ready, + msecs_to_jiffies(ICC_TIMEOUT_MSECS)); + if (ret == 0) { + dev_err(&icc_dev->pdev->dev, "timeout\n"); + mutex_unlock(&icc_dev->lock); + return -ETIMEDOUT; + } + + memcpy(reply, icc_dev->reply, icc_dev->reply_length); + + msg = (struct icc_msg *)reply; + expected = msg->checksum; + msg->checksum = 0; + checksum = icc_checksum(msg); + if (checksum != expected) { + dev_err(&icc_dev->pdev->dev, "checksum mismatch\n"); + mutex_unlock(&icc_dev->lock); + return -EINVAL; + } + + mutex_unlock(&icc_dev->lock); + return 0; +} +EXPORT_SYMBOL(icc_query); + +int icc_nvs_write(u32 partition, u16 offset, u16 length, const void *data) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_NVS; + msg->msg_type = 0; + msg->length = sizeof(*msg) + 6 + length; + msg->data[0] = 0; + msg->data[1] = partition; + *(u16 *)&msg->data[2] = offset; + *(u16 *)&msg->data[4] = length; + memcpy(&msg->data[6], data, length); + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_nvs_write); + +int icc_nvs_read(u32 partition, u16 offset, u16 length, void *data) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + int ret; + + msg->service_id = ICC_SERVICE_ID_NVS; + msg->msg_type = 1; + msg->length = ICC_MSG_MIN_SIZE; + msg->data[0] = 0; + msg->data[1] = partition; + *(u16 *)&msg->data[2] = offset; + *(u16 *)&msg->data[4] = length; + + ret = icc_query(buf, buf); + if (ret) + return ret; + + memcpy(data, &msg->data[2], length); + + return 0; +} +EXPORT_SYMBOL(icc_nvs_read); + +int icc_usbc_set_pdcon_op_mode(u8 PortId, u8 OpMode) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_USBC; + msg->msg_type = 0x10; + msg->length = ICC_MSG_MIN_SIZE; + msg->data[0] = PortId; + msg->data[1] = OpMode; + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_usbc_set_pdcon_op_mode); + +int icc_configuration_set_cpu_info_bit(u8 *bit) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_GENERAL; + msg->msg_type = 0x10; + msg->length = ICC_MSG_MIN_SIZE; + msg->data[0] = bit[1]; + msg->data[1] = bit[0]; + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_configuration_set_cpu_info_bit); + +int icc_configuration_clear_cpu_info_bit(void) +{ + u8 bit[2]; + int ret; + + bit[0] = 0; + bit[1] = 0; + ret = icc_configuration_set_cpu_info_bit(bit); + if (ret) + return ret; + + bit[0] = 0; + bit[1] = 1; + ret = icc_configuration_set_cpu_info_bit(bit); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(icc_configuration_clear_cpu_info_bit); + +__noreturn void icc_power_suspend(int keep) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_POWER; + msg->msg_type = 1; + msg->length = ICC_MSG_MIN_SIZE; + msg->data[0] = 1; // with eap + msg->data[1] = 1; + msg->data[2] = 1; + msg->data[3] = 0; + msg->data[4] = 1; + *(u16 *)&msg->data[5] = (2 * (keep != 0)) | 0x30; + *(u16 *)&msg->data[7] = 0; + + icc_query(buf, buf); + local_irq_disable(); + wbinvd(); + mp1_set_sleep_entry(); + while (1); +} +EXPORT_SYMBOL(icc_power_suspend); + +__noreturn void icc_power_shutdown(void) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + icc_configuration_clear_cpu_info_bit(); + + msg->service_id = ICC_SERVICE_ID_POWER; + msg->msg_type = 1; + msg->length = ICC_MSG_MIN_SIZE; + msg->data[0] = 0; + msg->data[1] = 0; // shutdown + msg->data[2] = 2; // depth + msg->data[3] = 0; // cause + msg->data[4] = 1; // hand + *(u32 *)&msg->data[5] = 0; + + icc_query(buf, buf); + while (1); +} +EXPORT_SYMBOL(icc_power_shutdown); + +__noreturn void icc_power_reboot(void) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + icc_configuration_clear_cpu_info_bit(); + + msg->service_id = ICC_SERVICE_ID_POWER; + msg->msg_type = 1; + msg->length = ICC_MSG_MIN_SIZE; + msg->data[0] = 0; + msg->data[1] = 1; // reboot + msg->data[2] = 2; // depth + msg->data[3] = 0; // cause + msg->data[4] = 1; // hand + *(u32 *)&msg->data[5] = 0; + + icc_query(buf, buf); + while (1); +} +EXPORT_SYMBOL(icc_power_reboot); + +int icc_button_enable_notification(u8 type, u8 enable) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_BUTTON; + msg->msg_type = 1; + msg->length = 0x20; + msg->data[0] = type; + msg->data[1] = enable; + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_button_enable_notification); + +int icc_button_enable_all_notifications(u8 enable) +{ + int ret; + + /* power button */ + ret = icc_button_enable_notification(0, enable); + if (ret) + return ret; + + /* eject button */ + ret = icc_button_enable_notification(1, enable); + if (ret) + return ret; + + /* reset button */ + ret = icc_button_enable_notification(2, enable); + if (ret) + return ret; + + return 0; +} +EXPORT_SYMBOL(icc_button_enable_all_notifications); + +int icc_thermal_enable_notification(u8 enable) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_THERMAL; + msg->msg_type = 2; + msg->length = 0x20; + msg->data[0] = enable; + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_thermal_enable_notification); + +int icc_device_power_control(u8 device, u8 state) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_DEVICE; + msg->msg_type = 0; + msg->length = 0x20; + msg->data[0] = device; + msg->data[1] = state; + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_device_power_control); + +int icc_device_power_get(u8 device, u8 *state) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + int ret; + + msg->service_id = ICC_SERVICE_ID_DEVICE; + msg->msg_type = 1; + msg->length = 0x20; + msg->data[0] = device; + + ret = icc_query(buf, buf); + if (ret) + return ret; + + *state = msg->data[2]; + + return 0; +} +EXPORT_SYMBOL(icc_device_power_get); + +int icc_indicator_set_led(const u8 setting[], size_t setting_size) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_INDICATOR; + msg->msg_type = 0x20; + msg->length = sizeof(*msg) + setting_size; + memcpy(msg->data, setting, setting_size); + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_indicator_set_led); + +int icc_indicator_set_led_white(u8 level) +{ + switch (level) { + case 0: + return icc_indicator_set_led(indicator_white_dim, sizeof(indicator_white_dim)); + case 1: + return icc_indicator_set_led(indicator_white_medium, sizeof(indicator_white_medium)); + case 2: + return icc_indicator_set_led(indicator_white_bright, sizeof(indicator_white_bright)); + default: + return -EINVAL; + } +} +EXPORT_SYMBOL(icc_indicator_set_led_white); + +int icc_fan_change_servo_pattern(u8 pattern) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_FAN; + msg->msg_type = 0xb; + msg->length = 0x20; + msg->data[0] = pattern; + msg->data[1] = pattern; + msg->data[2] = pattern; + msg->data[3] = pattern; + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_fan_change_servo_pattern); + +int icc_fan_update_param(const u8 *param) +{ + u8 buf[ICC_MSG_MAX_SIZE] = {}; + struct icc_msg *msg = (struct icc_msg *)buf; + + msg->service_id = ICC_SERVICE_ID_FAN; + msg->msg_type = 0xe; + msg->length = sizeof(*msg) + 0x6ae; + memcpy(msg->data, param, 0x6ae); + + return icc_query(buf, buf); +} +EXPORT_SYMBOL(icc_fan_update_param); + +int icc_fan_update_autoservo_param(void) +{ + u64 board_id, board_mask_a, board_mask_b; + u16 gddr6_id; + u8 gddr6_vendor, gddr6_revision; + const char *board_name = NULL; + const char *gddr6_name = NULL; + const u8 *param = NULL; + int ret; + + bootparam_get_config_board_id(&board_id); + board_id = be64_to_cpu(board_id); + board_mask_a = board_id & BOARD_MASK_A; + board_mask_b = board_id & BOARD_MASK_B; + + bootparam_get_config_gddr6_id(&gddr6_id); + gddr6_vendor = gddr6_id & 0xf; + gddr6_revision = gddr6_id >> 4; + + if (board_mask_a == BOARD_SANCARLO_1 || board_mask_a == BOARD_SANCARLO_2) { + board_name = "Sancarlo"; + param = autoservo_param_sancarlo; + } else if (board_mask_a == BOARD_A_EIGER_1 || board_mask_a == BOARD_A_EIGER_2) { + board_name = "A-Eiger"; + switch (gddr6_vendor) { + case GDDR6_SAMSUNG: + gddr6_name = "Samsung"; + param = autoservo_param_a_eiger_samsung; + break; + case GDDR6_HYNIX: + gddr6_name = "Hynix"; + param = autoservo_param_a_eiger_hynix; + break; + case GDDR6_MICRON: + gddr6_name = "Micron"; + param = autoservo_param_a_eiger_micron; + break; + default: + pr_info("FanServo: %s Unknown Vendor 0x%x\n", board_name, gddr6_vendor); + goto not_updated; + } + } else if (board_mask_a == BOARD_A_DENALI_1 || board_mask_a == BOARD_A_DENALI_2) { + board_name = "A-Denali"; + switch (gddr6_vendor) { + case GDDR6_SAMSUNG: + gddr6_name = "Samsung"; + param = autoservo_param_a_denali_samsung; + break; + case GDDR6_HYNIX: + gddr6_name = "Hynix"; + param = autoservo_param_a_denali_hynix; + break; + case GDDR6_MICRON: + gddr6_name = "Micron"; + param = autoservo_param_a_denali_micron; + break; + default: + pr_info("FanServo: %s Unknown Vendor 0x%x\n", board_name, gddr6_vendor); + goto not_updated; + } + } else if (board_mask_b == BOARD_B_EIGER_DENALI_1 || board_mask_b == BOARD_B_EIGER_DENALI_2) { + board_name = "B-Eiger/Denali"; + if (gddr6_vendor == GDDR6_SAMSUNG && gddr6_revision == 8) { + gddr6_name = "Samsung D1x"; + param = autoservo_param_b_eiger_denali_samsung_d1x; + } else if (gddr6_vendor == GDDR6_SAMSUNG && gddr6_revision == 9) { + gddr6_name = "Samsung D1z"; + param = NULL; + } else if (gddr6_vendor == GDDR6_HYNIX && gddr6_revision == 0) { + gddr6_name = "Hynix 1x"; + param = autoservo_param_b_eiger_denali_hynix_1x_micron_120s; + } else if (gddr6_vendor == GDDR6_HYNIX && gddr6_revision == 1) { + gddr6_name = "Hynix 1y"; + param = autoservo_param_b_eiger_denali_hynix_1y_micron_130s; + } else if (gddr6_vendor == GDDR6_MICRON && gddr6_revision == 0) { + gddr6_name = "Micron 120s"; + param = autoservo_param_b_eiger_denali_hynix_1x_micron_120s; + } else if (gddr6_vendor == GDDR6_MICRON && gddr6_revision == 1) { + gddr6_name = "Micron 130s"; + param = autoservo_param_b_eiger_denali_hynix_1y_micron_130s; + } else { + pr_info("FanServo: %s Unknown Vendor/Revision 0x%x/0x%x\n", board_name, gddr6_vendor, gddr6_revision); + goto not_updated; + } + } else if (board_mask_b == BOARD_D_EIGER_DENALI_1 || board_mask_b == BOARD_D_EIGER_DENALI_2) { + board_name = "D-Eiger/Denali"; + if (gddr6_vendor == GDDR6_SAMSUNG && gddr6_revision == 9) { + gddr6_name = "Samsung D1z"; + param = autoservo_param_d_eiger_denali_samsung_d1z; + } else if (gddr6_vendor == GDDR6_HYNIX && gddr6_revision == 1) { + gddr6_name = "Hynix 1y"; + param = autoservo_param_d_eiger_denali_hynix_1y; + } else if (gddr6_vendor == GDDR6_MICRON && gddr6_revision == 1) { + gddr6_name = "Micron 130s"; + param = autoservo_param_d_eiger_denali_micron_130s_y31j; + } else if (gddr6_vendor == GDDR6_MICRON && gddr6_revision == 2) { + gddr6_name = "Micron Y31J"; + param = autoservo_param_d_eiger_denali_micron_130s_y31j; + } else { + pr_info("FanServo: %s Unknown Vendor/Revision 0x%x/0x%x\n", board_name, gddr6_vendor, gddr6_revision); + goto not_updated; + } + } else { + pr_info("FanServo: 0x%016llX\n", board_id); + goto not_updated; + } + + if (gddr6_name) + pr_info("FanServo: %s %s\n", board_name, gddr6_name); + else + pr_info("FanServo: %s\n", board_name); + + if (!param) + goto not_updated; + + ret = icc_fan_update_param(param); + if (ret) + pr_err("Error: %s: %d\n", __func__, ret); + + return ret; + +not_updated: + pr_info("FanServo: Not update\n"); + return 0; +} +EXPORT_SYMBOL(icc_fan_update_autoservo_param); + +static void button_notification_handler(struct icc_msg *msg) +{ + if (msg->msg_type == 0x8010) { // power button down + input_report_key(icc_dev->idev, KEY_POWER, 1); + input_sync(icc_dev->idev); + } else if (msg->msg_type == 0x8011) { // power button up + input_report_key(icc_dev->idev, KEY_POWER, 0); + input_sync(icc_dev->idev); + } +} + +static void icc_notification_work_func(struct work_struct *work) +{ + struct icc_msg *msg; + struct icc_notification entry; + + while (kfifo_out_spinlocked(&icc_notification_fifo, &entry, 1, &icc_notification_lock)) { + msg = (struct icc_msg *)entry.notification; + if (entry.service_id == ICC_SERVICE_ID_HDMI) { + hdmi_notification_handler(msg); + } else if (entry.service_id == ICC_SERVICE_ID_BUTTON) { + button_notification_handler(msg); + } else { + pr_info("service id: %x\n", entry.service_id); + print_hex_dump(KERN_INFO, "event: ", DUMP_PREFIX_OFFSET, 16, 1, + msg->data, msg->length - sizeof(*msg), true); + } + + } +} + +static int icc_notification_handler(u8 service_id, u8 *notification) +{ + struct icc_msg *msg = (struct icc_msg *)notification; + struct icc_notification entry; + + entry.service_id = service_id; + memcpy(entry.notification, msg, msg->length); + + if (kfifo_in_spinlocked(&icc_notification_fifo, &entry, 1, &icc_notification_lock)) { + schedule_work(&icc_notification_work); + } else { + pr_warn_ratelimited("icc notification buffer full\n"); + } + + return 0; +} + +static irqreturn_t icc_interrupt(int irq, void *dev) +{ + struct spcie_icc_dev *icc_dev = dev; + struct icc_msg *msg; + u32 intr_status; + + while (1) { + intr_status = readl(icc_dev->icc_doorbell_base + ICC_REG_INTR_STATUS); + if (!intr_status) + break; + + /* Ack the interrupt */ + writel(intr_status, icc_dev->icc_doorbell_base + ICC_REG_INTR_STATUS); + + if (intr_status & ICC_SEND) { + msg = (struct icc_msg *)(icc_dev->icc_base + ICC_REPLY_OFFSET); + + if (msg->msg_type & ICC_MSG_TYPE_NOTIF) { + icc_dev->notification_length = min(msg->length, ICC_MSG_MAX_SIZE); + memcpy(icc_dev->notification, msg, icc_dev->notification_length); + + writew(0, icc_dev->icc_base + ICC_REG_EMW); + writew(1, icc_dev->icc_base + ICC_REG_EMR); + + writel(ICC_ACK, icc_dev->icc_doorbell_base + ICC_REG_DOORBELL); + + icc_notification_handler(msg->service_id, icc_dev->notification); + } else if (msg->msg_type & ICC_MSG_TYPE_REPLY) { + icc_dev->reply_length = min(msg->length, ICC_MSG_MAX_SIZE); + memcpy(icc_dev->reply, msg, icc_dev->reply_length); + + writew(0, icc_dev->icc_base + ICC_REG_EMW); + writew(1, icc_dev->icc_base + ICC_REG_EMR); + + writel(ICC_ACK, icc_dev->icc_doorbell_base + ICC_REG_DOORBELL); + + icc_dev->reply_ready = true; + wake_up(&icc_dev->wq); + } else { + dev_err(&icc_dev->pdev->dev, "unknown query\n"); + } + } + } + + return IRQ_HANDLED; +} + +static long icc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + switch (cmd) { + case ICC_FAN_CHANGE_SERVO_PATTERN: + { + u8 pattern; + if (copy_from_user(&pattern, (u8 __user *)arg, sizeof(u8))) + return -EFAULT; + return icc_fan_change_servo_pattern(pattern); + } + + default: + return -ENOTTY; + } +} + +static const struct file_operations icc_fops = { + .owner = THIS_MODULE, + .unlocked_ioctl = icc_ioctl, +}; + +static struct miscdevice icc_misc_device = { + .minor = MISC_DYNAMIC_MINOR, + .name = "icc", + .fops = &icc_fops, +}; + +static int spcie_power_button_init(struct spcie_icc_dev *icc_dev) +{ + icc_dev->idev = input_allocate_device(); + if (!icc_dev->idev) + return -ENOMEM; + + icc_dev->idev->name = "Power Button"; + icc_dev->idev->phys = "pm/button/input0"; + icc_dev->idev->id.bustype = BUS_HOST; + icc_dev->idev->dev.parent = NULL; + input_set_capability(icc_dev->idev, EV_KEY, KEY_POWER); + + return input_register_device(icc_dev->idev); +} + +static void spcie_power_button_remove(struct spcie_icc_dev *icc_dev) +{ + input_free_device(icc_dev->idev); +} + +static int spcie_icc_init(struct spcie_dev *sdev) +{ + int vector, ret; + + icc_dev = devm_kzalloc(&sdev->pdev->dev, sizeof(*icc_dev), GFP_KERNEL); + if (!icc_dev) + return -ENOMEM; + + icc_dev->pdev = sdev->pdev; + icc_dev->sdev = sdev; + + sdev->icc_dev = icc_dev; + + INIT_WORK(&icc_notification_work, icc_notification_work_func); + + mutex_init(&icc_dev->lock); + init_waitqueue_head(&icc_dev->wq); + + icc_dev->icc_doorbell_base = sdev->bar2 + ICC_DOORBELL_OFFSET; + icc_dev->icc_base = sdev->pervasive0; + + ret = spcie_power_button_init(icc_dev); + if (ret) + return ret; + + /* Clear status */ + writel(ICC_SEND | ICC_ACK, icc_dev->icc_doorbell_base + ICC_REG_INTR_STATUS); + + /* Request IRQ for icc subfunc */ + vector = pci_irq_vector(sdev->pdev, SPCIE_SUBFUNC_ICC); + ret = devm_request_irq(&sdev->pdev->dev, vector, icc_interrupt, 0, "icc", icc_dev); + if (ret) + return ret; + + /* Enable IRQs */ + writel(ICC_SEND | ICC_ACK, icc_dev->icc_doorbell_base + ICC_REG_INTR_MASK); + + /* Set DMI info */ + static char hw_model[32] = {0}, hw_info[32] = {0}; + if (icc_nvs_read(2, 0x30, 0x20, hw_model) == 0) { + dmi_set_system_info(DMI_PRODUCT_VERSION, hw_model); + } + if (icc_nvs_read(2, 0x10, 0x11, hw_info) == 0) { + dmi_set_system_info(DMI_PRODUCT_SERIAL, hw_info); + } + + /* Enable notifications */ + icc_button_enable_all_notifications(1); + icc_thermal_enable_notification(1); + + /* Update autoservo param */ + icc_fan_update_autoservo_param(); + + /* Set LED to white dim */ + icc_indicator_set_led_white(0); + + /* Enable SuperSpeed-USB-C port */ + icc_usbc_set_pdcon_op_mode(0, 5); + + /* Initialize HDMI */ + getHdmiConfiguration(); + hdmiSystemResume(); + sceHdmiInitVideoConfig(); + + ret = misc_register(&icc_misc_device); + if (ret) + return ret; + + return 0; +} + +static int spcie_icc_remove(struct spcie_dev *sdev) +{ + spcie_power_button_remove(sdev->icc_dev); + misc_deregister(&icc_misc_device); + return 0; +} + +static int spcie_icc_shutdown(struct spcie_dev *sdev) +{ + icc_fan_change_servo_pattern(0); + + /* Disable IRQs */ + writel(0, icc_dev->icc_doorbell_base + ICC_REG_INTR_MASK); + + return 0; +} + +bool spcie_is_initialized(void) +{ + return spcie_initialized; +} +EXPORT_SYMBOL(spcie_is_initialized); + +u32 spcie_get_chip_id(void) +{ + return spcie_chip_revision_id & 0xff0000; +} +EXPORT_SYMBOL(spcie_get_chip_id); + +u32 spcie_get_revision_id(void) +{ + return spcie_chip_revision_id & 0xffff; +} +EXPORT_SYMBOL(spcie_get_revision_id); + +u32 spcie_bar2_180000_read(u32 reg) +{ + return readl(sdev->bar2 + 0x180000 + reg); +} +EXPORT_SYMBOL(spcie_bar2_180000_read); + +void spcie_bar2_180000_write(u32 reg, u32 val) +{ + writel(val, sdev->bar2 + 0x180000 + reg); +} +EXPORT_SYMBOL(spcie_bar2_180000_write); + +u32 spcie_pervasive0_4000_read(u32 reg) +{ + return readl(sdev->pervasive0 + 0x4000 + reg); +} +EXPORT_SYMBOL(spcie_pervasive0_4000_read); + +static int spcie_init_dev(struct spcie_dev *sdev, int dev_ip) +{ + void __iomem *bar; + u32 offset0, offset1, offset2; + u32 val; + int retries = 10000; + + switch (dev_ip) { + case 0: + bar = sdev->bar2; + offset0 = 0x142020; + offset1 = 0x142028; + offset2 = 0x180020; + break; + case 1: + bar = sdev->bar2; + offset0 = 0x143820; + offset1 = 0x143828; + offset2 = 0x18002c; + break; + case 2: + bar = sdev->bar2; + offset0 = 0x144820; + offset1 = 0x144828; + offset2 = 0x180030; + break; + case 3: + bar = sdev->bar2; + offset0 = 0x144020; + offset1 = 0x144028; + offset2 = 0x180024; + break; + case 4: + bar = sdev->pervasive0; + offset0 = 0x42420; + offset1 = 0x42428; + offset2 = 0x7010; + break; + } + + writel(readl(bar + offset0) | 0x10, bar + offset0); + + while (1) { + val = readl(bar + offset1); + if ((val & 0x10) == 0 && (val & 0x20) == 0 && (val & 0x40) == 0 && (val & 0x80) == 0) + break; + udelay(10); + if (!--retries) { + printk("[ERROR]: cannot stop the transaction(%X): %X\n", offset0, val); + break; + } + } + + writel(readl(bar + offset0) | 0x1, bar + offset0); + + if (dev_ip == 4) { + writel(1, sdev->pervasive0 + offset2); + writel(3, sdev->pervasive0 + 0x74b4); + } else { + writel(3, sdev->bar2 + offset2); + + switch (dev_ip) { + case 0: + writel(1, sdev->pervasive0 + 0x74c8); + writel(0x1f, sdev->pervasive0 + 0x7c28); + break; + case 1: + writel(3, sdev->pervasive0 + 0x74c4); + writel(7, sdev->pervasive0 + 0x7c14); + break; + case 2: + writel(3, sdev->pervasive0 + 0x7498); + writel(7, sdev->pervasive0 + 0x7c18); + break; + case 3: + if (spcie_get_chip_id() == 0x110000) { + writel(7, sdev->pervasive0 + 0x74cc); + } else { + writel(1, sdev->pervasive0 + 0x74cc); + } + writel(0xf, sdev->pervasive0 + 0x7c1c); + break; + } + } + + writel(readl(bar + offset0) & ~0x11, bar + offset0); + + if (dev_ip == 4) { + writel(0, sdev->pervasive0 + offset2); + } else if (dev_ip == 0) { + writel(0, sdev->bar2 + offset2); + + writel(readl(sdev->pervasive0 + 0x7c28) & ~8, sdev->pervasive0 + 0x7c28); + writel(readl(sdev->pervasive0 + 0x7c28) & ~1, sdev->pervasive0 + 0x7c28); + + writel(1, sdev->bar2 + offset2); + writel(0, sdev->bar2 + offset2); + + writel(readl(sdev->pervasive0 + 0x7c28) | 8, sdev->pervasive0 + 0x7c28); + writel(readl(sdev->pervasive0 + 0x7c28) | 1, sdev->pervasive0 + 0x7c28); + + udelay(680); + } + + return 0; +} + +static int spcie_init(struct spcie_dev *sdev) +{ + writel(1, sdev->pervasive0 + 0x22004); + while ((readl(sdev->pervasive0 + 0x22000) & 7) != 4); + + spcie_init_dev(sdev, 0); + if (spcie_get_chip_id() == 0x110000) + spcie_init_dev(sdev, 1); + spcie_init_dev(sdev, 2); + spcie_init_dev(sdev, 3); + spcie_init_dev(sdev, 4); + + writel(1, sdev->bar2 + 0x18004c); + writel(1, sdev->pervasive0 + 0x7c08); + + writel(0, sdev->bar2 + 0x18004c); + writel(0, sdev->pervasive0 + 0x22004); + while ((readl(sdev->pervasive0 + 0x22000) & 4) != 0); + + return 0; +} + +static int spcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + u32 chip_revision, chip_id0, chip_id1; + char *chip_name, *rev_name; + int ret; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + sdev = devm_kzalloc(&pdev->dev, sizeof(*sdev), GFP_KERNEL); + if (!sdev) + return -ENOMEM; + + sdev->pdev = pdev; + + sdev->bar2 = pcim_iomap(pdev, 2, 0); + if (!sdev->bar2) + return -ENOMEM; + + sdev->pervasive0 = pcim_iomap(pdev, 4, 0); + if (!sdev->pervasive0) + return -ENOMEM; + + pci_set_master(pdev); + + chip_revision = readl(sdev->pervasive0 + 0x4000); + dev_info(&sdev->pdev->dev, "Chip revision: %08x\n", chip_revision); + + chip_id0 = readl(sdev->pervasive0 + 0x4008); + dev_info(&sdev->pdev->dev, "Chip ID0: %08x\n", chip_id0); + + chip_id1 = readl(sdev->pervasive0 + 0x4004); + dev_info(&sdev->pdev->dev, "Chip ID1: %08x\n", chip_id1); + + if ((chip_revision & 0xff000000) == 0x11000000) { + chip_name = "Salina"; + spcie_chip_revision_id = 0x110000; + } else if ((chip_revision & 0xff000000) == 0x12000000) { + chip_name = "Salina2"; + spcie_chip_revision_id = 0x120000; + } else { + panic("unknown subsys %08x\n", chip_revision); + } + + switch (chip_revision & 0xffff) { + case 0x100: rev_name = "A0"; break; + case 0x101: rev_name = "A1"; break; + case 0x200: rev_name = "B0"; break; + case 0x201: rev_name = "B1"; break; + case 0x300: rev_name = "C0"; break; + default: + panic("unknown subsys %08x\n", chip_revision); + } + + spcie_chip_revision_id |= (chip_revision & 0xffff); + + dev_info(&sdev->pdev->dev, "%s %s\n", chip_name, rev_name); + + ret = spcie_init(sdev); + if (ret) + return ret; + + ret = pci_alloc_irq_vectors(pdev, NUM_IRQS, NUM_IRQS, PCI_IRQ_MSI); + if (ret < 0) + return ret; + + ret = spcie_icc_init(sdev); + if (ret) { + pci_free_irq_vectors(pdev); + return ret; + } + + spcie_initialized = true; + + pci_set_drvdata(pdev, sdev); + return 0; +} + +static void spcie_remove(struct pci_dev *pdev) +{ + struct spcie_dev *sdev = pci_get_drvdata(pdev); + if (sdev) { + spcie_icc_remove(sdev); + pci_free_irq_vectors(pdev); + } +} + +static void spcie_shutdown(struct pci_dev *pdev) +{ + struct spcie_dev *sdev = pci_get_drvdata(pdev); + if (sdev) { + spcie_icc_shutdown(sdev); + } +} + +static const struct pci_device_id spcie_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_SPCIE) }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, spcie_ids); + +static struct pci_driver spcie_driver = { + .name = "spcie", + .id_table = spcie_ids, + .probe = spcie_probe, + .remove = spcie_remove, + .shutdown = spcie_shutdown, +}; + +module_pci_driver(spcie_driver); + +MODULE_AUTHOR("Andy Nguyen"); +MODULE_DESCRIPTION("PlayStation 5 Salina PCI Express glue driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/ps5/tpcie.c b/drivers/ps5/tpcie.c new file mode 100644 index 000000000000..23de43ea4b00 --- /dev/null +++ b/drivers/ps5/tpcie.c @@ -0,0 +1,303 @@ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include +#include +#include +#include + +#define PCI_DEVICE_ID_TPCIE 0x90ec +#define TPCIE_SUBFUNC_UART 6 +#define NUM_IRQS 8 + +#define UART_OFFSET 0x1010100 + +struct tpcie_dev; + +struct tpcie_uart_dev { + struct pci_dev *pdev; + struct tpcie_dev *tdev; + void __iomem *uart_base; + struct tty_driver *tty_drv; + struct tty_port tty_port; +}; + +struct tpcie_dev { + struct pci_dev *pdev; + void __iomem *bar4; + struct tpcie_uart_dev *uart_dev; +}; + +static struct tpcie_uart_dev *uart_dev; + +static bool tpcie_uart_rx_ready(void) +{ + return (readl(uart_dev->uart_base + 0xc) & 0x10) != 0; +} + +static bool tpcie_uart_tx_ready(void) +{ + return (readl(uart_dev->uart_base + 0xc) & 0x800) == 0; +} + +static void tpcie_uart_putc(char c) +{ + unsigned timeout = 0xffff; + while (!tpcie_uart_tx_ready() && --timeout) + cpu_relax(); + writel(c, uart_dev->uart_base + 0x4); +} + +static void tpcie_uart_write(struct console *con, const char *s, unsigned int n) +{ + int i; + for (i = 0; i < n; ++i) { + if (s[i] == '\n') + tpcie_uart_putc('\r'); + tpcie_uart_putc(s[i]); + } +} + +static ssize_t tpcie_uart_tty_write(struct tty_struct *tty, const u8 *buf, size_t count) +{ + int i; + for (i = 0; i < count; i++) { + tpcie_uart_putc(buf[i]); + } + tty_port_tty_wakeup(&uart_dev->tty_port); + return count; +} + +static unsigned int tpcie_uart_tty_write_room(struct tty_struct *tty) +{ + return 2048; +} + +static int tpcie_uart_tty_open(struct tty_struct *tty, struct file *file) +{ + return tty_port_open(&uart_dev->tty_port, tty, file); +} + +static void tpcie_uart_tty_close(struct tty_struct *tty, struct file *file) +{ + tty_port_close(&uart_dev->tty_port, tty, file); +} + +static void tpcie_uart_tty_hangup(struct tty_struct *tty) +{ + tty_port_hangup(&uart_dev->tty_port); +} + +static struct tty_operations tpcie_uart_tty_ops = { + .open = tpcie_uart_tty_open, + .close = tpcie_uart_tty_close, + .write = tpcie_uart_tty_write, + .write_room = tpcie_uart_tty_write_room, + .hangup = tpcie_uart_tty_hangup, +}; + +static const struct tty_port_operations tpcie_uart_port_ops = {}; + +static struct tty_driver *tpcie_uart_device(struct console *c, int *index) +{ + *index = 0; + return uart_dev->tty_drv; +} + +static struct console tpcie_uart_console = { + .name = "ttyTitania", + .device = tpcie_uart_device, + .write = tpcie_uart_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; + +static irqreturn_t uart_interrupt(int irq, void *dev) +{ + u8 ch; + while (tpcie_uart_rx_ready()) { + ch = readl(uart_dev->uart_base + 0x0); + tty_insert_flip_char(&uart_dev->tty_port, ch, TTY_NORMAL); + } + tty_flip_buffer_push(&uart_dev->tty_port); + return IRQ_HANDLED; +} + +static void tcpie_config_msi(struct tpcie_dev *tdev, int subfunc, struct msi_msg *msg) +{ + writel(0xffffffff, tdev->bar4 + 0x120214); + writel(0, tdev->bar4 + 0x12020c); + + writel(msg->address_lo, tdev->bar4 + 0x120204); + writel(msg->address_hi, tdev->bar4 + 0x120208); + + writel(msg->data & ~0x1f, tdev->bar4 + 0x120210); + if (subfunc == TPCIE_SUBFUNC_UART) { + writel(msg->data & 0x1f, tdev->bar4 + 0x120230); + } + writel(msg->data & 0x1f, tdev->bar4 + 0x120210 + subfunc * 4); + + writel(0x33, tdev->bar4 + 0x120200); +} + +static int tpcie_uart_init(struct tpcie_dev *tdev) +{ + struct tty_driver *drv; + struct msi_msg msg; + int vector, ret; + + uart_dev = devm_kzalloc(&tdev->pdev->dev, sizeof(*uart_dev), GFP_KERNEL); + if (!uart_dev) + return -ENOMEM; + + uart_dev->pdev = tdev->pdev; + uart_dev->tdev = tdev; + tdev->uart_dev = uart_dev; + uart_dev->uart_base = tdev->bar4 + UART_OFFSET; + + drv = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW); + if (IS_ERR(drv)) + return PTR_ERR(drv); + + drv->driver_name = "tpcie_uart"; + drv->name = "ttyTitania"; + drv->type = TTY_DRIVER_TYPE_SERIAL; + drv->major = 0; + drv->minor_start = 0; + drv->num = 1; + drv->subtype = SERIAL_TYPE_NORMAL; + drv->flags = TTY_DRIVER_RESET_TERMIOS | TTY_DRIVER_REAL_RAW; + drv->init_termios = tty_std_termios; + tty_set_operations(drv, &tpcie_uart_tty_ops); + uart_dev->tty_drv = drv; + + tty_port_init(&uart_dev->tty_port); + uart_dev->tty_port.ops = &tpcie_uart_port_ops; + tty_port_link_device(&uart_dev->tty_port, drv, 0); + + ret = tty_register_driver(drv); + if (ret) { + tty_driver_kref_put(drv); + return ret; + } + + register_console(&tpcie_uart_console); + + /* Request IRQ for uart subfunc */ + vector = pci_irq_vector(tdev->pdev, TPCIE_SUBFUNC_UART); + ret = devm_request_irq(&tdev->pdev->dev, vector, uart_interrupt, 0, "uart", uart_dev); + if (ret) + goto err_unreg_tty; + + /* Special MSI configuration */ + ret = irq_chip_compose_msi_msg(irq_get_irq_data(vector), &msg); + if (ret) + goto err_unreg_tty; + + tcpie_config_msi(tdev, TPCIE_SUBFUNC_UART, &msg); + + /* Enable IRQs */ + writel(0x10, uart_dev->uart_base + 0x8); + + return 0; + +err_unreg_tty: + unregister_console(&tpcie_uart_console); + tty_unregister_driver(drv); + tty_driver_kref_put(drv); + return ret; +} + +static void tpcie_uart_remove(struct tpcie_dev *tdev) +{ + unregister_console(&tpcie_uart_console); + + if (uart_dev->tty_drv) { + tty_unregister_driver(uart_dev->tty_drv); + tty_driver_kref_put(uart_dev->tty_drv); + } + + tty_port_destroy(&uart_dev->tty_port); +} + +static void tpcie_uart_shutdown(struct tpcie_dev *tdev) +{ + /* Disable IRQs */ + writel(0, uart_dev->uart_base + 0x8); +} + +static int tpcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct tpcie_dev *tdev; + int ret; + + ret = pcim_enable_device(pdev); + if (ret) + return ret; + + tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL); + if (!tdev) + return -ENOMEM; + + tdev->pdev = pdev; + tdev->bar4 = pcim_iomap(pdev, 4, 0); + if (!tdev->bar4) + return -ENOMEM; + + pci_set_master(pdev); + + ret = pci_alloc_irq_vectors(pdev, NUM_IRQS, NUM_IRQS, PCI_IRQ_MSI); + if (ret < 0) + return ret; + + writel(0xf, tdev->bar4 + 0x1142000 + 0x100); + writel(0xf, tdev->bar4 + 0x1142000 + 0x104); + + ret = tpcie_uart_init(tdev); + if (ret) { + pci_free_irq_vectors(pdev); + return ret; + } + + pci_set_drvdata(pdev, tdev); + return 0; +} + +static void tpcie_remove(struct pci_dev *pdev) +{ + struct tpcie_dev *tdev = pci_get_drvdata(pdev); + if (tdev) { + tpcie_uart_remove(tdev); + pci_free_irq_vectors(pdev); + } +} + +static void tpcie_shutdown(struct pci_dev *pdev) +{ + struct tpcie_dev *tdev = pci_get_drvdata(pdev); + if (tdev) { + tpcie_uart_shutdown(tdev); + } +} + +static const struct pci_device_id tpcie_ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_SONY, PCI_DEVICE_ID_TPCIE) }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, tpcie_ids); + +static struct pci_driver tpcie_driver = { + .name = "tpcie", + .id_table = tpcie_ids, + .probe = tpcie_probe, + .remove = tpcie_remove, + .shutdown = tpcie_shutdown, +}; + +module_pci_driver(tpcie_driver); + +MODULE_AUTHOR("Andy Nguyen"); +MODULE_DESCRIPTION("PlayStation 5 Titania PCI Express glue driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/dmi.h b/include/linux/dmi.h index 2eedf44e6801..2785a47665be 100644 --- a/include/linux/dmi.h +++ b/include/linux/dmi.h @@ -105,6 +105,9 @@ extern struct kobject *dmi_kobj; extern int dmi_check_system(const struct dmi_system_id *list); const struct dmi_system_id *dmi_first_match(const struct dmi_system_id *list); extern const char * dmi_get_system_info(int field); +#ifdef CONFIG_X86_PS5 +extern void dmi_set_system_info(int field, const char *str); +#endif extern const struct dmi_device * dmi_find_device(int type, const char *name, const struct dmi_device *from); extern void dmi_setup(void); diff --git a/include/linux/ps5.h b/include/linux/ps5.h new file mode 100644 index 000000000000..4020a0b0c61c --- /dev/null +++ b/include/linux/ps5.h @@ -0,0 +1,93 @@ +#ifndef _LINUX_PS5_H +#define _LINUX_PS5_H + +#include +#include + +#define ICC_MSG_MIN_SIZE 0x20 +#define ICC_MSG_MAX_SIZE 0x7f0 + +struct icc_msg { + u8 magic; + u8 service_id; + u16 msg_type; + u16 unk_04; + u16 id; + u16 length; + u16 checksum; + u8 data[]; +}; + +enum icc_service_id { + ICC_SERVICE_ID_CONFIGURATION = 0x01, + ICC_SERVICE_ID_GENERAL = 0x02, + ICC_SERVICE_ID_NVS = 0x03, + ICC_SERVICE_ID_POWER = 0x04, + ICC_SERVICE_ID_DEVICE = 0x05, + ICC_SERVICE_ID_UNKNOWN_07 = 0x07, + ICC_SERVICE_ID_BUTTON = 0x08, + ICC_SERVICE_ID_INDICATOR = 0x09, + ICC_SERVICE_ID_FAN = 0x0a, + ICC_SERVICE_ID_THERMAL = 0x0b, + ICC_SERVICE_ID_HDMI = 0x10, + ICC_SERVICE_ID_USBC = 0x12, + ICC_SERVICE_ID_UNKNOWN_13 = 0x13, + ICC_SERVICE_ID_CRASH_REPORT = 0x14, + ICC_SERVICE_ID_BDDRIVE = 0x15, + ICC_SERVICE_ID_UNKNOWN_8C = 0x8c, + ICC_SERVICE_ID_UNKNOWN_8D = 0x8d, + ICC_SERVICE_ID_SC_CONFIG = 0x8e, + ICC_SERVICE_ID_FLOYD = 0x9a, +}; + +bool spcie_is_initialized(void); + +u32 spcie_get_chip_id(void); +u32 spcie_get_revision_id(void); +u32 spcie_bar2_180000_read(u32 reg); +void spcie_bar2_180000_write(u32 reg, u32 val); +u32 spcie_pervasive0_4000_read(u32 reg); + +int icc_query(u8 *query, u8 *reply); + +void hdmiSystemResume(void); +void sceHdmiInitVideoConfig(void); +void sceHdmiSetVideoConfig(const struct drm_display_mode *mode); +void sceHdmiSetAudioConfig(int channels); +void sceHdmiDeviceSetVideoMute(int mute); +void sceHdmiSetAudioMute(int mute); +void sceHdmiOutputMode(void); +int getHdmiConfiguration(void); +bool isHdmiModeValid(const struct drm_display_mode *mode, int force_1080p); + +int icc_nvs_write(u32 partition, u16 offset, u16 length, const void *data); +int icc_nvs_read(u32 partition, u16 offset, u16 length, void *data); + +int icc_usbc_set_pdcon_op_mode(u8 PortId, u8 OpMode); +int icc_configuration_set_cpu_info_bit(u8 *bit); +int icc_configuration_clear_cpu_info_bit(void); + +__noreturn void icc_power_suspend(int keep); +void __noreturn icc_power_shutdown(void); +void __noreturn icc_power_reboot(void); + +int icc_button_enable_notification(u8 type, u8 enable); +int icc_button_enable_all_notifications(u8 enable); +int icc_thermal_enable_notification(u8 enable); + +int icc_device_power_control(u8 device, u8 state); +int icc_device_power_get(u8 device, u8 *state); + +int icc_indicator_set_led(const u8 setting[], size_t setting_size); +int icc_indicator_set_led_white(u8 level); + +int icc_fan_change_servo_pattern(u8 pattern); +int icc_fan_update_param(const u8 *param); +int icc_fan_update_autoservo_param(void); + +void hdmi_notification_handler(struct icc_msg *msg); + +void mp1_set_pm1_addr(u64 addr); +int mp1_set_sleep_entry(void); + +#endif /* _LINUX_PS5_H */ diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 28169d7e143b..44f516daa21d 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -61,6 +61,9 @@ scm_version() local no_dirty=false local tag + # Do not add any suffix for ps5-linux. + return + while [ $# -gt 0 ]; do case "$1" in diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c index a4104376523a..befee7ef6c94 100644 --- a/sound/hda/controllers/intel.c +++ b/sound/hda/controllers/intel.c @@ -2640,6 +2640,8 @@ static const struct pci_device_id azx_ids[] = { AZX_DCAPS_PM_RUNTIME }, { PCI_VDEVICE(ATI, 0x1308), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, + { PCI_VDEVICE(ATI, 0x13ea), + .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, { PCI_VDEVICE(ATI, 0x157a), .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI_NS }, { PCI_VDEVICE(ATI, 0x15b3),