Snap for 8323489 from 34072d736b to android13-5.15-keystone-qcom-release
Change-Id: Ic62b8491097dc5e866deca396824324ab4edd0a8
This commit is contained in:
@@ -23,7 +23,7 @@ There are four components to pagemap:
|
||||
* Bit 56 page exclusively mapped (since 4.2)
|
||||
* Bit 57 pte is uffd-wp write-protected (since 5.13) (see
|
||||
:ref:`Documentation/admin-guide/mm/userfaultfd.rst <userfaultfd>`)
|
||||
* Bits 57-60 zero
|
||||
* Bits 58-60 zero
|
||||
* Bit 61 page is file-page or shared-anon (since 3.5)
|
||||
* Bit 62 page swapped
|
||||
* Bit 63 page present
|
||||
|
||||
@@ -183,25 +183,25 @@ Frame Buffer Compression (FBC)
|
||||
Display Refresh Rate Switching (DRRS)
|
||||
-------------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:doc: Display Refresh Rate Switching (DRRS)
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_dp_set_drrs_state
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_edp_drrs_enable
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_edp_drrs_disable
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_edp_drrs_invalidate
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_edp_drrs_flush
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_dp.c
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c
|
||||
:functions: intel_dp_drrs_init
|
||||
|
||||
DPIO
|
||||
|
||||
@@ -198,6 +198,15 @@ The glob (~) accepts a wild card character (\*,?) and character classes
|
||||
prev_comm ~ "*sh*"
|
||||
prev_comm ~ "ba*sh"
|
||||
|
||||
If the field is a pointer that points into user space (for example
|
||||
"filename" from sys_enter_openat), then you have to append ".ustring" to the
|
||||
field name::
|
||||
|
||||
filename.ustring ~ "password"
|
||||
|
||||
As the kernel will have to know how to retrieve the memory that the pointer
|
||||
is at from user space.
|
||||
|
||||
5.2 Setting filters
|
||||
-------------------
|
||||
|
||||
@@ -230,6 +239,16 @@ Currently the caret ('^') for an error always appears at the beginning of
|
||||
the filter string; the error message should still be useful though
|
||||
even without more accurate position info.
|
||||
|
||||
5.2.1 Filter limitations
|
||||
------------------------
|
||||
|
||||
If a filter is placed on a string pointer ``(char *)`` that does not point
|
||||
to a string on the ring buffer, but instead points to kernel or user space
|
||||
memory, then, for safety reasons, at most 1024 bytes of the content is
|
||||
copied onto a temporary buffer to do the compare. If the copy of the memory
|
||||
faults (the pointer points to memory that should not be accessed), then the
|
||||
string compare will be treated as not matching.
|
||||
|
||||
5.3 Clearing filters
|
||||
--------------------
|
||||
|
||||
|
||||
@@ -7024,7 +7024,6 @@ F: drivers/net/mdio/fwnode_mdio.c
|
||||
F: drivers/net/mdio/of_mdio.c
|
||||
F: drivers/net/pcs/
|
||||
F: drivers/net/phy/
|
||||
F: drivers/of/of_net.c
|
||||
F: include/dt-bindings/net/qca-ar803x.h
|
||||
F: include/linux/*mdio*.h
|
||||
F: include/linux/mdio/*.h
|
||||
@@ -7036,6 +7035,7 @@ F: include/linux/platform_data/mdio-gpio.h
|
||||
F: include/trace/events/mdio.h
|
||||
F: include/uapi/linux/mdio.h
|
||||
F: include/uapi/linux/mii.h
|
||||
F: net/core/of_net.c
|
||||
|
||||
EXFAT FILE SYSTEM
|
||||
M: Namjae Jeon <linkinjeon@kernel.org>
|
||||
|
||||
2
Makefile
2
Makefile
@@ -1,7 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
VERSION = 5
|
||||
PATCHLEVEL = 15
|
||||
SUBLEVEL = 26
|
||||
SUBLEVEL = 27
|
||||
EXTRAVERSION =
|
||||
NAME = Trick or Treat
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -624,6 +624,7 @@
|
||||
ieee80211_scan_completed
|
||||
ieee80211_stop_queues
|
||||
ieee80211_stop_tx_ba_cb_irqsafe
|
||||
ieee80211_tx_prepare_skb
|
||||
ieee80211_tx_status_irqsafe
|
||||
ieee80211_unregister_hw
|
||||
ieee80211_wake_queues
|
||||
|
||||
@@ -158,6 +158,24 @@
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
/* Unusable as clockevent because if unreliable oscillator, allow to idle */
|
||||
&timer1_target {
|
||||
/delete-property/ti,no-reset-on-init;
|
||||
/delete-property/ti,no-idle;
|
||||
timer@0 {
|
||||
/delete-property/ti,timer-alwon;
|
||||
};
|
||||
};
|
||||
|
||||
/* Preferred timer for clockevent */
|
||||
&timer12_target {
|
||||
ti,no-reset-on-init;
|
||||
ti,no-idle;
|
||||
timer@0 {
|
||||
/* Always clocked by secure_32k_fck */
|
||||
};
|
||||
};
|
||||
|
||||
&twl_gpio {
|
||||
ti,use-leds;
|
||||
/*
|
||||
|
||||
@@ -14,36 +14,3 @@
|
||||
display2 = &tv0;
|
||||
};
|
||||
};
|
||||
|
||||
/* Unusable as clocksource because of unreliable oscillator */
|
||||
&counter32k {
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
/* Unusable as clockevent because if unreliable oscillator, allow to idle */
|
||||
&timer1_target {
|
||||
/delete-property/ti,no-reset-on-init;
|
||||
/delete-property/ti,no-idle;
|
||||
timer@0 {
|
||||
/delete-property/ti,timer-alwon;
|
||||
};
|
||||
};
|
||||
|
||||
/* Preferred always-on timer for clocksource */
|
||||
&timer12_target {
|
||||
ti,no-reset-on-init;
|
||||
ti,no-idle;
|
||||
timer@0 {
|
||||
/* Always clocked by secure_32k_fck */
|
||||
};
|
||||
};
|
||||
|
||||
/* Preferred timer for clockevent */
|
||||
&timer2_target {
|
||||
ti,no-reset-on-init;
|
||||
ti,no-idle;
|
||||
timer@0 {
|
||||
assigned-clocks = <&gpt2_fck>;
|
||||
assigned-clock-parents = <&sys_ck>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -13,12 +13,15 @@
|
||||
"google,nyan-big-rev1", "google,nyan-big-rev0",
|
||||
"google,nyan-big", "google,nyan", "nvidia,tegra124";
|
||||
|
||||
panel: panel {
|
||||
compatible = "auo,b133xtn01";
|
||||
|
||||
power-supply = <&vdd_3v3_panel>;
|
||||
backlight = <&backlight>;
|
||||
ddc-i2c-bus = <&dpaux>;
|
||||
host1x@50000000 {
|
||||
dpaux@545c0000 {
|
||||
aux-bus {
|
||||
panel: panel {
|
||||
compatible = "auo,b133xtn01";
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
mmc@700b0400 { /* SD Card on this bus */
|
||||
|
||||
@@ -15,12 +15,15 @@
|
||||
"google,nyan-blaze-rev0", "google,nyan-blaze",
|
||||
"google,nyan", "nvidia,tegra124";
|
||||
|
||||
panel: panel {
|
||||
compatible = "samsung,ltn140at29-301";
|
||||
|
||||
power-supply = <&vdd_3v3_panel>;
|
||||
backlight = <&backlight>;
|
||||
ddc-i2c-bus = <&dpaux>;
|
||||
host1x@50000000 {
|
||||
dpaux@545c0000 {
|
||||
aux-bus {
|
||||
panel: panel {
|
||||
compatible = "samsung,ltn140at29-301";
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
sound {
|
||||
|
||||
@@ -48,6 +48,13 @@
|
||||
dpaux@545c0000 {
|
||||
vdd-supply = <&vdd_3v3_panel>;
|
||||
status = "okay";
|
||||
|
||||
aux-bus {
|
||||
panel: panel {
|
||||
compatible = "lg,lp129qe";
|
||||
backlight = <&backlight>;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1079,13 +1086,6 @@
|
||||
};
|
||||
};
|
||||
|
||||
panel: panel {
|
||||
compatible = "lg,lp129qe";
|
||||
power-supply = <&vdd_3v3_panel>;
|
||||
backlight = <&backlight>;
|
||||
ddc-i2c-bus = <&dpaux>;
|
||||
};
|
||||
|
||||
vdd_mux: regulator@0 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "+VDD_MUX";
|
||||
|
||||
@@ -154,22 +154,38 @@ static int kgdb_compiled_brk_fn(struct pt_regs *regs, unsigned int instr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct undef_hook kgdb_brkpt_hook = {
|
||||
static struct undef_hook kgdb_brkpt_arm_hook = {
|
||||
.instr_mask = 0xffffffff,
|
||||
.instr_val = KGDB_BREAKINST,
|
||||
.cpsr_mask = MODE_MASK,
|
||||
.cpsr_mask = PSR_T_BIT | MODE_MASK,
|
||||
.cpsr_val = SVC_MODE,
|
||||
.fn = kgdb_brk_fn
|
||||
};
|
||||
|
||||
static struct undef_hook kgdb_compiled_brkpt_hook = {
|
||||
static struct undef_hook kgdb_brkpt_thumb_hook = {
|
||||
.instr_mask = 0xffff,
|
||||
.instr_val = KGDB_BREAKINST & 0xffff,
|
||||
.cpsr_mask = PSR_T_BIT | MODE_MASK,
|
||||
.cpsr_val = PSR_T_BIT | SVC_MODE,
|
||||
.fn = kgdb_brk_fn
|
||||
};
|
||||
|
||||
static struct undef_hook kgdb_compiled_brkpt_arm_hook = {
|
||||
.instr_mask = 0xffffffff,
|
||||
.instr_val = KGDB_COMPILED_BREAK,
|
||||
.cpsr_mask = MODE_MASK,
|
||||
.cpsr_mask = PSR_T_BIT | MODE_MASK,
|
||||
.cpsr_val = SVC_MODE,
|
||||
.fn = kgdb_compiled_brk_fn
|
||||
};
|
||||
|
||||
static struct undef_hook kgdb_compiled_brkpt_thumb_hook = {
|
||||
.instr_mask = 0xffff,
|
||||
.instr_val = KGDB_COMPILED_BREAK & 0xffff,
|
||||
.cpsr_mask = PSR_T_BIT | MODE_MASK,
|
||||
.cpsr_val = PSR_T_BIT | SVC_MODE,
|
||||
.fn = kgdb_compiled_brk_fn
|
||||
};
|
||||
|
||||
static int __kgdb_notify(struct die_args *args, unsigned long cmd)
|
||||
{
|
||||
struct pt_regs *regs = args->regs;
|
||||
@@ -210,8 +226,10 @@ int kgdb_arch_init(void)
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
register_undef_hook(&kgdb_brkpt_hook);
|
||||
register_undef_hook(&kgdb_compiled_brkpt_hook);
|
||||
register_undef_hook(&kgdb_brkpt_arm_hook);
|
||||
register_undef_hook(&kgdb_brkpt_thumb_hook);
|
||||
register_undef_hook(&kgdb_compiled_brkpt_arm_hook);
|
||||
register_undef_hook(&kgdb_compiled_brkpt_thumb_hook);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -224,8 +242,10 @@ int kgdb_arch_init(void)
|
||||
*/
|
||||
void kgdb_arch_exit(void)
|
||||
{
|
||||
unregister_undef_hook(&kgdb_brkpt_hook);
|
||||
unregister_undef_hook(&kgdb_compiled_brkpt_hook);
|
||||
unregister_undef_hook(&kgdb_brkpt_arm_hook);
|
||||
unregister_undef_hook(&kgdb_brkpt_thumb_hook);
|
||||
unregister_undef_hook(&kgdb_compiled_brkpt_arm_hook);
|
||||
unregister_undef_hook(&kgdb_compiled_brkpt_thumb_hook);
|
||||
unregister_die_notifier(&kgdb_notifier);
|
||||
}
|
||||
|
||||
|
||||
@@ -212,12 +212,14 @@ early_param("ecc", early_ecc);
|
||||
static int __init early_cachepolicy(char *p)
|
||||
{
|
||||
pr_warn("cachepolicy kernel parameter not supported without cp15\n");
|
||||
return 0;
|
||||
}
|
||||
early_param("cachepolicy", early_cachepolicy);
|
||||
|
||||
static int __init noalign_setup(char *__unused)
|
||||
{
|
||||
pr_warn("noalign kernel parameter not supported without cp15\n");
|
||||
return 1;
|
||||
}
|
||||
__setup("noalign", noalign_setup);
|
||||
|
||||
|
||||
@@ -543,8 +543,7 @@
|
||||
<0x02000000 0x00 0x50000000 0x00 0x50000000 0x0 0x08000000>,
|
||||
<0x42000000 0x40 0x00000000 0x40 0x00000000 0x1 0x00000000>;
|
||||
/* Standard AXI Translation entries as programmed by EDK2 */
|
||||
dma-ranges = <0x02000000 0x0 0x2c1c0000 0x0 0x2c1c0000 0x0 0x00040000>,
|
||||
<0x02000000 0x0 0x80000000 0x0 0x80000000 0x0 0x80000000>,
|
||||
dma-ranges = <0x02000000 0x0 0x80000000 0x0 0x80000000 0x0 0x80000000>,
|
||||
<0x43000000 0x8 0x00000000 0x8 0x00000000 0x2 0x00000000>;
|
||||
#interrupt-cells = <1>;
|
||||
interrupt-map-mask = <0 0 0 7>;
|
||||
|
||||
@@ -286,7 +286,7 @@
|
||||
|
||||
sound: sound {
|
||||
compatible = "rockchip,rk3399-gru-sound";
|
||||
rockchip,cpu = <&i2s0 &i2s2>;
|
||||
rockchip,cpu = <&i2s0 &spdif>;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -437,10 +437,6 @@ ap_i2c_audio: &i2c8 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2s2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&io_domains {
|
||||
status = "okay";
|
||||
|
||||
@@ -537,6 +533,17 @@ ap_i2c_audio: &i2c8 {
|
||||
vqmmc-supply = <&ppvar_sd_card_io>;
|
||||
};
|
||||
|
||||
&spdif {
|
||||
status = "okay";
|
||||
|
||||
/*
|
||||
* SPDIF is routed internally to DP; we either don't use these pins, or
|
||||
* mux them to something else.
|
||||
*/
|
||||
/delete-property/ pinctrl-0;
|
||||
/delete-property/ pinctrl-names;
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
status = "okay";
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
*/
|
||||
|
||||
|
||||
void start_backtrace(struct stackframe *frame, unsigned long fp,
|
||||
notrace void start_backtrace(struct stackframe *frame, unsigned long fp,
|
||||
unsigned long pc)
|
||||
{
|
||||
frame->fp = fp;
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <linux/percpu.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/atomic.h>
|
||||
#include <asm/asm.h>
|
||||
#include <asm/cmpxchg.h>
|
||||
#include <asm/compiler.h>
|
||||
#include <asm/war.h>
|
||||
@@ -39,7 +40,7 @@ static __inline__ long local_add_return(long i, local_t * l)
|
||||
" .set arch=r4000 \n"
|
||||
__SYNC(full, loongson3_war) " \n"
|
||||
"1:" __LL "%1, %2 # local_add_return \n"
|
||||
" addu %0, %1, %3 \n"
|
||||
__stringify(LONG_ADDU) " %0, %1, %3 \n"
|
||||
__SC "%0, %2 \n"
|
||||
" beqzl %0, 1b \n"
|
||||
" addu %0, %1, %3 \n"
|
||||
@@ -55,7 +56,7 @@ static __inline__ long local_add_return(long i, local_t * l)
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
__SYNC(full, loongson3_war) " \n"
|
||||
"1:" __LL "%1, %2 # local_add_return \n"
|
||||
" addu %0, %1, %3 \n"
|
||||
__stringify(LONG_ADDU) " %0, %1, %3 \n"
|
||||
__SC "%0, %2 \n"
|
||||
" beqz %0, 1b \n"
|
||||
" addu %0, %1, %3 \n"
|
||||
@@ -88,7 +89,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
|
||||
" .set arch=r4000 \n"
|
||||
__SYNC(full, loongson3_war) " \n"
|
||||
"1:" __LL "%1, %2 # local_sub_return \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
__stringify(LONG_SUBU) " %0, %1, %3 \n"
|
||||
__SC "%0, %2 \n"
|
||||
" beqzl %0, 1b \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
@@ -104,7 +105,7 @@ static __inline__ long local_sub_return(long i, local_t * l)
|
||||
" .set "MIPS_ISA_ARCH_LEVEL" \n"
|
||||
__SYNC(full, loongson3_war) " \n"
|
||||
"1:" __LL "%1, %2 # local_sub_return \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
__stringify(LONG_SUBU) " %0, %1, %3 \n"
|
||||
__SC "%0, %2 \n"
|
||||
" beqz %0, 1b \n"
|
||||
" subu %0, %1, %3 \n"
|
||||
|
||||
@@ -803,7 +803,7 @@ early_param("coherentio", setcoherentio);
|
||||
|
||||
static int __init setnocoherentio(char *str)
|
||||
{
|
||||
dma_default_coherent = true;
|
||||
dma_default_coherent = false;
|
||||
pr_info("Software DMA cache coherency (command line)\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -20,31 +20,41 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
static void *detect_magic __initdata = detect_memory_region;
|
||||
#define MT7621_MEM_TEST_PATTERN 0xaa5555aa
|
||||
|
||||
static u32 detect_magic __initdata;
|
||||
|
||||
phys_addr_t mips_cpc_default_phys_base(void)
|
||||
{
|
||||
panic("Cannot detect cpc address");
|
||||
}
|
||||
|
||||
static bool __init mt7621_addr_wraparound_test(phys_addr_t size)
|
||||
{
|
||||
void *dm = (void *)KSEG1ADDR(&detect_magic);
|
||||
|
||||
if (CPHYSADDR(dm + size) >= MT7621_LOWMEM_MAX_SIZE)
|
||||
return true;
|
||||
__raw_writel(MT7621_MEM_TEST_PATTERN, dm);
|
||||
if (__raw_readl(dm) != __raw_readl(dm + size))
|
||||
return false;
|
||||
__raw_writel(~MT7621_MEM_TEST_PATTERN, dm);
|
||||
return __raw_readl(dm) == __raw_readl(dm + size);
|
||||
}
|
||||
|
||||
static void __init mt7621_memory_detect(void)
|
||||
{
|
||||
void *dm = &detect_magic;
|
||||
phys_addr_t size;
|
||||
|
||||
for (size = 32 * SZ_1M; size < 256 * SZ_1M; size <<= 1) {
|
||||
if (!__builtin_memcmp(dm, dm + size, sizeof(detect_magic)))
|
||||
break;
|
||||
for (size = 32 * SZ_1M; size <= 256 * SZ_1M; size <<= 1) {
|
||||
if (mt7621_addr_wraparound_test(size)) {
|
||||
memblock_add(MT7621_LOWMEM_BASE, size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((size == 256 * SZ_1M) &&
|
||||
(CPHYSADDR(dm + size) < MT7621_LOWMEM_MAX_SIZE) &&
|
||||
__builtin_memcmp(dm, dm + size, sizeof(detect_magic))) {
|
||||
memblock_add(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE);
|
||||
memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE);
|
||||
} else {
|
||||
memblock_add(MT7621_LOWMEM_BASE, size);
|
||||
}
|
||||
memblock_add(MT7621_LOWMEM_BASE, MT7621_LOWMEM_MAX_SIZE);
|
||||
memblock_add(MT7621_HIGHMEM_BASE, MT7621_HIGHMEM_SIZE);
|
||||
}
|
||||
|
||||
void __init ralink_of_remap(void)
|
||||
|
||||
@@ -24,6 +24,9 @@ obj-$(CONFIG_KASAN) += kasan_init.o
|
||||
ifdef CONFIG_KASAN
|
||||
KASAN_SANITIZE_kasan_init.o := n
|
||||
KASAN_SANITIZE_init.o := n
|
||||
ifdef CONFIG_DEBUG_VIRTUAL
|
||||
KASAN_SANITIZE_physaddr.o := n
|
||||
endif
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_DEBUG_VIRTUAL) += physaddr.o
|
||||
|
||||
@@ -451,6 +451,7 @@ static uintptr_t __init best_map_size(phys_addr_t base, phys_addr_t size)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_XIP_KERNEL
|
||||
#define phys_ram_base (*(phys_addr_t *)XIP_FIXUP(&phys_ram_base))
|
||||
/* called from head.S with MMU off */
|
||||
asmlinkage void __init __copy_data(void)
|
||||
{
|
||||
|
||||
@@ -22,8 +22,7 @@ asmlinkage void __init kasan_early_init(void)
|
||||
|
||||
for (i = 0; i < PTRS_PER_PTE; ++i)
|
||||
set_pte(kasan_early_shadow_pte + i,
|
||||
mk_pte(virt_to_page(kasan_early_shadow_page),
|
||||
PAGE_KERNEL));
|
||||
pfn_pte(virt_to_pfn(kasan_early_shadow_page), PAGE_KERNEL));
|
||||
|
||||
for (i = 0; i < PTRS_PER_PMD; ++i)
|
||||
set_pmd(kasan_early_shadow_pmd + i,
|
||||
|
||||
@@ -69,8 +69,13 @@ static inline void swap_ex_entry_fixup(struct exception_table_entry *a,
|
||||
{
|
||||
a->fixup = b->fixup + delta;
|
||||
b->fixup = tmp.fixup - delta;
|
||||
a->handler = b->handler + delta;
|
||||
b->handler = tmp.handler - delta;
|
||||
a->handler = b->handler;
|
||||
if (a->handler)
|
||||
a->handler += delta;
|
||||
b->handler = tmp.handler;
|
||||
if (b->handler)
|
||||
b->handler -= delta;
|
||||
}
|
||||
#define swap_ex_entry_fixup swap_ex_entry_fixup
|
||||
|
||||
#endif
|
||||
|
||||
@@ -3447,7 +3447,7 @@ bool kvm_arch_no_poll(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/* do not poll with more than halt_poll_max_steal percent of steal time */
|
||||
if (S390_lowcore.avg_steal_timer * 100 / (TICK_USEC << 12) >=
|
||||
halt_poll_max_steal) {
|
||||
READ_ONCE(halt_poll_max_steal)) {
|
||||
vcpu->stat.halt_no_poll_steal++;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -68,15 +68,6 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
/*
|
||||
* Only check the mask _after_ interrupt has been disabled to avoid the
|
||||
* mask changing under our feet.
|
||||
*/
|
||||
if (cpumask_empty(cpus)) {
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
|
||||
flush_pcpu = (struct hv_tlb_flush **)
|
||||
this_cpu_ptr(hyperv_pcpu_input_arg);
|
||||
|
||||
@@ -115,7 +106,9 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
|
||||
* must. We will also check all VP numbers when walking the
|
||||
* supplied CPU set to remain correct in all cases.
|
||||
*/
|
||||
if (hv_cpu_number_to_vp_number(cpumask_last(cpus)) >= 64)
|
||||
cpu = cpumask_last(cpus);
|
||||
|
||||
if (cpu < nr_cpumask_bits && hv_cpu_number_to_vp_number(cpu) >= 64)
|
||||
goto do_ex_hypercall;
|
||||
|
||||
for_each_cpu(cpu, cpus) {
|
||||
@@ -131,6 +124,12 @@ static void hyperv_flush_tlb_multi(const struct cpumask *cpus,
|
||||
__set_bit(vcpu, (unsigned long *)
|
||||
&flush->processor_mask);
|
||||
}
|
||||
|
||||
/* nothing to flush if 'processor_mask' ends up being empty */
|
||||
if (!flush->processor_mask) {
|
||||
local_irq_restore(flags);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -3579,7 +3579,7 @@ set_root_pgd:
|
||||
out_unlock:
|
||||
write_unlock(&vcpu->kvm->mmu_lock);
|
||||
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
static int mmu_alloc_special_roots(struct kvm_vcpu *vcpu)
|
||||
|
||||
@@ -51,7 +51,7 @@ void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
|
||||
|
||||
/* The full case. */
|
||||
do {
|
||||
old.control = new.control = pi_desc->control;
|
||||
old.control = new.control = READ_ONCE(pi_desc->control);
|
||||
|
||||
dest = cpu_physical_id(cpu);
|
||||
|
||||
@@ -104,7 +104,7 @@ static void __pi_post_block(struct kvm_vcpu *vcpu)
|
||||
unsigned int dest;
|
||||
|
||||
do {
|
||||
old.control = new.control = pi_desc->control;
|
||||
old.control = new.control = READ_ONCE(pi_desc->control);
|
||||
WARN(old.nv != POSTED_INTR_WAKEUP_VECTOR,
|
||||
"Wakeup handler not enabled while the VCPU is blocked\n");
|
||||
|
||||
@@ -147,7 +147,8 @@ int pi_pre_block(struct kvm_vcpu *vcpu)
|
||||
struct pi_desc old, new;
|
||||
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
|
||||
|
||||
if (!vmx_can_use_vtd_pi(vcpu->kvm))
|
||||
if (!vmx_can_use_vtd_pi(vcpu->kvm) ||
|
||||
vmx_interrupt_blocked(vcpu))
|
||||
return 0;
|
||||
|
||||
WARN_ON(irqs_disabled());
|
||||
@@ -162,7 +163,7 @@ int pi_pre_block(struct kvm_vcpu *vcpu)
|
||||
}
|
||||
|
||||
do {
|
||||
old.control = new.control = pi_desc->control;
|
||||
old.control = new.control = READ_ONCE(pi_desc->control);
|
||||
|
||||
WARN((pi_desc->sn == 1),
|
||||
"Warning: SN field of posted-interrupts "
|
||||
|
||||
@@ -848,6 +848,7 @@ int load_pdptrs(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu, unsigned long cr3)
|
||||
|
||||
memcpy(mmu->pdptrs, pdpte, sizeof(mmu->pdptrs));
|
||||
kvm_register_mark_dirty(vcpu, VCPU_EXREG_PDPTR);
|
||||
kvm_make_request(KVM_REQ_LOAD_MMU_PGD, vcpu);
|
||||
vcpu->arch.pdptrs_from_userspace = false;
|
||||
|
||||
out:
|
||||
@@ -7998,7 +7999,12 @@ int x86_emulate_instruction(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
|
||||
* updating interruptibility state and injecting single-step #DBs.
|
||||
*/
|
||||
if (emulation_type & EMULTYPE_SKIP) {
|
||||
kvm_rip_write(vcpu, ctxt->_eip);
|
||||
if (ctxt->mode != X86EMUL_MODE_PROT64)
|
||||
ctxt->eip = (u32)ctxt->_eip;
|
||||
else
|
||||
ctxt->eip = ctxt->_eip;
|
||||
|
||||
kvm_rip_write(vcpu, ctxt->eip);
|
||||
if (ctxt->eflags & X86_EFLAGS_RF)
|
||||
kvm_set_rflags(vcpu, ctxt->eflags & ~X86_EFLAGS_RF);
|
||||
return 1;
|
||||
@@ -8062,6 +8068,9 @@ restart:
|
||||
writeback = false;
|
||||
r = 0;
|
||||
vcpu->arch.complete_userspace_io = complete_emulated_mmio;
|
||||
} else if (vcpu->arch.complete_userspace_io) {
|
||||
writeback = false;
|
||||
r = 0;
|
||||
} else if (r == EMULATION_RESTART)
|
||||
goto restart;
|
||||
else
|
||||
|
||||
@@ -446,7 +446,7 @@ static struct bio *bio_copy_kern(struct request_queue *q, void *data,
|
||||
if (bytes > len)
|
||||
bytes = len;
|
||||
|
||||
page = alloc_page(GFP_NOIO | gfp_mask);
|
||||
page = alloc_page(GFP_NOIO | __GFP_ZERO | gfp_mask);
|
||||
if (!page)
|
||||
goto cleanup;
|
||||
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <trace/hooks/fault.h>
|
||||
#include <trace/hooks/traps.h>
|
||||
#include <trace/hooks/fips140.h>
|
||||
#include <trace/hooks/thermal.h>
|
||||
|
||||
/*
|
||||
* Export tracepoints that act as a bare tracehook (ie: have no trace event
|
||||
@@ -248,3 +249,5 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_sha256);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_aes_expandkey);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_aes_encrypt);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_aes_decrypt);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_modify_thermal_request_freq);
|
||||
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_modify_thermal_target_freq);
|
||||
|
||||
@@ -964,14 +964,14 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
|
||||
if ((freq >> 12) != 0xABCDE) {
|
||||
int i;
|
||||
u8 sr;
|
||||
u16 sr;
|
||||
u32 total = 0;
|
||||
|
||||
pr_warn("BIOS has not set timing clocks\n");
|
||||
|
||||
/* This is the process the HPT371 BIOS is reported to use */
|
||||
for (i = 0; i < 128; i++) {
|
||||
pci_read_config_byte(dev, 0x78, &sr);
|
||||
pci_read_config_word(dev, 0x78, &sr);
|
||||
total += sr & 0x1FF;
|
||||
udelay(15);
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ static int lcd2s_redefine_char(struct charlcd *lcd, char *esc)
|
||||
if (buf[1] > 7)
|
||||
return 1;
|
||||
|
||||
i = 0;
|
||||
i = 2;
|
||||
shift = 0;
|
||||
value = 0;
|
||||
while (*esc && i < LCD2S_CHARACTER_SIZE + 2) {
|
||||
@@ -298,6 +298,10 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c,
|
||||
I2C_FUNC_SMBUS_WRITE_BLOCK_DATA))
|
||||
return -EIO;
|
||||
|
||||
lcd2s = devm_kzalloc(&i2c->dev, sizeof(*lcd2s), GFP_KERNEL);
|
||||
if (!lcd2s)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Test, if the display is responding */
|
||||
err = lcd2s_i2c_smbus_write_byte(i2c, LCD2S_CMD_DISPLAY_OFF);
|
||||
if (err < 0)
|
||||
@@ -307,12 +311,6 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c,
|
||||
if (!lcd)
|
||||
return -ENOMEM;
|
||||
|
||||
lcd2s = kzalloc(sizeof(struct lcd2s_data), GFP_KERNEL);
|
||||
if (!lcd2s) {
|
||||
err = -ENOMEM;
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
lcd->drvdata = lcd2s;
|
||||
lcd2s->i2c = i2c;
|
||||
lcd2s->charlcd = lcd;
|
||||
@@ -321,26 +319,24 @@ static int lcd2s_i2c_probe(struct i2c_client *i2c,
|
||||
err = device_property_read_u32(&i2c->dev, "display-height-chars",
|
||||
&lcd->height);
|
||||
if (err)
|
||||
goto fail2;
|
||||
goto fail1;
|
||||
|
||||
err = device_property_read_u32(&i2c->dev, "display-width-chars",
|
||||
&lcd->width);
|
||||
if (err)
|
||||
goto fail2;
|
||||
goto fail1;
|
||||
|
||||
lcd->ops = &lcd2s_ops;
|
||||
|
||||
err = charlcd_register(lcd2s->charlcd);
|
||||
if (err)
|
||||
goto fail2;
|
||||
goto fail1;
|
||||
|
||||
i2c_set_clientdata(i2c, lcd2s);
|
||||
return 0;
|
||||
|
||||
fail2:
|
||||
kfree(lcd2s);
|
||||
fail1:
|
||||
kfree(lcd);
|
||||
charlcd_free(lcd2s->charlcd);
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -349,7 +345,7 @@ static int lcd2s_i2c_remove(struct i2c_client *i2c)
|
||||
struct lcd2s_data *lcd2s = i2c_get_clientdata(i2c);
|
||||
|
||||
charlcd_unregister(lcd2s->charlcd);
|
||||
kfree(lcd2s->charlcd);
|
||||
charlcd_free(lcd2s->charlcd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
#include <linux/ioprio.h>
|
||||
#include <linux/blk-cgroup.h>
|
||||
#include <linux/sched/mm.h>
|
||||
#include <linux/statfs.h>
|
||||
|
||||
#include "loop.h"
|
||||
|
||||
@@ -939,8 +940,13 @@ static void loop_config_discard(struct loop_device *lo)
|
||||
granularity = 0;
|
||||
|
||||
} else {
|
||||
struct kstatfs sbuf;
|
||||
|
||||
max_discard_sectors = UINT_MAX >> 9;
|
||||
granularity = inode->i_sb->s_blocksize;
|
||||
if (!vfs_statfs(&file->f_path, &sbuf))
|
||||
granularity = sbuf.f_bsize;
|
||||
else
|
||||
max_discard_sectors = 0;
|
||||
}
|
||||
|
||||
if (max_discard_sectors) {
|
||||
|
||||
@@ -241,8 +241,7 @@ static void __init dmtimer_systimer_assign_alwon(void)
|
||||
bool quirk_unreliable_oscillator = false;
|
||||
|
||||
/* Quirk unreliable 32 KiHz oscillator with incomplete dts */
|
||||
if (of_machine_is_compatible("ti,omap3-beagle-ab4") ||
|
||||
of_machine_is_compatible("timll,omap3-devkit8000")) {
|
||||
if (of_machine_is_compatible("ti,omap3-beagle-ab4")) {
|
||||
quirk_unreliable_oscillator = true;
|
||||
counter_32k = -ENODEV;
|
||||
}
|
||||
|
||||
@@ -115,8 +115,10 @@ static dma_cookie_t shdma_tx_submit(struct dma_async_tx_descriptor *tx)
|
||||
ret = pm_runtime_get(schan->dev);
|
||||
|
||||
spin_unlock_irq(&schan->chan_lock);
|
||||
if (ret < 0)
|
||||
if (ret < 0) {
|
||||
dev_err(schan->dev, "%s(): GET = %d\n", __func__, ret);
|
||||
pm_runtime_put(schan->dev);
|
||||
}
|
||||
|
||||
pm_runtime_barrier(schan->dev);
|
||||
|
||||
|
||||
@@ -2112,7 +2112,7 @@ static void __exit scmi_driver_exit(void)
|
||||
}
|
||||
module_exit(scmi_driver_exit);
|
||||
|
||||
MODULE_ALIAS("platform: arm-scmi");
|
||||
MODULE_ALIAS("platform:arm-scmi");
|
||||
MODULE_AUTHOR("Sudeep Holla <sudeep.holla@arm.com>");
|
||||
MODULE_DESCRIPTION("ARM SCMI protocol driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
||||
@@ -25,7 +25,7 @@ typedef void __noreturn (*jump_kernel_func)(unsigned int, unsigned long);
|
||||
|
||||
static u32 hartid;
|
||||
|
||||
static u32 get_boot_hartid_from_fdt(void)
|
||||
static int get_boot_hartid_from_fdt(void)
|
||||
{
|
||||
const void *fdt;
|
||||
int chosen_node, len;
|
||||
@@ -33,23 +33,26 @@ static u32 get_boot_hartid_from_fdt(void)
|
||||
|
||||
fdt = get_efi_config_table(DEVICE_TREE_GUID);
|
||||
if (!fdt)
|
||||
return U32_MAX;
|
||||
return -EINVAL;
|
||||
|
||||
chosen_node = fdt_path_offset(fdt, "/chosen");
|
||||
if (chosen_node < 0)
|
||||
return U32_MAX;
|
||||
return -EINVAL;
|
||||
|
||||
prop = fdt_getprop((void *)fdt, chosen_node, "boot-hartid", &len);
|
||||
if (!prop || len != sizeof(u32))
|
||||
return U32_MAX;
|
||||
return -EINVAL;
|
||||
|
||||
return fdt32_to_cpu(*prop);
|
||||
hartid = fdt32_to_cpu(*prop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
efi_status_t check_platform_features(void)
|
||||
{
|
||||
hartid = get_boot_hartid_from_fdt();
|
||||
if (hartid == U32_MAX) {
|
||||
int ret;
|
||||
|
||||
ret = get_boot_hartid_from_fdt();
|
||||
if (ret) {
|
||||
efi_err("/chosen/boot-hartid missing or invalid!\n");
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
@@ -742,6 +742,7 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
|
||||
{
|
||||
const struct efivar_operations *ops;
|
||||
efi_status_t status;
|
||||
unsigned long varsize;
|
||||
|
||||
if (!__efivars)
|
||||
return -EINVAL;
|
||||
@@ -764,15 +765,17 @@ int efivar_entry_set_safe(efi_char16_t *name, efi_guid_t vendor, u32 attributes,
|
||||
return efivar_entry_set_nonblocking(name, vendor, attributes,
|
||||
size, data);
|
||||
|
||||
varsize = size + ucs2_strsize(name, 1024);
|
||||
if (!block) {
|
||||
if (down_trylock(&efivars_lock))
|
||||
return -EBUSY;
|
||||
status = check_var_size_nonblocking(attributes, varsize);
|
||||
} else {
|
||||
if (down_interruptible(&efivars_lock))
|
||||
return -EINTR;
|
||||
status = check_var_size(attributes, varsize);
|
||||
}
|
||||
|
||||
status = check_var_size(attributes, size + ucs2_strsize(name, 1024));
|
||||
if (status != EFI_SUCCESS) {
|
||||
up(&efivars_lock);
|
||||
return -ENOSPC;
|
||||
|
||||
@@ -891,6 +891,717 @@ MODULE_PARM_DESC(smu_pptable_id,
|
||||
"specify pptable id to be used (-1 = auto(default) value, 0 = use pptable from vbios, > 0 = soft pptable id)");
|
||||
module_param_named(smu_pptable_id, amdgpu_smu_pptable_id, int, 0444);
|
||||
|
||||
/* These devices are not supported by amdgpu.
|
||||
* They are supported by the mach64, r128, radeon drivers
|
||||
*/
|
||||
static const u16 amdgpu_unsupported_pciidlist[] = {
|
||||
/* mach64 */
|
||||
0x4354,
|
||||
0x4358,
|
||||
0x4554,
|
||||
0x4742,
|
||||
0x4744,
|
||||
0x4749,
|
||||
0x474C,
|
||||
0x474D,
|
||||
0x474E,
|
||||
0x474F,
|
||||
0x4750,
|
||||
0x4751,
|
||||
0x4752,
|
||||
0x4753,
|
||||
0x4754,
|
||||
0x4755,
|
||||
0x4756,
|
||||
0x4757,
|
||||
0x4758,
|
||||
0x4759,
|
||||
0x475A,
|
||||
0x4C42,
|
||||
0x4C44,
|
||||
0x4C47,
|
||||
0x4C49,
|
||||
0x4C4D,
|
||||
0x4C4E,
|
||||
0x4C50,
|
||||
0x4C51,
|
||||
0x4C52,
|
||||
0x4C53,
|
||||
0x5654,
|
||||
0x5655,
|
||||
0x5656,
|
||||
/* r128 */
|
||||
0x4c45,
|
||||
0x4c46,
|
||||
0x4d46,
|
||||
0x4d4c,
|
||||
0x5041,
|
||||
0x5042,
|
||||
0x5043,
|
||||
0x5044,
|
||||
0x5045,
|
||||
0x5046,
|
||||
0x5047,
|
||||
0x5048,
|
||||
0x5049,
|
||||
0x504A,
|
||||
0x504B,
|
||||
0x504C,
|
||||
0x504D,
|
||||
0x504E,
|
||||
0x504F,
|
||||
0x5050,
|
||||
0x5051,
|
||||
0x5052,
|
||||
0x5053,
|
||||
0x5054,
|
||||
0x5055,
|
||||
0x5056,
|
||||
0x5057,
|
||||
0x5058,
|
||||
0x5245,
|
||||
0x5246,
|
||||
0x5247,
|
||||
0x524b,
|
||||
0x524c,
|
||||
0x534d,
|
||||
0x5446,
|
||||
0x544C,
|
||||
0x5452,
|
||||
/* radeon */
|
||||
0x3150,
|
||||
0x3151,
|
||||
0x3152,
|
||||
0x3154,
|
||||
0x3155,
|
||||
0x3E50,
|
||||
0x3E54,
|
||||
0x4136,
|
||||
0x4137,
|
||||
0x4144,
|
||||
0x4145,
|
||||
0x4146,
|
||||
0x4147,
|
||||
0x4148,
|
||||
0x4149,
|
||||
0x414A,
|
||||
0x414B,
|
||||
0x4150,
|
||||
0x4151,
|
||||
0x4152,
|
||||
0x4153,
|
||||
0x4154,
|
||||
0x4155,
|
||||
0x4156,
|
||||
0x4237,
|
||||
0x4242,
|
||||
0x4336,
|
||||
0x4337,
|
||||
0x4437,
|
||||
0x4966,
|
||||
0x4967,
|
||||
0x4A48,
|
||||
0x4A49,
|
||||
0x4A4A,
|
||||
0x4A4B,
|
||||
0x4A4C,
|
||||
0x4A4D,
|
||||
0x4A4E,
|
||||
0x4A4F,
|
||||
0x4A50,
|
||||
0x4A54,
|
||||
0x4B48,
|
||||
0x4B49,
|
||||
0x4B4A,
|
||||
0x4B4B,
|
||||
0x4B4C,
|
||||
0x4C57,
|
||||
0x4C58,
|
||||
0x4C59,
|
||||
0x4C5A,
|
||||
0x4C64,
|
||||
0x4C66,
|
||||
0x4C67,
|
||||
0x4E44,
|
||||
0x4E45,
|
||||
0x4E46,
|
||||
0x4E47,
|
||||
0x4E48,
|
||||
0x4E49,
|
||||
0x4E4A,
|
||||
0x4E4B,
|
||||
0x4E50,
|
||||
0x4E51,
|
||||
0x4E52,
|
||||
0x4E53,
|
||||
0x4E54,
|
||||
0x4E56,
|
||||
0x5144,
|
||||
0x5145,
|
||||
0x5146,
|
||||
0x5147,
|
||||
0x5148,
|
||||
0x514C,
|
||||
0x514D,
|
||||
0x5157,
|
||||
0x5158,
|
||||
0x5159,
|
||||
0x515A,
|
||||
0x515E,
|
||||
0x5460,
|
||||
0x5462,
|
||||
0x5464,
|
||||
0x5548,
|
||||
0x5549,
|
||||
0x554A,
|
||||
0x554B,
|
||||
0x554C,
|
||||
0x554D,
|
||||
0x554E,
|
||||
0x554F,
|
||||
0x5550,
|
||||
0x5551,
|
||||
0x5552,
|
||||
0x5554,
|
||||
0x564A,
|
||||
0x564B,
|
||||
0x564F,
|
||||
0x5652,
|
||||
0x5653,
|
||||
0x5657,
|
||||
0x5834,
|
||||
0x5835,
|
||||
0x5954,
|
||||
0x5955,
|
||||
0x5974,
|
||||
0x5975,
|
||||
0x5960,
|
||||
0x5961,
|
||||
0x5962,
|
||||
0x5964,
|
||||
0x5965,
|
||||
0x5969,
|
||||
0x5a41,
|
||||
0x5a42,
|
||||
0x5a61,
|
||||
0x5a62,
|
||||
0x5b60,
|
||||
0x5b62,
|
||||
0x5b63,
|
||||
0x5b64,
|
||||
0x5b65,
|
||||
0x5c61,
|
||||
0x5c63,
|
||||
0x5d48,
|
||||
0x5d49,
|
||||
0x5d4a,
|
||||
0x5d4c,
|
||||
0x5d4d,
|
||||
0x5d4e,
|
||||
0x5d4f,
|
||||
0x5d50,
|
||||
0x5d52,
|
||||
0x5d57,
|
||||
0x5e48,
|
||||
0x5e4a,
|
||||
0x5e4b,
|
||||
0x5e4c,
|
||||
0x5e4d,
|
||||
0x5e4f,
|
||||
0x6700,
|
||||
0x6701,
|
||||
0x6702,
|
||||
0x6703,
|
||||
0x6704,
|
||||
0x6705,
|
||||
0x6706,
|
||||
0x6707,
|
||||
0x6708,
|
||||
0x6709,
|
||||
0x6718,
|
||||
0x6719,
|
||||
0x671c,
|
||||
0x671d,
|
||||
0x671f,
|
||||
0x6720,
|
||||
0x6721,
|
||||
0x6722,
|
||||
0x6723,
|
||||
0x6724,
|
||||
0x6725,
|
||||
0x6726,
|
||||
0x6727,
|
||||
0x6728,
|
||||
0x6729,
|
||||
0x6738,
|
||||
0x6739,
|
||||
0x673e,
|
||||
0x6740,
|
||||
0x6741,
|
||||
0x6742,
|
||||
0x6743,
|
||||
0x6744,
|
||||
0x6745,
|
||||
0x6746,
|
||||
0x6747,
|
||||
0x6748,
|
||||
0x6749,
|
||||
0x674A,
|
||||
0x6750,
|
||||
0x6751,
|
||||
0x6758,
|
||||
0x6759,
|
||||
0x675B,
|
||||
0x675D,
|
||||
0x675F,
|
||||
0x6760,
|
||||
0x6761,
|
||||
0x6762,
|
||||
0x6763,
|
||||
0x6764,
|
||||
0x6765,
|
||||
0x6766,
|
||||
0x6767,
|
||||
0x6768,
|
||||
0x6770,
|
||||
0x6771,
|
||||
0x6772,
|
||||
0x6778,
|
||||
0x6779,
|
||||
0x677B,
|
||||
0x6840,
|
||||
0x6841,
|
||||
0x6842,
|
||||
0x6843,
|
||||
0x6849,
|
||||
0x684C,
|
||||
0x6850,
|
||||
0x6858,
|
||||
0x6859,
|
||||
0x6880,
|
||||
0x6888,
|
||||
0x6889,
|
||||
0x688A,
|
||||
0x688C,
|
||||
0x688D,
|
||||
0x6898,
|
||||
0x6899,
|
||||
0x689b,
|
||||
0x689c,
|
||||
0x689d,
|
||||
0x689e,
|
||||
0x68a0,
|
||||
0x68a1,
|
||||
0x68a8,
|
||||
0x68a9,
|
||||
0x68b0,
|
||||
0x68b8,
|
||||
0x68b9,
|
||||
0x68ba,
|
||||
0x68be,
|
||||
0x68bf,
|
||||
0x68c0,
|
||||
0x68c1,
|
||||
0x68c7,
|
||||
0x68c8,
|
||||
0x68c9,
|
||||
0x68d8,
|
||||
0x68d9,
|
||||
0x68da,
|
||||
0x68de,
|
||||
0x68e0,
|
||||
0x68e1,
|
||||
0x68e4,
|
||||
0x68e5,
|
||||
0x68e8,
|
||||
0x68e9,
|
||||
0x68f1,
|
||||
0x68f2,
|
||||
0x68f8,
|
||||
0x68f9,
|
||||
0x68fa,
|
||||
0x68fe,
|
||||
0x7100,
|
||||
0x7101,
|
||||
0x7102,
|
||||
0x7103,
|
||||
0x7104,
|
||||
0x7105,
|
||||
0x7106,
|
||||
0x7108,
|
||||
0x7109,
|
||||
0x710A,
|
||||
0x710B,
|
||||
0x710C,
|
||||
0x710E,
|
||||
0x710F,
|
||||
0x7140,
|
||||
0x7141,
|
||||
0x7142,
|
||||
0x7143,
|
||||
0x7144,
|
||||
0x7145,
|
||||
0x7146,
|
||||
0x7147,
|
||||
0x7149,
|
||||
0x714A,
|
||||
0x714B,
|
||||
0x714C,
|
||||
0x714D,
|
||||
0x714E,
|
||||
0x714F,
|
||||
0x7151,
|
||||
0x7152,
|
||||
0x7153,
|
||||
0x715E,
|
||||
0x715F,
|
||||
0x7180,
|
||||
0x7181,
|
||||
0x7183,
|
||||
0x7186,
|
||||
0x7187,
|
||||
0x7188,
|
||||
0x718A,
|
||||
0x718B,
|
||||
0x718C,
|
||||
0x718D,
|
||||
0x718F,
|
||||
0x7193,
|
||||
0x7196,
|
||||
0x719B,
|
||||
0x719F,
|
||||
0x71C0,
|
||||
0x71C1,
|
||||
0x71C2,
|
||||
0x71C3,
|
||||
0x71C4,
|
||||
0x71C5,
|
||||
0x71C6,
|
||||
0x71C7,
|
||||
0x71CD,
|
||||
0x71CE,
|
||||
0x71D2,
|
||||
0x71D4,
|
||||
0x71D5,
|
||||
0x71D6,
|
||||
0x71DA,
|
||||
0x71DE,
|
||||
0x7200,
|
||||
0x7210,
|
||||
0x7211,
|
||||
0x7240,
|
||||
0x7243,
|
||||
0x7244,
|
||||
0x7245,
|
||||
0x7246,
|
||||
0x7247,
|
||||
0x7248,
|
||||
0x7249,
|
||||
0x724A,
|
||||
0x724B,
|
||||
0x724C,
|
||||
0x724D,
|
||||
0x724E,
|
||||
0x724F,
|
||||
0x7280,
|
||||
0x7281,
|
||||
0x7283,
|
||||
0x7284,
|
||||
0x7287,
|
||||
0x7288,
|
||||
0x7289,
|
||||
0x728B,
|
||||
0x728C,
|
||||
0x7290,
|
||||
0x7291,
|
||||
0x7293,
|
||||
0x7297,
|
||||
0x7834,
|
||||
0x7835,
|
||||
0x791e,
|
||||
0x791f,
|
||||
0x793f,
|
||||
0x7941,
|
||||
0x7942,
|
||||
0x796c,
|
||||
0x796d,
|
||||
0x796e,
|
||||
0x796f,
|
||||
0x9400,
|
||||
0x9401,
|
||||
0x9402,
|
||||
0x9403,
|
||||
0x9405,
|
||||
0x940A,
|
||||
0x940B,
|
||||
0x940F,
|
||||
0x94A0,
|
||||
0x94A1,
|
||||
0x94A3,
|
||||
0x94B1,
|
||||
0x94B3,
|
||||
0x94B4,
|
||||
0x94B5,
|
||||
0x94B9,
|
||||
0x9440,
|
||||
0x9441,
|
||||
0x9442,
|
||||
0x9443,
|
||||
0x9444,
|
||||
0x9446,
|
||||
0x944A,
|
||||
0x944B,
|
||||
0x944C,
|
||||
0x944E,
|
||||
0x9450,
|
||||
0x9452,
|
||||
0x9456,
|
||||
0x945A,
|
||||
0x945B,
|
||||
0x945E,
|
||||
0x9460,
|
||||
0x9462,
|
||||
0x946A,
|
||||
0x946B,
|
||||
0x947A,
|
||||
0x947B,
|
||||
0x9480,
|
||||
0x9487,
|
||||
0x9488,
|
||||
0x9489,
|
||||
0x948A,
|
||||
0x948F,
|
||||
0x9490,
|
||||
0x9491,
|
||||
0x9495,
|
||||
0x9498,
|
||||
0x949C,
|
||||
0x949E,
|
||||
0x949F,
|
||||
0x94C0,
|
||||
0x94C1,
|
||||
0x94C3,
|
||||
0x94C4,
|
||||
0x94C5,
|
||||
0x94C6,
|
||||
0x94C7,
|
||||
0x94C8,
|
||||
0x94C9,
|
||||
0x94CB,
|
||||
0x94CC,
|
||||
0x94CD,
|
||||
0x9500,
|
||||
0x9501,
|
||||
0x9504,
|
||||
0x9505,
|
||||
0x9506,
|
||||
0x9507,
|
||||
0x9508,
|
||||
0x9509,
|
||||
0x950F,
|
||||
0x9511,
|
||||
0x9515,
|
||||
0x9517,
|
||||
0x9519,
|
||||
0x9540,
|
||||
0x9541,
|
||||
0x9542,
|
||||
0x954E,
|
||||
0x954F,
|
||||
0x9552,
|
||||
0x9553,
|
||||
0x9555,
|
||||
0x9557,
|
||||
0x955f,
|
||||
0x9580,
|
||||
0x9581,
|
||||
0x9583,
|
||||
0x9586,
|
||||
0x9587,
|
||||
0x9588,
|
||||
0x9589,
|
||||
0x958A,
|
||||
0x958B,
|
||||
0x958C,
|
||||
0x958D,
|
||||
0x958E,
|
||||
0x958F,
|
||||
0x9590,
|
||||
0x9591,
|
||||
0x9593,
|
||||
0x9595,
|
||||
0x9596,
|
||||
0x9597,
|
||||
0x9598,
|
||||
0x9599,
|
||||
0x959B,
|
||||
0x95C0,
|
||||
0x95C2,
|
||||
0x95C4,
|
||||
0x95C5,
|
||||
0x95C6,
|
||||
0x95C7,
|
||||
0x95C9,
|
||||
0x95CC,
|
||||
0x95CD,
|
||||
0x95CE,
|
||||
0x95CF,
|
||||
0x9610,
|
||||
0x9611,
|
||||
0x9612,
|
||||
0x9613,
|
||||
0x9614,
|
||||
0x9615,
|
||||
0x9616,
|
||||
0x9640,
|
||||
0x9641,
|
||||
0x9642,
|
||||
0x9643,
|
||||
0x9644,
|
||||
0x9645,
|
||||
0x9647,
|
||||
0x9648,
|
||||
0x9649,
|
||||
0x964a,
|
||||
0x964b,
|
||||
0x964c,
|
||||
0x964e,
|
||||
0x964f,
|
||||
0x9710,
|
||||
0x9711,
|
||||
0x9712,
|
||||
0x9713,
|
||||
0x9714,
|
||||
0x9715,
|
||||
0x9802,
|
||||
0x9803,
|
||||
0x9804,
|
||||
0x9805,
|
||||
0x9806,
|
||||
0x9807,
|
||||
0x9808,
|
||||
0x9809,
|
||||
0x980A,
|
||||
0x9900,
|
||||
0x9901,
|
||||
0x9903,
|
||||
0x9904,
|
||||
0x9905,
|
||||
0x9906,
|
||||
0x9907,
|
||||
0x9908,
|
||||
0x9909,
|
||||
0x990A,
|
||||
0x990B,
|
||||
0x990C,
|
||||
0x990D,
|
||||
0x990E,
|
||||
0x990F,
|
||||
0x9910,
|
||||
0x9913,
|
||||
0x9917,
|
||||
0x9918,
|
||||
0x9919,
|
||||
0x9990,
|
||||
0x9991,
|
||||
0x9992,
|
||||
0x9993,
|
||||
0x9994,
|
||||
0x9995,
|
||||
0x9996,
|
||||
0x9997,
|
||||
0x9998,
|
||||
0x9999,
|
||||
0x999A,
|
||||
0x999B,
|
||||
0x999C,
|
||||
0x999D,
|
||||
0x99A0,
|
||||
0x99A2,
|
||||
0x99A4,
|
||||
/* radeon secondary ids */
|
||||
0x3171,
|
||||
0x3e70,
|
||||
0x4164,
|
||||
0x4165,
|
||||
0x4166,
|
||||
0x4168,
|
||||
0x4170,
|
||||
0x4171,
|
||||
0x4172,
|
||||
0x4173,
|
||||
0x496e,
|
||||
0x4a69,
|
||||
0x4a6a,
|
||||
0x4a6b,
|
||||
0x4a70,
|
||||
0x4a74,
|
||||
0x4b69,
|
||||
0x4b6b,
|
||||
0x4b6c,
|
||||
0x4c6e,
|
||||
0x4e64,
|
||||
0x4e65,
|
||||
0x4e66,
|
||||
0x4e67,
|
||||
0x4e68,
|
||||
0x4e69,
|
||||
0x4e6a,
|
||||
0x4e71,
|
||||
0x4f73,
|
||||
0x5569,
|
||||
0x556b,
|
||||
0x556d,
|
||||
0x556f,
|
||||
0x5571,
|
||||
0x5854,
|
||||
0x5874,
|
||||
0x5940,
|
||||
0x5941,
|
||||
0x5b72,
|
||||
0x5b73,
|
||||
0x5b74,
|
||||
0x5b75,
|
||||
0x5d44,
|
||||
0x5d45,
|
||||
0x5d6d,
|
||||
0x5d6f,
|
||||
0x5d72,
|
||||
0x5d77,
|
||||
0x5e6b,
|
||||
0x5e6d,
|
||||
0x7120,
|
||||
0x7124,
|
||||
0x7129,
|
||||
0x712e,
|
||||
0x712f,
|
||||
0x7162,
|
||||
0x7163,
|
||||
0x7166,
|
||||
0x7167,
|
||||
0x7172,
|
||||
0x7173,
|
||||
0x71a0,
|
||||
0x71a1,
|
||||
0x71a3,
|
||||
0x71a7,
|
||||
0x71bb,
|
||||
0x71e0,
|
||||
0x71e1,
|
||||
0x71e2,
|
||||
0x71e6,
|
||||
0x71e7,
|
||||
0x71f2,
|
||||
0x7269,
|
||||
0x726b,
|
||||
0x726e,
|
||||
0x72a0,
|
||||
0x72a8,
|
||||
0x72b1,
|
||||
0x72b3,
|
||||
0x793f,
|
||||
};
|
||||
|
||||
static const struct pci_device_id pciidlist[] = {
|
||||
#ifdef CONFIG_DRM_AMDGPU_SI
|
||||
{0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI},
|
||||
@@ -1273,7 +1984,7 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
struct drm_device *ddev;
|
||||
struct amdgpu_device *adev;
|
||||
unsigned long flags = ent->driver_data;
|
||||
int ret, retry = 0;
|
||||
int ret, retry = 0, i;
|
||||
bool supports_atomic = false;
|
||||
bool is_fw_fb;
|
||||
resource_size_t base, size;
|
||||
@@ -1281,6 +1992,12 @@ static int amdgpu_pci_probe(struct pci_dev *pdev,
|
||||
if (amdgpu_aspm == -1 && !pcie_aspm_enabled(pdev))
|
||||
amdgpu_aspm = 0;
|
||||
|
||||
/* skip devices which are owned by radeon */
|
||||
for (i = 0; i < ARRAY_SIZE(amdgpu_unsupported_pciidlist); i++) {
|
||||
if (amdgpu_unsupported_pciidlist[i] == pdev->device)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (amdgpu_virtual_display ||
|
||||
amdgpu_device_asic_has_dc_support(flags & AMD_ASIC_MASK))
|
||||
supports_atomic = true;
|
||||
|
||||
@@ -142,15 +142,16 @@ static void amdgpu_vkms_crtc_atomic_disable(struct drm_crtc *crtc,
|
||||
static void amdgpu_vkms_crtc_atomic_flush(struct drm_crtc *crtc,
|
||||
struct drm_atomic_state *state)
|
||||
{
|
||||
unsigned long flags;
|
||||
if (crtc->state->event) {
|
||||
spin_lock(&crtc->dev->event_lock);
|
||||
spin_lock_irqsave(&crtc->dev->event_lock, flags);
|
||||
|
||||
if (drm_crtc_vblank_get(crtc) != 0)
|
||||
drm_crtc_send_vblank_event(crtc, crtc->state->event);
|
||||
else
|
||||
drm_crtc_arm_vblank_event(crtc, crtc->state->event);
|
||||
|
||||
spin_unlock(&crtc->dev->event_lock);
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
|
||||
crtc->state->event = NULL;
|
||||
}
|
||||
|
||||
@@ -768,11 +768,17 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm,
|
||||
* Check if all VM PDs/PTs are ready for updates
|
||||
*
|
||||
* Returns:
|
||||
* True if eviction list is empty.
|
||||
* True if VM is not evicting.
|
||||
*/
|
||||
bool amdgpu_vm_ready(struct amdgpu_vm *vm)
|
||||
{
|
||||
return list_empty(&vm->evicted);
|
||||
bool ret;
|
||||
|
||||
amdgpu_vm_eviction_lock(vm);
|
||||
ret = !vm->evicting;
|
||||
amdgpu_vm_eviction_unlock(vm);
|
||||
|
||||
return ret && list_empty(&vm->evicted);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1060,6 +1060,9 @@ static int kfd_parse_subtype_iolink(struct crat_subtype_iolink *iolink,
|
||||
return -ENODEV;
|
||||
/* same everything but the other direction */
|
||||
props2 = kmemdup(props, sizeof(*props2), GFP_KERNEL);
|
||||
if (!props2)
|
||||
return -ENOMEM;
|
||||
|
||||
props2->node_from = id_to;
|
||||
props2->node_to = id_from;
|
||||
props2->kobj = NULL;
|
||||
|
||||
@@ -1279,9 +1279,6 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)
|
||||
adev_to_drm(adev)->mode_config.cursor_width = adev->dm.dc->caps.max_cursor_size;
|
||||
adev_to_drm(adev)->mode_config.cursor_height = adev->dm.dc->caps.max_cursor_size;
|
||||
|
||||
/* Disable vblank IRQs aggressively for power-saving */
|
||||
adev_to_drm(adev)->vblank_disable_immediate = true;
|
||||
|
||||
if (drm_vblank_init(adev_to_drm(adev), adev->dm.display_indexes_num)) {
|
||||
DRM_ERROR(
|
||||
"amdgpu: failed to initialize sw for display support.\n");
|
||||
@@ -3815,6 +3812,9 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Disable vblank IRQs aggressively for power-saving. */
|
||||
adev_to_drm(adev)->vblank_disable_immediate = true;
|
||||
|
||||
/* loops over all connectors on the board */
|
||||
for (i = 0; i < link_cnt; i++) {
|
||||
struct dc_link *link = NULL;
|
||||
@@ -3861,6 +3861,12 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
update_connector_ext_caps(aconnector);
|
||||
if (amdgpu_dc_feature_mask & DC_PSR_MASK)
|
||||
amdgpu_dm_set_psr_caps(link);
|
||||
|
||||
/* TODO: Fix vblank control helpers to delay PSR entry to allow this when
|
||||
* PSR is also supported.
|
||||
*/
|
||||
if (link->psr_settings.psr_feature_enabled)
|
||||
adev_to_drm(adev)->vblank_disable_immediate = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -582,32 +582,32 @@ static struct wm_table lpddr5_wm_table = {
|
||||
.wm_inst = WM_A,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.65333,
|
||||
.sr_exit_time_us = 5.32,
|
||||
.sr_enter_plus_exit_time_us = 6.38,
|
||||
.sr_exit_time_us = 13.5,
|
||||
.sr_enter_plus_exit_time_us = 16.5,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_B,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.65333,
|
||||
.sr_exit_time_us = 9.82,
|
||||
.sr_enter_plus_exit_time_us = 11.196,
|
||||
.sr_exit_time_us = 13.5,
|
||||
.sr_enter_plus_exit_time_us = 16.5,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_C,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.65333,
|
||||
.sr_exit_time_us = 9.89,
|
||||
.sr_enter_plus_exit_time_us = 11.24,
|
||||
.sr_exit_time_us = 13.5,
|
||||
.sr_enter_plus_exit_time_us = 16.5,
|
||||
.valid = true,
|
||||
},
|
||||
{
|
||||
.wm_inst = WM_D,
|
||||
.wm_type = WM_TYPE_PSTATE_CHG,
|
||||
.pstate_latency_us = 11.65333,
|
||||
.sr_exit_time_us = 9.748,
|
||||
.sr_enter_plus_exit_time_us = 11.102,
|
||||
.sr_exit_time_us = 13.5,
|
||||
.sr_enter_plus_exit_time_us = 16.5,
|
||||
.valid = true,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -3650,7 +3650,9 @@ bool dp_retrieve_lttpr_cap(struct dc_link *link)
|
||||
lttpr_dpcd_data,
|
||||
sizeof(lttpr_dpcd_data));
|
||||
if (status != DC_OK) {
|
||||
dm_error("%s: Read LTTPR caps data failed.\n", __func__);
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
DC_LOG_DP2("%s: Read LTTPR caps data failed.\n", __func__);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1799,9 +1799,6 @@ enum dc_status dc_remove_stream_from_ctx(
|
||||
dc->res_pool,
|
||||
del_pipe->stream_res.stream_enc,
|
||||
false);
|
||||
/* Release link encoder from stream in new dc_state. */
|
||||
if (dc->res_pool->funcs->link_enc_unassign)
|
||||
dc->res_pool->funcs->link_enc_unassign(new_ctx, del_pipe->stream);
|
||||
|
||||
if (del_pipe->stream_res.audio)
|
||||
update_audio_usage(
|
||||
|
||||
@@ -1622,12 +1622,106 @@ static void dcn301_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *b
|
||||
dml_init_instance(&dc->dml, &dcn3_01_soc, &dcn3_01_ip, DML_PROJECT_DCN30);
|
||||
}
|
||||
|
||||
static void calculate_wm_set_for_vlevel(
|
||||
int vlevel,
|
||||
struct wm_range_table_entry *table_entry,
|
||||
struct dcn_watermarks *wm_set,
|
||||
struct display_mode_lib *dml,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt)
|
||||
{
|
||||
double dram_clock_change_latency_cached = dml->soc.dram_clock_change_latency_us;
|
||||
|
||||
ASSERT(vlevel < dml->soc.num_states);
|
||||
/* only pipe 0 is read for voltage and dcf/soc clocks */
|
||||
pipes[0].clks_cfg.voltage = vlevel;
|
||||
pipes[0].clks_cfg.dcfclk_mhz = dml->soc.clock_limits[vlevel].dcfclk_mhz;
|
||||
pipes[0].clks_cfg.socclk_mhz = dml->soc.clock_limits[vlevel].socclk_mhz;
|
||||
|
||||
dml->soc.dram_clock_change_latency_us = table_entry->pstate_latency_us;
|
||||
dml->soc.sr_exit_time_us = table_entry->sr_exit_time_us;
|
||||
dml->soc.sr_enter_plus_exit_time_us = table_entry->sr_enter_plus_exit_time_us;
|
||||
|
||||
wm_set->urgent_ns = get_wm_urgent(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->pte_meta_urgent_ns = get_wm_memory_trip(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(dml, pipes, pipe_cnt) * 1000;
|
||||
wm_set->urgent_latency_ns = get_urgent_latency(dml, pipes, pipe_cnt) * 1000;
|
||||
dml->soc.dram_clock_change_latency_us = dram_clock_change_latency_cached;
|
||||
|
||||
}
|
||||
|
||||
static void dcn301_calculate_wm_and_dlg(
|
||||
struct dc *dc, struct dc_state *context,
|
||||
display_e2e_pipe_params_st *pipes,
|
||||
int pipe_cnt,
|
||||
int vlevel_req)
|
||||
{
|
||||
int i, pipe_idx;
|
||||
int vlevel, vlevel_max;
|
||||
struct wm_range_table_entry *table_entry;
|
||||
struct clk_bw_params *bw_params = dc->clk_mgr->bw_params;
|
||||
|
||||
ASSERT(bw_params);
|
||||
|
||||
vlevel_max = bw_params->clk_table.num_entries - 1;
|
||||
|
||||
/* WM Set D */
|
||||
table_entry = &bw_params->wm_table.entries[WM_D];
|
||||
if (table_entry->wm_type == WM_TYPE_RETRAINING)
|
||||
vlevel = 0;
|
||||
else
|
||||
vlevel = vlevel_max;
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.d,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
/* WM Set C */
|
||||
table_entry = &bw_params->wm_table.entries[WM_C];
|
||||
vlevel = min(max(vlevel_req, 2), vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.c,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
/* WM Set B */
|
||||
table_entry = &bw_params->wm_table.entries[WM_B];
|
||||
vlevel = min(max(vlevel_req, 1), vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.b,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
|
||||
/* WM Set A */
|
||||
table_entry = &bw_params->wm_table.entries[WM_A];
|
||||
vlevel = min(vlevel_req, vlevel_max);
|
||||
calculate_wm_set_for_vlevel(vlevel, table_entry, &context->bw_ctx.bw.dcn.watermarks.a,
|
||||
&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
|
||||
for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) {
|
||||
if (!context->res_ctx.pipe_ctx[i].stream)
|
||||
continue;
|
||||
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt);
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx);
|
||||
|
||||
if (dc->config.forced_clocks) {
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz;
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz;
|
||||
}
|
||||
if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000)
|
||||
pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0;
|
||||
if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000)
|
||||
pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0;
|
||||
|
||||
pipe_idx++;
|
||||
}
|
||||
|
||||
dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel);
|
||||
}
|
||||
|
||||
static struct resource_funcs dcn301_res_pool_funcs = {
|
||||
.destroy = dcn301_destroy_resource_pool,
|
||||
.link_enc_create = dcn301_link_encoder_create,
|
||||
.panel_cntl_create = dcn301_panel_cntl_create,
|
||||
.validate_bandwidth = dcn30_validate_bandwidth,
|
||||
.calculate_wm_and_dlg = dcn30_calculate_wm_and_dlg,
|
||||
.calculate_wm_and_dlg = dcn301_calculate_wm_and_dlg,
|
||||
.update_soc_for_wm_a = dcn30_update_soc_for_wm_a,
|
||||
.populate_dml_pipes = dcn30_populate_dml_pipes_from_context,
|
||||
.acquire_idle_pipe_for_layer = dcn20_acquire_idle_pipe_for_layer,
|
||||
|
||||
@@ -70,6 +70,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(fram
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_ccflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_vba.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn2x/dcn2x.o := $(dml_rcflags)
|
||||
@@ -84,6 +85,7 @@ CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_rcfla
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/display_mode_lib.o := $(dml_rcflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dml/dsc/rc_calc_fpu.o := $(dml_rcflags)
|
||||
endif
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/dml1_display_rq_dlg_calc.o := $(dml_ccflags)
|
||||
CFLAGS_$(AMDDALPATH)/dc/dml/display_rq_dlg_helpers.o := $(dml_ccflags)
|
||||
@@ -99,6 +101,7 @@ DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o
|
||||
DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o
|
||||
DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o
|
||||
DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o
|
||||
DML += dsc/rc_calc_fpu.o
|
||||
endif
|
||||
|
||||
AMD_DAL_DML = $(addprefix $(AMDDALPATH)/dc/dml/,$(DML))
|
||||
|
||||
291
drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c
Normal file
291
drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.c
Normal file
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rc_calc_fpu.h"
|
||||
|
||||
#include "qp_tables.h"
|
||||
#include "amdgpu_dm/dc_fpu.h"
|
||||
|
||||
#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min)
|
||||
|
||||
#define MODE_SELECT(val444, val422, val420) \
|
||||
(cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420))
|
||||
|
||||
|
||||
#define TABLE_CASE(mode, bpc, max) case (table_hash(mode, BPC_##bpc, max)): \
|
||||
table = qp_table_##mode##_##bpc##bpc_##max; \
|
||||
table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \
|
||||
break
|
||||
|
||||
static int median3(int a, int b, int c)
|
||||
{
|
||||
if (a > b)
|
||||
swap(a, b);
|
||||
if (b > c)
|
||||
swap(b, c);
|
||||
if (a > b)
|
||||
swap(b, c);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static double dsc_roundf(double num)
|
||||
{
|
||||
if (num < 0.0)
|
||||
num = num - 0.5;
|
||||
else
|
||||
num = num + 0.5;
|
||||
|
||||
return (int)(num);
|
||||
}
|
||||
|
||||
static double dsc_ceil(double num)
|
||||
{
|
||||
double retval = (int)num;
|
||||
|
||||
if (retval != num && num > 0)
|
||||
retval = num + 1;
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc,
|
||||
enum max_min max_min, float bpp)
|
||||
{
|
||||
int mode = MODE_SELECT(444, 422, 420);
|
||||
int sel = table_hash(mode, bpc, max_min);
|
||||
int table_size = 0;
|
||||
int index;
|
||||
const struct qp_entry *table = 0L;
|
||||
|
||||
// alias enum
|
||||
enum { min = DAL_MM_MIN, max = DAL_MM_MAX };
|
||||
switch (sel) {
|
||||
TABLE_CASE(444, 8, max);
|
||||
TABLE_CASE(444, 8, min);
|
||||
TABLE_CASE(444, 10, max);
|
||||
TABLE_CASE(444, 10, min);
|
||||
TABLE_CASE(444, 12, max);
|
||||
TABLE_CASE(444, 12, min);
|
||||
TABLE_CASE(422, 8, max);
|
||||
TABLE_CASE(422, 8, min);
|
||||
TABLE_CASE(422, 10, max);
|
||||
TABLE_CASE(422, 10, min);
|
||||
TABLE_CASE(422, 12, max);
|
||||
TABLE_CASE(422, 12, min);
|
||||
TABLE_CASE(420, 8, max);
|
||||
TABLE_CASE(420, 8, min);
|
||||
TABLE_CASE(420, 10, max);
|
||||
TABLE_CASE(420, 10, min);
|
||||
TABLE_CASE(420, 12, max);
|
||||
TABLE_CASE(420, 12, min);
|
||||
}
|
||||
|
||||
if (table == 0)
|
||||
return;
|
||||
|
||||
index = (bpp - table[0].bpp) * 2;
|
||||
|
||||
/* requested size is bigger than the table */
|
||||
if (index >= table_size) {
|
||||
dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(qps, table[index].qps, sizeof(qp_set));
|
||||
}
|
||||
|
||||
static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
|
||||
{
|
||||
int *p = ofs;
|
||||
|
||||
if (mode == CM_444 || mode == CM_RGB) {
|
||||
*p++ = (bpp <= 6) ? (0) : ((((bpp >= 8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((((bpp >= 8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((((bpp >= 8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else if (mode == CM_422) {
|
||||
*p++ = (bpp <= 8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp - 8) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2.0 / 1))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else {
|
||||
*p++ = (bpp <= 6) ? (2) : ((bpp >= 8) ? (10) : (2 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (8) : (0 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (6) : (0 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((bpp >= 8) ? (4) : (-2 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((bpp >= 8) ? (2) : (-4 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((bpp >= 8) ? (0) : (-6 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-2) : (-8 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-4) : (-8 + dsc_roundf((bpp - 6) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-6) : (-8 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-10) : ((bpp >= 8) ? (-8) : (-10 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 4) ? (-12) : ((bpp >= 5) ? (-10) : (-12 + dsc_roundf((bpp - 4) * (2 / 1.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
}
|
||||
}
|
||||
|
||||
void _do_calc_rc_params(struct rc_params *rc,
|
||||
enum colour_mode cm,
|
||||
enum bits_per_comp bpc,
|
||||
u16 drm_bpp,
|
||||
bool is_navite_422_or_420,
|
||||
int slice_width,
|
||||
int slice_height,
|
||||
int minor_version)
|
||||
{
|
||||
float bpp;
|
||||
float bpp_group;
|
||||
float initial_xmit_delay_factor;
|
||||
int padding_pixels;
|
||||
int i;
|
||||
|
||||
dc_assert_fp_enabled();
|
||||
|
||||
bpp = ((float)drm_bpp / 16.0);
|
||||
/* in native_422 or native_420 modes, the bits_per_pixel is double the
|
||||
* target bpp (the latter is what calc_rc_params expects)
|
||||
*/
|
||||
if (is_navite_422_or_420)
|
||||
bpp /= 2.0;
|
||||
|
||||
rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
|
||||
bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0);
|
||||
|
||||
switch (cm) {
|
||||
case CM_420:
|
||||
rc->initial_fullness_offset = (bpp >= 6) ? (2048) : ((bpp <= 4) ? (6144) : ((((bpp > 4) && (bpp <= 5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp - 5) * (3584)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
break;
|
||||
case CM_422:
|
||||
rc->initial_fullness_offset = (bpp >= 8) ? (2048) : ((bpp <= 7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
case CM_444:
|
||||
case CM_RGB:
|
||||
rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <= 8) ? (6144) : ((((bpp > 8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0;
|
||||
rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor);
|
||||
|
||||
if (cm == CM_422 || cm == CM_420)
|
||||
slice_width /= 2;
|
||||
|
||||
padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0;
|
||||
if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) {
|
||||
if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1)
|
||||
rc->initial_xmit_delay++;
|
||||
}
|
||||
|
||||
rc->flatness_min_qp = ((bpc == BPC_8) ? (3) : ((bpc == BPC_10) ? (7) : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_max_qp = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_det_thresh = 2 << (bpc - 8);
|
||||
|
||||
get_qp_set(rc->qp_min, cm, bpc, DAL_MM_MIN, bpp);
|
||||
get_qp_set(rc->qp_max, cm, bpc, DAL_MM_MAX, bpp);
|
||||
if (cm == CM_444 && minor_version == 1) {
|
||||
for (i = 0; i < QP_SET_SIZE; ++i) {
|
||||
rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0;
|
||||
rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0;
|
||||
}
|
||||
}
|
||||
get_ofs_set(rc->ofs, cm, bpp);
|
||||
|
||||
/* fixed parameters */
|
||||
rc->rc_model_size = 8192;
|
||||
rc->rc_edge_factor = 6;
|
||||
rc->rc_tgt_offset_hi = 3;
|
||||
rc->rc_tgt_offset_lo = 3;
|
||||
|
||||
rc->rc_buf_thresh[0] = 896;
|
||||
rc->rc_buf_thresh[1] = 1792;
|
||||
rc->rc_buf_thresh[2] = 2688;
|
||||
rc->rc_buf_thresh[3] = 3584;
|
||||
rc->rc_buf_thresh[4] = 4480;
|
||||
rc->rc_buf_thresh[5] = 5376;
|
||||
rc->rc_buf_thresh[6] = 6272;
|
||||
rc->rc_buf_thresh[7] = 6720;
|
||||
rc->rc_buf_thresh[8] = 7168;
|
||||
rc->rc_buf_thresh[9] = 7616;
|
||||
rc->rc_buf_thresh[10] = 7744;
|
||||
rc->rc_buf_thresh[11] = 7872;
|
||||
rc->rc_buf_thresh[12] = 8000;
|
||||
rc->rc_buf_thresh[13] = 8064;
|
||||
}
|
||||
|
||||
u32 _do_bytes_per_pixel_calc(int slice_width,
|
||||
u16 drm_bpp,
|
||||
bool is_navite_422_or_420)
|
||||
{
|
||||
float bpp;
|
||||
u32 bytes_per_pixel;
|
||||
double d_bytes_per_pixel;
|
||||
|
||||
dc_assert_fp_enabled();
|
||||
|
||||
bpp = ((float)drm_bpp / 16.0);
|
||||
d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
|
||||
// TODO: Make sure the formula for calculating this is precise (ceiling
|
||||
// vs. floor, and at what point they should be applied)
|
||||
if (is_navite_422_or_420)
|
||||
d_bytes_per_pixel /= 2;
|
||||
|
||||
bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000);
|
||||
|
||||
return bytes_per_pixel;
|
||||
}
|
||||
94
drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h
Normal file
94
drivers/gpu/drm/amd/display/dc/dml/dsc/rc_calc_fpu.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2021 Advanced Micro Devices, Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __RC_CALC_FPU_H__
|
||||
#define __RC_CALC_FPU_H__
|
||||
|
||||
#include "os_types.h"
|
||||
#include <drm/drm_dsc.h>
|
||||
|
||||
#define QP_SET_SIZE 15
|
||||
|
||||
typedef int qp_set[QP_SET_SIZE];
|
||||
|
||||
struct rc_params {
|
||||
int rc_quant_incr_limit0;
|
||||
int rc_quant_incr_limit1;
|
||||
int initial_fullness_offset;
|
||||
int initial_xmit_delay;
|
||||
int first_line_bpg_offset;
|
||||
int second_line_bpg_offset;
|
||||
int flatness_min_qp;
|
||||
int flatness_max_qp;
|
||||
int flatness_det_thresh;
|
||||
qp_set qp_min;
|
||||
qp_set qp_max;
|
||||
qp_set ofs;
|
||||
int rc_model_size;
|
||||
int rc_edge_factor;
|
||||
int rc_tgt_offset_hi;
|
||||
int rc_tgt_offset_lo;
|
||||
int rc_buf_thresh[QP_SET_SIZE - 1];
|
||||
};
|
||||
|
||||
enum colour_mode {
|
||||
CM_RGB, /* 444 RGB */
|
||||
CM_444, /* 444 YUV or simple 422 */
|
||||
CM_422, /* native 422 */
|
||||
CM_420 /* native 420 */
|
||||
};
|
||||
|
||||
enum bits_per_comp {
|
||||
BPC_8 = 8,
|
||||
BPC_10 = 10,
|
||||
BPC_12 = 12
|
||||
};
|
||||
|
||||
enum max_min {
|
||||
DAL_MM_MIN = 0,
|
||||
DAL_MM_MAX = 1
|
||||
};
|
||||
|
||||
struct qp_entry {
|
||||
float bpp;
|
||||
const qp_set qps;
|
||||
};
|
||||
|
||||
typedef struct qp_entry qp_table[];
|
||||
|
||||
u32 _do_bytes_per_pixel_calc(int slice_width,
|
||||
u16 drm_bpp,
|
||||
bool is_navite_422_or_420);
|
||||
|
||||
void _do_calc_rc_params(struct rc_params *rc,
|
||||
enum colour_mode cm,
|
||||
enum bits_per_comp bpc,
|
||||
u16 drm_bpp,
|
||||
bool is_navite_422_or_420,
|
||||
int slice_width,
|
||||
int slice_height,
|
||||
int minor_version);
|
||||
|
||||
#endif
|
||||
@@ -1,35 +1,6 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
# Makefile for the 'dsc' sub-component of DAL.
|
||||
|
||||
ifdef CONFIG_X86
|
||||
dsc_ccflags := -mhard-float -msse
|
||||
endif
|
||||
|
||||
ifdef CONFIG_PPC64
|
||||
dsc_ccflags := -mhard-float -maltivec
|
||||
endif
|
||||
|
||||
ifdef CONFIG_CC_IS_GCC
|
||||
ifeq ($(call cc-ifversion, -lt, 0701, y), y)
|
||||
IS_OLD_GCC = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef CONFIG_X86
|
||||
ifdef IS_OLD_GCC
|
||||
# Stack alignment mismatch, proceed with caution.
|
||||
# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3
|
||||
# (8B stack alignment).
|
||||
dsc_ccflags += -mpreferred-stack-boundary=4
|
||||
else
|
||||
dsc_ccflags += -msse2
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_ccflags)
|
||||
CFLAGS_REMOVE_$(AMDDALPATH)/dc/dsc/rc_calc.o := $(dsc_rcflags)
|
||||
|
||||
DSC = dc_dsc.o rc_calc.o rc_calc_dpi.o
|
||||
|
||||
AMD_DAL_DSC = $(addprefix $(AMDDALPATH)/dc/dsc/,$(DSC))
|
||||
|
||||
@@ -23,266 +23,7 @@
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
#include <drm/drm_dsc.h>
|
||||
|
||||
#include "os_types.h"
|
||||
#include "rc_calc.h"
|
||||
#include "qp_tables.h"
|
||||
|
||||
#define table_hash(mode, bpc, max_min) ((mode << 16) | (bpc << 8) | max_min)
|
||||
|
||||
#define MODE_SELECT(val444, val422, val420) \
|
||||
(cm == CM_444 || cm == CM_RGB) ? (val444) : (cm == CM_422 ? (val422) : (val420))
|
||||
|
||||
|
||||
#define TABLE_CASE(mode, bpc, max) case (table_hash(mode, BPC_##bpc, max)): \
|
||||
table = qp_table_##mode##_##bpc##bpc_##max; \
|
||||
table_size = sizeof(qp_table_##mode##_##bpc##bpc_##max)/sizeof(*qp_table_##mode##_##bpc##bpc_##max); \
|
||||
break
|
||||
|
||||
|
||||
static void get_qp_set(qp_set qps, enum colour_mode cm, enum bits_per_comp bpc,
|
||||
enum max_min max_min, float bpp)
|
||||
{
|
||||
int mode = MODE_SELECT(444, 422, 420);
|
||||
int sel = table_hash(mode, bpc, max_min);
|
||||
int table_size = 0;
|
||||
int index;
|
||||
const struct qp_entry *table = 0L;
|
||||
|
||||
// alias enum
|
||||
enum { min = DAL_MM_MIN, max = DAL_MM_MAX };
|
||||
switch (sel) {
|
||||
TABLE_CASE(444, 8, max);
|
||||
TABLE_CASE(444, 8, min);
|
||||
TABLE_CASE(444, 10, max);
|
||||
TABLE_CASE(444, 10, min);
|
||||
TABLE_CASE(444, 12, max);
|
||||
TABLE_CASE(444, 12, min);
|
||||
TABLE_CASE(422, 8, max);
|
||||
TABLE_CASE(422, 8, min);
|
||||
TABLE_CASE(422, 10, max);
|
||||
TABLE_CASE(422, 10, min);
|
||||
TABLE_CASE(422, 12, max);
|
||||
TABLE_CASE(422, 12, min);
|
||||
TABLE_CASE(420, 8, max);
|
||||
TABLE_CASE(420, 8, min);
|
||||
TABLE_CASE(420, 10, max);
|
||||
TABLE_CASE(420, 10, min);
|
||||
TABLE_CASE(420, 12, max);
|
||||
TABLE_CASE(420, 12, min);
|
||||
}
|
||||
|
||||
if (table == 0)
|
||||
return;
|
||||
|
||||
index = (bpp - table[0].bpp) * 2;
|
||||
|
||||
/* requested size is bigger than the table */
|
||||
if (index >= table_size) {
|
||||
dm_error("ERROR: Requested rc_calc to find a bpp entry that exceeds the table size\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(qps, table[index].qps, sizeof(qp_set));
|
||||
}
|
||||
|
||||
static double dsc_roundf(double num)
|
||||
{
|
||||
if (num < 0.0)
|
||||
num = num - 0.5;
|
||||
else
|
||||
num = num + 0.5;
|
||||
|
||||
return (int)(num);
|
||||
}
|
||||
|
||||
static double dsc_ceil(double num)
|
||||
{
|
||||
double retval = (int)num;
|
||||
|
||||
if (retval != num && num > 0)
|
||||
retval = num + 1;
|
||||
|
||||
return (int)retval;
|
||||
}
|
||||
|
||||
static void get_ofs_set(qp_set ofs, enum colour_mode mode, float bpp)
|
||||
{
|
||||
int *p = ofs;
|
||||
|
||||
if (mode == CM_444 || mode == CM_RGB) {
|
||||
*p++ = (bpp <= 6) ? (0) : ((((bpp >= 8) && (bpp <= 12))) ? (2) : ((bpp >= 15) ? (10) : ((((bpp > 6) && (bpp < 8))) ? (0 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (2 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (8) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (8 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((((bpp >= 8) && (bpp <= 12))) ? (0) : ((bpp >= 15) ? (6) : ((((bpp > 6) && (bpp < 8))) ? (-2 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (0 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((((bpp >= 8) && (bpp <= 12))) ? (-2) : ((bpp >= 15) ? (4) : ((((bpp > 6) && (bpp < 8))) ? (-4 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-2 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((((bpp >= 8) && (bpp <= 12))) ? (-4) : ((bpp >= 15) ? (2) : ((((bpp > 6) && (bpp < 8))) ? (-6 + dsc_roundf((bpp - 6) * (2 / 2.0))) : (-4 + dsc_roundf((bpp - 12) * (6 / 3.0))))));
|
||||
*p++ = (bpp <= 12) ? (-6) : ((bpp >= 15) ? (0) : (-6 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-2) : (-8 + dsc_roundf((bpp - 12) * (6 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-4) : (-8 + dsc_roundf((bpp - 12) * (4 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-8) : ((bpp >= 15) ? (-6) : (-8 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = (bpp <= 12) ? (-10) : ((bpp >= 15) ? (-8) : (-10 + dsc_roundf((bpp - 12) * (2 / 3.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 8) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else if (mode == CM_422) {
|
||||
*p++ = (bpp <= 8) ? (2) : ((bpp >= 10) ? (10) : (2 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (8) : (0 + dsc_roundf((bpp - 8) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (0) : ((bpp >= 10) ? (6) : (0 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-2) : ((bpp >= 10) ? (4) : (-2 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-4) : ((bpp >= 10) ? (2) : (-4 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-6) : ((bpp >= 10) ? (0) : (-6 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-2) : (-8 + dsc_roundf((bpp - 8) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-4) : (-8 + dsc_roundf((bpp - 8) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-8) : ((bpp >= 10) ? (-6) : (-8 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 8) ? (-10) : ((bpp >= 10) ? (-8) : (-10 + dsc_roundf((bpp - 8) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 6) ? (-12) : ((bpp >= 7) ? (-10) : (-12 + dsc_roundf((bpp - 6) * (2.0 / 1))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
} else {
|
||||
*p++ = (bpp <= 6) ? (2) : ((bpp >= 8) ? (10) : (2 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (8) : (0 + dsc_roundf((bpp - 6) * (8 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (0) : ((bpp >= 8) ? (6) : (0 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-2) : ((bpp >= 8) ? (4) : (-2 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-4) : ((bpp >= 8) ? (2) : (-4 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-6) : ((bpp >= 8) ? (0) : (-6 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-2) : (-8 + dsc_roundf((bpp - 6) * (6 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-4) : (-8 + dsc_roundf((bpp - 6) * (4 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-8) : ((bpp >= 8) ? (-6) : (-8 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = (bpp <= 6) ? (-10) : ((bpp >= 8) ? (-8) : (-10 + dsc_roundf((bpp - 6) * (2 / 2.0))));
|
||||
*p++ = -10;
|
||||
*p++ = (bpp <= 4) ? (-12) : ((bpp >= 5) ? (-10) : (-12 + dsc_roundf((bpp - 4) * (2 / 1.0))));
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
*p++ = -12;
|
||||
}
|
||||
}
|
||||
|
||||
static int median3(int a, int b, int c)
|
||||
{
|
||||
if (a > b)
|
||||
swap(a, b);
|
||||
if (b > c)
|
||||
swap(b, c);
|
||||
if (a > b)
|
||||
swap(b, c);
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
static void _do_calc_rc_params(struct rc_params *rc, enum colour_mode cm,
|
||||
enum bits_per_comp bpc, u16 drm_bpp,
|
||||
bool is_navite_422_or_420,
|
||||
int slice_width, int slice_height,
|
||||
int minor_version)
|
||||
{
|
||||
float bpp;
|
||||
float bpp_group;
|
||||
float initial_xmit_delay_factor;
|
||||
int padding_pixels;
|
||||
int i;
|
||||
|
||||
bpp = ((float)drm_bpp / 16.0);
|
||||
/* in native_422 or native_420 modes, the bits_per_pixel is double the
|
||||
* target bpp (the latter is what calc_rc_params expects)
|
||||
*/
|
||||
if (is_navite_422_or_420)
|
||||
bpp /= 2.0;
|
||||
|
||||
rc->rc_quant_incr_limit0 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->rc_quant_incr_limit1 = ((bpc == BPC_8) ? 11 : (bpc == BPC_10 ? 15 : 19)) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
|
||||
bpp_group = MODE_SELECT(bpp, bpp * 2.0, bpp * 2.0);
|
||||
|
||||
switch (cm) {
|
||||
case CM_420:
|
||||
rc->initial_fullness_offset = (bpp >= 6) ? (2048) : ((bpp <= 4) ? (6144) : ((((bpp > 4) && (bpp <= 5))) ? (6144 - dsc_roundf((bpp - 4) * (512))) : (5632 - dsc_roundf((bpp - 5) * (3584)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = median3(0, 12, (int)((3 * bpc * 3) - (3 * bpp_group)));
|
||||
break;
|
||||
case CM_422:
|
||||
rc->initial_fullness_offset = (bpp >= 8) ? (2048) : ((bpp <= 7) ? (5632) : (5632 - dsc_roundf((bpp - 7) * (3584))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)((3 * bpc * 4) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
case CM_444:
|
||||
case CM_RGB:
|
||||
rc->initial_fullness_offset = (bpp >= 12) ? (2048) : ((bpp <= 8) ? (6144) : ((((bpp > 8) && (bpp <= 10))) ? (6144 - dsc_roundf((bpp - 8) * (512 / 2))) : (5632 - dsc_roundf((bpp - 10) * (3584 / 2)))));
|
||||
rc->first_line_bpg_offset = median3(0, (12 + (int) (0.09 * min(34, slice_height - 8))), (int)(((3 * bpc + (cm == CM_444 ? 0 : 2)) * 3) - (3 * bpp_group)));
|
||||
rc->second_line_bpg_offset = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
initial_xmit_delay_factor = (cm == CM_444 || cm == CM_RGB) ? 1.0 : 2.0;
|
||||
rc->initial_xmit_delay = dsc_roundf(8192.0/2.0/bpp/initial_xmit_delay_factor);
|
||||
|
||||
if (cm == CM_422 || cm == CM_420)
|
||||
slice_width /= 2;
|
||||
|
||||
padding_pixels = ((slice_width % 3) != 0) ? (3 - (slice_width % 3)) * (rc->initial_xmit_delay / slice_width) : 0;
|
||||
if (3 * bpp_group >= (((rc->initial_xmit_delay + 2) / 3) * (3 + (cm == CM_422)))) {
|
||||
if ((rc->initial_xmit_delay + padding_pixels) % 3 == 1)
|
||||
rc->initial_xmit_delay++;
|
||||
}
|
||||
|
||||
rc->flatness_min_qp = ((bpc == BPC_8) ? (3) : ((bpc == BPC_10) ? (7) : (11))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_max_qp = ((bpc == BPC_8) ? (12) : ((bpc == BPC_10) ? (16) : (20))) - ((minor_version == 1 && cm == CM_444) ? 1 : 0);
|
||||
rc->flatness_det_thresh = 2 << (bpc - 8);
|
||||
|
||||
get_qp_set(rc->qp_min, cm, bpc, DAL_MM_MIN, bpp);
|
||||
get_qp_set(rc->qp_max, cm, bpc, DAL_MM_MAX, bpp);
|
||||
if (cm == CM_444 && minor_version == 1) {
|
||||
for (i = 0; i < QP_SET_SIZE; ++i) {
|
||||
rc->qp_min[i] = rc->qp_min[i] > 0 ? rc->qp_min[i] - 1 : 0;
|
||||
rc->qp_max[i] = rc->qp_max[i] > 0 ? rc->qp_max[i] - 1 : 0;
|
||||
}
|
||||
}
|
||||
get_ofs_set(rc->ofs, cm, bpp);
|
||||
|
||||
/* fixed parameters */
|
||||
rc->rc_model_size = 8192;
|
||||
rc->rc_edge_factor = 6;
|
||||
rc->rc_tgt_offset_hi = 3;
|
||||
rc->rc_tgt_offset_lo = 3;
|
||||
|
||||
rc->rc_buf_thresh[0] = 896;
|
||||
rc->rc_buf_thresh[1] = 1792;
|
||||
rc->rc_buf_thresh[2] = 2688;
|
||||
rc->rc_buf_thresh[3] = 3584;
|
||||
rc->rc_buf_thresh[4] = 4480;
|
||||
rc->rc_buf_thresh[5] = 5376;
|
||||
rc->rc_buf_thresh[6] = 6272;
|
||||
rc->rc_buf_thresh[7] = 6720;
|
||||
rc->rc_buf_thresh[8] = 7168;
|
||||
rc->rc_buf_thresh[9] = 7616;
|
||||
rc->rc_buf_thresh[10] = 7744;
|
||||
rc->rc_buf_thresh[11] = 7872;
|
||||
rc->rc_buf_thresh[12] = 8000;
|
||||
rc->rc_buf_thresh[13] = 8064;
|
||||
}
|
||||
|
||||
static u32 _do_bytes_per_pixel_calc(int slice_width, u16 drm_bpp,
|
||||
bool is_navite_422_or_420)
|
||||
{
|
||||
float bpp;
|
||||
u32 bytes_per_pixel;
|
||||
double d_bytes_per_pixel;
|
||||
|
||||
bpp = ((float)drm_bpp / 16.0);
|
||||
d_bytes_per_pixel = dsc_ceil(bpp * slice_width / 8.0) / slice_width;
|
||||
// TODO: Make sure the formula for calculating this is precise (ceiling
|
||||
// vs. floor, and at what point they should be applied)
|
||||
if (is_navite_422_or_420)
|
||||
d_bytes_per_pixel /= 2;
|
||||
|
||||
bytes_per_pixel = (u32)dsc_ceil(d_bytes_per_pixel * 0x10000000);
|
||||
|
||||
return bytes_per_pixel;
|
||||
}
|
||||
|
||||
/**
|
||||
* calc_rc_params - reads the user's cmdline mode
|
||||
|
||||
@@ -27,55 +27,7 @@
|
||||
#ifndef __RC_CALC_H__
|
||||
#define __RC_CALC_H__
|
||||
|
||||
|
||||
#define QP_SET_SIZE 15
|
||||
|
||||
typedef int qp_set[QP_SET_SIZE];
|
||||
|
||||
struct rc_params {
|
||||
int rc_quant_incr_limit0;
|
||||
int rc_quant_incr_limit1;
|
||||
int initial_fullness_offset;
|
||||
int initial_xmit_delay;
|
||||
int first_line_bpg_offset;
|
||||
int second_line_bpg_offset;
|
||||
int flatness_min_qp;
|
||||
int flatness_max_qp;
|
||||
int flatness_det_thresh;
|
||||
qp_set qp_min;
|
||||
qp_set qp_max;
|
||||
qp_set ofs;
|
||||
int rc_model_size;
|
||||
int rc_edge_factor;
|
||||
int rc_tgt_offset_hi;
|
||||
int rc_tgt_offset_lo;
|
||||
int rc_buf_thresh[QP_SET_SIZE - 1];
|
||||
};
|
||||
|
||||
enum colour_mode {
|
||||
CM_RGB, /* 444 RGB */
|
||||
CM_444, /* 444 YUV or simple 422 */
|
||||
CM_422, /* native 422 */
|
||||
CM_420 /* native 420 */
|
||||
};
|
||||
|
||||
enum bits_per_comp {
|
||||
BPC_8 = 8,
|
||||
BPC_10 = 10,
|
||||
BPC_12 = 12
|
||||
};
|
||||
|
||||
enum max_min {
|
||||
DAL_MM_MIN = 0,
|
||||
DAL_MM_MAX = 1
|
||||
};
|
||||
|
||||
struct qp_entry {
|
||||
float bpp;
|
||||
const qp_set qps;
|
||||
};
|
||||
|
||||
typedef struct qp_entry qp_table[];
|
||||
#include "dml/dsc/rc_calc_fpu.h"
|
||||
|
||||
void calc_rc_params(struct rc_params *rc, const struct drm_dsc_config *pps);
|
||||
u32 calc_dsc_bytes_per_pixel(const struct drm_dsc_config *pps);
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
#include "os_types.h"
|
||||
#include <drm/drm_dsc.h>
|
||||
#include "dscc_types.h"
|
||||
#include "rc_calc.h"
|
||||
|
||||
@@ -72,6 +72,9 @@
|
||||
#define DC_LOG_DSC(...) DRM_DEBUG_KMS(__VA_ARGS__)
|
||||
#define DC_LOG_SMU(...) pr_debug("[SMU_MSG]:"__VA_ARGS__)
|
||||
#define DC_LOG_DWB(...) DRM_DEBUG_KMS(__VA_ARGS__)
|
||||
#if defined(CONFIG_DRM_AMD_DC_DCN)
|
||||
#define DC_LOG_DP2(...) DRM_DEBUG_KMS(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
struct dal_logger;
|
||||
|
||||
|
||||
@@ -1308,21 +1308,37 @@ static int sienna_cichlid_populate_umd_state_clk(struct smu_context *smu)
|
||||
&dpm_context->dpm_tables.soc_table;
|
||||
struct smu_umd_pstate_table *pstate_table =
|
||||
&smu->pstate_table;
|
||||
struct amdgpu_device *adev = smu->adev;
|
||||
|
||||
pstate_table->gfxclk_pstate.min = gfx_table->min;
|
||||
pstate_table->gfxclk_pstate.peak = gfx_table->max;
|
||||
if (gfx_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK)
|
||||
pstate_table->gfxclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK;
|
||||
|
||||
pstate_table->uclk_pstate.min = mem_table->min;
|
||||
pstate_table->uclk_pstate.peak = mem_table->max;
|
||||
if (mem_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK)
|
||||
pstate_table->uclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK;
|
||||
|
||||
pstate_table->socclk_pstate.min = soc_table->min;
|
||||
pstate_table->socclk_pstate.peak = soc_table->max;
|
||||
if (soc_table->max >= SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK)
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
case CHIP_NAVY_FLOUNDER:
|
||||
pstate_table->gfxclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_GFXCLK;
|
||||
pstate_table->uclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK;
|
||||
pstate_table->socclk_pstate.standard = SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK;
|
||||
break;
|
||||
case CHIP_DIMGREY_CAVEFISH:
|
||||
pstate_table->gfxclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_GFXCLK;
|
||||
pstate_table->uclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_MEMCLK;
|
||||
pstate_table->socclk_pstate.standard = DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_SOCCLK;
|
||||
break;
|
||||
case CHIP_BEIGE_GOBY:
|
||||
pstate_table->gfxclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_GFXCLK;
|
||||
pstate_table->uclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_MEMCLK;
|
||||
pstate_table->socclk_pstate.standard = BEIGE_GOBY_UMD_PSTATE_PROFILING_SOCCLK;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -33,6 +33,14 @@ typedef enum {
|
||||
#define SIENNA_CICHLID_UMD_PSTATE_PROFILING_SOCCLK 960
|
||||
#define SIENNA_CICHLID_UMD_PSTATE_PROFILING_MEMCLK 1000
|
||||
|
||||
#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_GFXCLK 1950
|
||||
#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_SOCCLK 960
|
||||
#define DIMGREY_CAVEFISH_UMD_PSTATE_PROFILING_MEMCLK 676
|
||||
|
||||
#define BEIGE_GOBY_UMD_PSTATE_PROFILING_GFXCLK 2200
|
||||
#define BEIGE_GOBY_UMD_PSTATE_PROFILING_SOCCLK 960
|
||||
#define BEIGE_GOBY_UMD_PSTATE_PROFILING_MEMCLK 1000
|
||||
|
||||
extern void sienna_cichlid_set_ppt_funcs(struct smu_context *smu);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1473,6 +1473,7 @@ static inline void ti_sn_gpio_unregister(void) {}
|
||||
|
||||
static void ti_sn65dsi86_runtime_disable(void *data)
|
||||
{
|
||||
pm_runtime_dont_use_autosuspend(data);
|
||||
pm_runtime_disable(data);
|
||||
}
|
||||
|
||||
@@ -1532,11 +1533,11 @@ static int ti_sn65dsi86_probe(struct i2c_client *client,
|
||||
"failed to get reference clock\n");
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_set_autosuspend_delay(pdata->dev, 500);
|
||||
pm_runtime_use_autosuspend(pdata->dev);
|
||||
ret = devm_add_action_or_reset(dev, ti_sn65dsi86_runtime_disable, dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
pm_runtime_set_autosuspend_delay(pdata->dev, 500);
|
||||
pm_runtime_use_autosuspend(pdata->dev);
|
||||
|
||||
ti_sn65dsi86_debugfs_init(pdata);
|
||||
|
||||
|
||||
@@ -1001,7 +1001,7 @@ crtc_needs_disable(struct drm_crtc_state *old_state,
|
||||
* it's in self refresh mode and needs to be fully disabled.
|
||||
*/
|
||||
return old_state->active ||
|
||||
(old_state->self_refresh_active && !new_state->enable) ||
|
||||
(old_state->self_refresh_active && !new_state->active) ||
|
||||
new_state->self_refresh_active;
|
||||
}
|
||||
|
||||
|
||||
@@ -211,6 +211,8 @@ i915-y += \
|
||||
display/intel_dpio_phy.o \
|
||||
display/intel_dpll.o \
|
||||
display/intel_dpll_mgr.o \
|
||||
display/intel_dpt.o \
|
||||
display/intel_drrs.o \
|
||||
display/intel_dsb.o \
|
||||
display/intel_fb.o \
|
||||
display/intel_fbc.o \
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "intel_dp_link_training.h"
|
||||
#include "intel_dp_mst.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_dsi.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
|
||||
@@ -84,6 +84,7 @@
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dmc.h"
|
||||
#include "intel_dp_link_training.h"
|
||||
#include "intel_dpt.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_fdi.h"
|
||||
#include "intel_fbdev.h"
|
||||
@@ -126,182 +127,6 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state);
|
||||
static void intel_modeset_setup_hw_state(struct drm_device *dev,
|
||||
struct drm_modeset_acquire_ctx *ctx);
|
||||
|
||||
struct i915_dpt {
|
||||
struct i915_address_space vm;
|
||||
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_vma *vma;
|
||||
void __iomem *iomem;
|
||||
};
|
||||
|
||||
#define i915_is_dpt(vm) ((vm)->is_dpt)
|
||||
|
||||
static inline struct i915_dpt *
|
||||
i915_vm_to_dpt(struct i915_address_space *vm)
|
||||
{
|
||||
BUILD_BUG_ON(offsetof(struct i915_dpt, vm));
|
||||
GEM_BUG_ON(!i915_is_dpt(vm));
|
||||
return container_of(vm, struct i915_dpt, vm);
|
||||
}
|
||||
|
||||
#define dpt_total_entries(dpt) ((dpt)->vm.total >> PAGE_SHIFT)
|
||||
|
||||
static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
|
||||
{
|
||||
writeq(pte, addr);
|
||||
}
|
||||
|
||||
static void dpt_insert_page(struct i915_address_space *vm,
|
||||
dma_addr_t addr,
|
||||
u64 offset,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
gen8_pte_t __iomem *base = dpt->iomem;
|
||||
|
||||
gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE,
|
||||
vm->pte_encode(addr, level, flags));
|
||||
}
|
||||
|
||||
static void dpt_insert_entries(struct i915_address_space *vm,
|
||||
struct i915_vma *vma,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
gen8_pte_t __iomem *base = dpt->iomem;
|
||||
const gen8_pte_t pte_encode = vm->pte_encode(0, level, flags);
|
||||
struct sgt_iter sgt_iter;
|
||||
dma_addr_t addr;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Note that we ignore PTE_READ_ONLY here. The caller must be careful
|
||||
* not to allow the user to override access to a read only page.
|
||||
*/
|
||||
|
||||
i = vma->node.start / I915_GTT_PAGE_SIZE;
|
||||
for_each_sgt_daddr(addr, sgt_iter, vma->pages)
|
||||
gen8_set_pte(&base[i++], pte_encode | addr);
|
||||
}
|
||||
|
||||
static void dpt_clear_range(struct i915_address_space *vm,
|
||||
u64 start, u64 length)
|
||||
{
|
||||
}
|
||||
|
||||
static void dpt_bind_vma(struct i915_address_space *vm,
|
||||
struct i915_vm_pt_stash *stash,
|
||||
struct i915_vma *vma,
|
||||
enum i915_cache_level cache_level,
|
||||
u32 flags)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
u32 pte_flags;
|
||||
|
||||
/* Applicable to VLV (gen8+ do not support RO in the GGTT) */
|
||||
pte_flags = 0;
|
||||
if (vma->vm->has_read_only && i915_gem_object_is_readonly(obj))
|
||||
pte_flags |= PTE_READ_ONLY;
|
||||
if (i915_gem_object_is_lmem(obj))
|
||||
pte_flags |= PTE_LM;
|
||||
|
||||
vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
|
||||
|
||||
vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Without aliasing PPGTT there's no difference between
|
||||
* GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
|
||||
* upgrade to both bound if we bind either to avoid double-binding.
|
||||
*/
|
||||
atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags);
|
||||
}
|
||||
|
||||
static void dpt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma)
|
||||
{
|
||||
vm->clear_range(vm, vma->node.start, vma->size);
|
||||
}
|
||||
|
||||
static void dpt_cleanup(struct i915_address_space *vm)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
|
||||
i915_gem_object_put(dpt->obj);
|
||||
}
|
||||
|
||||
static struct i915_address_space *
|
||||
intel_dpt_create(struct intel_framebuffer *fb)
|
||||
{
|
||||
struct drm_gem_object *obj = &intel_fb_obj(&fb->base)->base;
|
||||
struct drm_i915_private *i915 = to_i915(obj->dev);
|
||||
struct drm_i915_gem_object *dpt_obj;
|
||||
struct i915_address_space *vm;
|
||||
struct i915_dpt *dpt;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
if (intel_fb_needs_pot_stride_remap(fb))
|
||||
size = intel_remapped_info_size(&fb->remapped_view.gtt.remapped);
|
||||
else
|
||||
size = DIV_ROUND_UP_ULL(obj->size, I915_GTT_PAGE_SIZE);
|
||||
|
||||
size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE);
|
||||
|
||||
if (HAS_LMEM(i915))
|
||||
dpt_obj = i915_gem_object_create_lmem(i915, size, 0);
|
||||
else
|
||||
dpt_obj = i915_gem_object_create_stolen(i915, size);
|
||||
if (IS_ERR(dpt_obj))
|
||||
return ERR_CAST(dpt_obj);
|
||||
|
||||
ret = i915_gem_object_set_cache_level(dpt_obj, I915_CACHE_NONE);
|
||||
if (ret) {
|
||||
i915_gem_object_put(dpt_obj);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
dpt = kzalloc(sizeof(*dpt), GFP_KERNEL);
|
||||
if (!dpt) {
|
||||
i915_gem_object_put(dpt_obj);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
vm = &dpt->vm;
|
||||
|
||||
vm->gt = &i915->gt;
|
||||
vm->i915 = i915;
|
||||
vm->dma = i915->drm.dev;
|
||||
vm->total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE;
|
||||
vm->is_dpt = true;
|
||||
|
||||
i915_address_space_init(vm, VM_CLASS_DPT);
|
||||
|
||||
vm->insert_page = dpt_insert_page;
|
||||
vm->clear_range = dpt_clear_range;
|
||||
vm->insert_entries = dpt_insert_entries;
|
||||
vm->cleanup = dpt_cleanup;
|
||||
|
||||
vm->vma_ops.bind_vma = dpt_bind_vma;
|
||||
vm->vma_ops.unbind_vma = dpt_unbind_vma;
|
||||
vm->vma_ops.set_pages = ggtt_set_pages;
|
||||
vm->vma_ops.clear_pages = clear_pages;
|
||||
|
||||
vm->pte_encode = gen8_ggtt_pte_encode;
|
||||
|
||||
dpt->obj = dpt_obj;
|
||||
|
||||
return &dpt->vm;
|
||||
}
|
||||
|
||||
static void intel_dpt_destroy(struct i915_address_space *vm)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
|
||||
i915_vm_close(&dpt->vm);
|
||||
}
|
||||
|
||||
/* returns HPLL frequency in kHz */
|
||||
int vlv_get_hpll_vco(struct drm_i915_private *dev_priv)
|
||||
{
|
||||
@@ -1879,49 +1704,6 @@ static void intel_plane_disable_noatomic(struct intel_crtc *crtc,
|
||||
intel_wait_for_vblank(dev_priv, crtc->pipe);
|
||||
}
|
||||
|
||||
static struct i915_vma *intel_dpt_pin(struct i915_address_space *vm)
|
||||
{
|
||||
struct drm_i915_private *i915 = vm->i915;
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
intel_wakeref_t wakeref;
|
||||
struct i915_vma *vma;
|
||||
void __iomem *iomem;
|
||||
|
||||
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
|
||||
atomic_inc(&i915->gpu_error.pending_fb_pin);
|
||||
|
||||
vma = i915_gem_object_ggtt_pin(dpt->obj, NULL, 0, 4096,
|
||||
HAS_LMEM(i915) ? 0 : PIN_MAPPABLE);
|
||||
if (IS_ERR(vma))
|
||||
goto err;
|
||||
|
||||
iomem = i915_vma_pin_iomap(vma);
|
||||
i915_vma_unpin(vma);
|
||||
if (IS_ERR(iomem)) {
|
||||
vma = iomem;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dpt->vma = vma;
|
||||
dpt->iomem = iomem;
|
||||
|
||||
i915_vma_get(vma);
|
||||
|
||||
err:
|
||||
atomic_dec(&i915->gpu_error.pending_fb_pin);
|
||||
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
|
||||
|
||||
return vma;
|
||||
}
|
||||
|
||||
static void intel_dpt_unpin(struct i915_address_space *vm)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
|
||||
i915_vma_unpin_iomap(dpt->vma);
|
||||
i915_vma_put(dpt->vma);
|
||||
}
|
||||
|
||||
static bool
|
||||
intel_reuse_initial_plane_obj(struct drm_i915_private *i915,
|
||||
const struct intel_initial_plane_config *plane_config,
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dmc.h"
|
||||
#include "intel_dp.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_hdmi.h"
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
#include "intel_dp_mst.h"
|
||||
#include "intel_dpio_phy.h"
|
||||
#include "intel_dpll.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_fifo_underrun.h"
|
||||
#include "intel_hdcp.h"
|
||||
#include "intel_hdmi.h"
|
||||
@@ -1610,46 +1611,6 @@ intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp,
|
||||
intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
int output_bpp, bool constant_n)
|
||||
{
|
||||
struct intel_connector *intel_connector = intel_dp->attached_connector;
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
int pixel_clock;
|
||||
|
||||
if (pipe_config->vrr.enable)
|
||||
return;
|
||||
|
||||
/*
|
||||
* DRRS and PSR can't be enable together, so giving preference to PSR
|
||||
* as it allows more power-savings by complete shutting down display,
|
||||
* so to guarantee this, intel_dp_drrs_compute_config() must be called
|
||||
* after intel_psr_compute_config().
|
||||
*/
|
||||
if (pipe_config->has_psr)
|
||||
return;
|
||||
|
||||
if (!intel_connector->panel.downclock_mode ||
|
||||
dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
|
||||
return;
|
||||
|
||||
pipe_config->has_drrs = true;
|
||||
|
||||
pixel_clock = intel_connector->panel.downclock_mode->clock;
|
||||
if (pipe_config->splitter.enable)
|
||||
pixel_clock /= pipe_config->splitter.link_count;
|
||||
|
||||
intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
|
||||
pipe_config->port_clock, &pipe_config->dp_m2_n2,
|
||||
constant_n, pipe_config->fec_enable);
|
||||
|
||||
/* FIXME: abstract this better */
|
||||
if (pipe_config->splitter.enable)
|
||||
pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count;
|
||||
}
|
||||
|
||||
int
|
||||
intel_dp_compute_config(struct intel_encoder *encoder,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
@@ -4737,432 +4698,6 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect
|
||||
drm_connector_attach_vrr_capable_property(connector);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_dp_set_drrs_state - program registers for RR switch to take effect
|
||||
* @dev_priv: i915 device
|
||||
* @crtc_state: a pointer to the active intel_crtc_state
|
||||
* @refresh_rate: RR to be programmed
|
||||
*
|
||||
* This function gets called when refresh rate (RR) has to be changed from
|
||||
* one frequency to another. Switches can be between high and low RR
|
||||
* supported by the panel or to any other RR based on media playback (in
|
||||
* this case, RR value needs to be passed from user space).
|
||||
*
|
||||
* The caller of this function needs to take a lock on dev_priv->drrs.
|
||||
*/
|
||||
static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
int refresh_rate)
|
||||
{
|
||||
struct intel_dp *intel_dp = dev_priv->drrs.dp;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
|
||||
|
||||
if (refresh_rate <= 0) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Refresh rate should be positive non-zero.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intel_dp == NULL) {
|
||||
drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!crtc) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS: intel_crtc not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
|
||||
drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode) ==
|
||||
refresh_rate)
|
||||
index = DRRS_LOW_RR;
|
||||
|
||||
if (index == dev_priv->drrs.refresh_rate_type) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS requested for previously set RR...ignoring\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!crtc_state->hw.active) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"eDP encoder disabled. CRTC not Active\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) {
|
||||
switch (index) {
|
||||
case DRRS_HIGH_RR:
|
||||
intel_dp_set_m_n(crtc_state, M1_N1);
|
||||
break;
|
||||
case DRRS_LOW_RR:
|
||||
intel_dp_set_m_n(crtc_state, M2_N2);
|
||||
break;
|
||||
case DRRS_MAX_RR:
|
||||
default:
|
||||
drm_err(&dev_priv->drm,
|
||||
"Unsupported refreshrate type\n");
|
||||
}
|
||||
} else if (DISPLAY_VER(dev_priv) > 6) {
|
||||
i915_reg_t reg = PIPECONF(crtc_state->cpu_transcoder);
|
||||
u32 val;
|
||||
|
||||
val = intel_de_read(dev_priv, reg);
|
||||
if (index > DRRS_HIGH_RR) {
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
|
||||
else
|
||||
val |= PIPECONF_EDP_RR_MODE_SWITCH;
|
||||
} else {
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
|
||||
else
|
||||
val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
|
||||
}
|
||||
intel_de_write(dev_priv, reg, val);
|
||||
}
|
||||
|
||||
dev_priv->drrs.refresh_rate_type = index;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n",
|
||||
refresh_rate);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_edp_drrs_enable_locked(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
dev_priv->drrs.busy_frontbuffer_bits = 0;
|
||||
dev_priv->drrs.dp = intel_dp;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_enable - init drrs struct if supported
|
||||
* @intel_dp: DP struct
|
||||
* @crtc_state: A pointer to the active crtc state.
|
||||
*
|
||||
* Initializes frontbuffer_bits and drrs.dp
|
||||
*/
|
||||
void intel_edp_drrs_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (!crtc_state->has_drrs)
|
||||
return;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n");
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
if (dev_priv->drrs.dp) {
|
||||
drm_warn(&dev_priv->drm, "DRRS already enabled\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
intel_edp_drrs_enable_locked(intel_dp);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_edp_drrs_disable_locked(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
|
||||
int refresh;
|
||||
|
||||
refresh = drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode);
|
||||
intel_dp_set_drrs_state(dev_priv, crtc_state, refresh);
|
||||
}
|
||||
|
||||
dev_priv->drrs.dp = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_disable - Disable DRRS
|
||||
* @intel_dp: DP struct
|
||||
* @old_crtc_state: Pointer to old crtc_state.
|
||||
*
|
||||
*/
|
||||
void intel_edp_drrs_disable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *old_crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (!old_crtc_state->has_drrs)
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
if (!dev_priv->drrs.dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
intel_edp_drrs_disable_locked(intel_dp, old_crtc_state);
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
|
||||
cancel_delayed_work_sync(&dev_priv->drrs.work);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_update - Update DRRS state
|
||||
* @intel_dp: Intel DP
|
||||
* @crtc_state: new CRTC state
|
||||
*
|
||||
* This function will update DRRS states, disabling or enabling DRRS when
|
||||
* executing fastsets. For full modeset, intel_edp_drrs_disable() and
|
||||
* intel_edp_drrs_enable() should be called instead.
|
||||
*/
|
||||
void
|
||||
intel_edp_drrs_update(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
/* New state matches current one? */
|
||||
if (crtc_state->has_drrs == !!dev_priv->drrs.dp)
|
||||
goto unlock;
|
||||
|
||||
if (crtc_state->has_drrs)
|
||||
intel_edp_drrs_enable_locked(intel_dp);
|
||||
else
|
||||
intel_edp_drrs_disable_locked(intel_dp, crtc_state);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
static void intel_edp_drrs_downclock_work(struct work_struct *work)
|
||||
{
|
||||
struct drm_i915_private *dev_priv =
|
||||
container_of(work, typeof(*dev_priv), drrs.work.work);
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
|
||||
if (!intel_dp)
|
||||
goto unlock;
|
||||
|
||||
/*
|
||||
* The delayed work can race with an invalidate hence we need to
|
||||
* recheck.
|
||||
*/
|
||||
|
||||
if (dev_priv->drrs.busy_frontbuffer_bits)
|
||||
goto unlock;
|
||||
|
||||
if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR) {
|
||||
struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode));
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_invalidate - Disable Idleness DRRS
|
||||
* @dev_priv: i915 device
|
||||
* @frontbuffer_bits: frontbuffer plane tracking bits
|
||||
*
|
||||
* This function gets called everytime rendering on the given planes start.
|
||||
* Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
|
||||
*
|
||||
* Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
|
||||
*/
|
||||
void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits)
|
||||
{
|
||||
struct intel_dp *intel_dp;
|
||||
struct drm_crtc *crtc;
|
||||
enum pipe pipe;
|
||||
|
||||
if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&dev_priv->drrs.work);
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
if (!intel_dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
pipe = to_intel_crtc(crtc)->pipe;
|
||||
|
||||
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
|
||||
dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
|
||||
|
||||
/* invalidate means busy screen hence upclock */
|
||||
if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
|
||||
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_flush - Restart Idleness DRRS
|
||||
* @dev_priv: i915 device
|
||||
* @frontbuffer_bits: frontbuffer plane tracking bits
|
||||
*
|
||||
* This function gets called every time rendering on the given planes has
|
||||
* completed or flip on a crtc is completed. So DRRS should be upclocked
|
||||
* (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
|
||||
* if no other planes are dirty.
|
||||
*
|
||||
* Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
|
||||
*/
|
||||
void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits)
|
||||
{
|
||||
struct intel_dp *intel_dp;
|
||||
struct drm_crtc *crtc;
|
||||
enum pipe pipe;
|
||||
|
||||
if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&dev_priv->drrs.work);
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
if (!intel_dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
pipe = to_intel_crtc(crtc)->pipe;
|
||||
|
||||
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
|
||||
dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
|
||||
|
||||
/* flush means busy screen hence upclock */
|
||||
if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
|
||||
|
||||
/*
|
||||
* flush also means no more activity hence schedule downclock, if all
|
||||
* other fbs are quiescent too
|
||||
*/
|
||||
if (!dev_priv->drrs.busy_frontbuffer_bits)
|
||||
schedule_delayed_work(&dev_priv->drrs.work,
|
||||
msecs_to_jiffies(1000));
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* DOC: Display Refresh Rate Switching (DRRS)
|
||||
*
|
||||
* Display Refresh Rate Switching (DRRS) is a power conservation feature
|
||||
* which enables swtching between low and high refresh rates,
|
||||
* dynamically, based on the usage scenario. This feature is applicable
|
||||
* for internal panels.
|
||||
*
|
||||
* Indication that the panel supports DRRS is given by the panel EDID, which
|
||||
* would list multiple refresh rates for one resolution.
|
||||
*
|
||||
* DRRS is of 2 types - static and seamless.
|
||||
* Static DRRS involves changing refresh rate (RR) by doing a full modeset
|
||||
* (may appear as a blink on screen) and is used in dock-undock scenario.
|
||||
* Seamless DRRS involves changing RR without any visual effect to the user
|
||||
* and can be used during normal system usage. This is done by programming
|
||||
* certain registers.
|
||||
*
|
||||
* Support for static/seamless DRRS may be indicated in the VBT based on
|
||||
* inputs from the panel spec.
|
||||
*
|
||||
* DRRS saves power by switching to low RR based on usage scenarios.
|
||||
*
|
||||
* The implementation is based on frontbuffer tracking implementation. When
|
||||
* there is a disturbance on the screen triggered by user activity or a periodic
|
||||
* system activity, DRRS is disabled (RR is changed to high RR). When there is
|
||||
* no movement on screen, after a timeout of 1 second, a switch to low RR is
|
||||
* made.
|
||||
*
|
||||
* For integration with frontbuffer tracking code, intel_edp_drrs_invalidate()
|
||||
* and intel_edp_drrs_flush() are called.
|
||||
*
|
||||
* DRRS can be further extended to support other internal panels and also
|
||||
* the scenario of video playback wherein RR is set based on the rate
|
||||
* requested by userspace.
|
||||
*/
|
||||
|
||||
/**
|
||||
* intel_dp_drrs_init - Init basic DRRS work and mutex.
|
||||
* @connector: eDP connector
|
||||
* @fixed_mode: preferred mode of panel
|
||||
*
|
||||
* This function is called only once at driver load to initialize basic
|
||||
* DRRS stuff.
|
||||
*
|
||||
* Returns:
|
||||
* Downclock mode if panel supports it, else return NULL.
|
||||
* DRRS support is determined by the presence of downclock mode (apart
|
||||
* from VBT setting).
|
||||
*/
|
||||
static struct drm_display_mode *
|
||||
intel_dp_drrs_init(struct intel_connector *connector,
|
||||
struct drm_display_mode *fixed_mode)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct drm_display_mode *downclock_mode = NULL;
|
||||
|
||||
INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
|
||||
mutex_init(&dev_priv->drrs.mutex);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) <= 6) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS supported for Gen7 and above\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
|
||||
drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode);
|
||||
if (!downclock_mode) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Downclock mode is not found. DRRS not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev_priv->drrs.type = dev_priv->vbt.drrs_type;
|
||||
|
||||
dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"seamless DRRS supported for eDP panel.\n");
|
||||
return downclock_mode;
|
||||
}
|
||||
|
||||
static bool intel_edp_init_connector(struct intel_dp *intel_dp,
|
||||
struct intel_connector *intel_connector)
|
||||
{
|
||||
|
||||
@@ -70,17 +70,6 @@ int intel_dp_max_link_rate(struct intel_dp *intel_dp);
|
||||
int intel_dp_max_lane_count(struct intel_dp *intel_dp);
|
||||
int intel_dp_rate_select(struct intel_dp *intel_dp, int rate);
|
||||
|
||||
void intel_edp_drrs_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_edp_drrs_disable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_edp_drrs_update(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
|
||||
void intel_dp_compute_rate(struct intel_dp *intel_dp, int port_clock,
|
||||
u8 *link_bw, u8 *rate_select);
|
||||
bool intel_dp_source_supports_hbr2(struct intel_dp *intel_dp);
|
||||
|
||||
229
drivers/gpu/drm/i915/display/intel_dpt.c
Normal file
229
drivers/gpu/drm/i915/display/intel_dpt.c
Normal file
@@ -0,0 +1,229 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_dpt.h"
|
||||
#include "intel_fb.h"
|
||||
#include "gt/gen8_ppgtt.h"
|
||||
|
||||
struct i915_dpt {
|
||||
struct i915_address_space vm;
|
||||
|
||||
struct drm_i915_gem_object *obj;
|
||||
struct i915_vma *vma;
|
||||
void __iomem *iomem;
|
||||
};
|
||||
|
||||
#define i915_is_dpt(vm) ((vm)->is_dpt)
|
||||
|
||||
static inline struct i915_dpt *
|
||||
i915_vm_to_dpt(struct i915_address_space *vm)
|
||||
{
|
||||
BUILD_BUG_ON(offsetof(struct i915_dpt, vm));
|
||||
GEM_BUG_ON(!i915_is_dpt(vm));
|
||||
return container_of(vm, struct i915_dpt, vm);
|
||||
}
|
||||
|
||||
#define dpt_total_entries(dpt) ((dpt)->vm.total >> PAGE_SHIFT)
|
||||
|
||||
static void gen8_set_pte(void __iomem *addr, gen8_pte_t pte)
|
||||
{
|
||||
writeq(pte, addr);
|
||||
}
|
||||
|
||||
static void dpt_insert_page(struct i915_address_space *vm,
|
||||
dma_addr_t addr,
|
||||
u64 offset,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
gen8_pte_t __iomem *base = dpt->iomem;
|
||||
|
||||
gen8_set_pte(base + offset / I915_GTT_PAGE_SIZE,
|
||||
vm->pte_encode(addr, level, flags));
|
||||
}
|
||||
|
||||
static void dpt_insert_entries(struct i915_address_space *vm,
|
||||
struct i915_vma *vma,
|
||||
enum i915_cache_level level,
|
||||
u32 flags)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
gen8_pte_t __iomem *base = dpt->iomem;
|
||||
const gen8_pte_t pte_encode = vm->pte_encode(0, level, flags);
|
||||
struct sgt_iter sgt_iter;
|
||||
dma_addr_t addr;
|
||||
int i;
|
||||
|
||||
/*
|
||||
* Note that we ignore PTE_READ_ONLY here. The caller must be careful
|
||||
* not to allow the user to override access to a read only page.
|
||||
*/
|
||||
|
||||
i = vma->node.start / I915_GTT_PAGE_SIZE;
|
||||
for_each_sgt_daddr(addr, sgt_iter, vma->pages)
|
||||
gen8_set_pte(&base[i++], pte_encode | addr);
|
||||
}
|
||||
|
||||
static void dpt_clear_range(struct i915_address_space *vm,
|
||||
u64 start, u64 length)
|
||||
{
|
||||
}
|
||||
|
||||
static void dpt_bind_vma(struct i915_address_space *vm,
|
||||
struct i915_vm_pt_stash *stash,
|
||||
struct i915_vma *vma,
|
||||
enum i915_cache_level cache_level,
|
||||
u32 flags)
|
||||
{
|
||||
struct drm_i915_gem_object *obj = vma->obj;
|
||||
u32 pte_flags;
|
||||
|
||||
/* Applicable to VLV (gen8+ do not support RO in the GGTT) */
|
||||
pte_flags = 0;
|
||||
if (vma->vm->has_read_only && i915_gem_object_is_readonly(obj))
|
||||
pte_flags |= PTE_READ_ONLY;
|
||||
if (i915_gem_object_is_lmem(obj))
|
||||
pte_flags |= PTE_LM;
|
||||
|
||||
vma->vm->insert_entries(vma->vm, vma, cache_level, pte_flags);
|
||||
|
||||
vma->page_sizes.gtt = I915_GTT_PAGE_SIZE;
|
||||
|
||||
/*
|
||||
* Without aliasing PPGTT there's no difference between
|
||||
* GLOBAL/LOCAL_BIND, it's all the same ptes. Hence unconditionally
|
||||
* upgrade to both bound if we bind either to avoid double-binding.
|
||||
*/
|
||||
atomic_or(I915_VMA_GLOBAL_BIND | I915_VMA_LOCAL_BIND, &vma->flags);
|
||||
}
|
||||
|
||||
static void dpt_unbind_vma(struct i915_address_space *vm, struct i915_vma *vma)
|
||||
{
|
||||
vm->clear_range(vm, vma->node.start, vma->size);
|
||||
}
|
||||
|
||||
static void dpt_cleanup(struct i915_address_space *vm)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
|
||||
i915_gem_object_put(dpt->obj);
|
||||
}
|
||||
|
||||
struct i915_vma *intel_dpt_pin(struct i915_address_space *vm)
|
||||
{
|
||||
struct drm_i915_private *i915 = vm->i915;
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
intel_wakeref_t wakeref;
|
||||
struct i915_vma *vma;
|
||||
void __iomem *iomem;
|
||||
|
||||
wakeref = intel_runtime_pm_get(&i915->runtime_pm);
|
||||
atomic_inc(&i915->gpu_error.pending_fb_pin);
|
||||
|
||||
vma = i915_gem_object_ggtt_pin(dpt->obj, NULL, 0, 4096,
|
||||
HAS_LMEM(i915) ? 0 : PIN_MAPPABLE);
|
||||
if (IS_ERR(vma))
|
||||
goto err;
|
||||
|
||||
iomem = i915_vma_pin_iomap(vma);
|
||||
i915_vma_unpin(vma);
|
||||
if (IS_ERR(iomem)) {
|
||||
vma = iomem;
|
||||
goto err;
|
||||
}
|
||||
|
||||
dpt->vma = vma;
|
||||
dpt->iomem = iomem;
|
||||
|
||||
i915_vma_get(vma);
|
||||
|
||||
err:
|
||||
atomic_dec(&i915->gpu_error.pending_fb_pin);
|
||||
intel_runtime_pm_put(&i915->runtime_pm, wakeref);
|
||||
|
||||
return vma;
|
||||
}
|
||||
|
||||
void intel_dpt_unpin(struct i915_address_space *vm)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
|
||||
i915_vma_unpin_iomap(dpt->vma);
|
||||
i915_vma_put(dpt->vma);
|
||||
}
|
||||
|
||||
struct i915_address_space *
|
||||
intel_dpt_create(struct intel_framebuffer *fb)
|
||||
{
|
||||
struct drm_gem_object *obj = &intel_fb_obj(&fb->base)->base;
|
||||
struct drm_i915_private *i915 = to_i915(obj->dev);
|
||||
struct drm_i915_gem_object *dpt_obj;
|
||||
struct i915_address_space *vm;
|
||||
struct i915_dpt *dpt;
|
||||
size_t size;
|
||||
int ret;
|
||||
|
||||
if (intel_fb_needs_pot_stride_remap(fb))
|
||||
size = intel_remapped_info_size(&fb->remapped_view.gtt.remapped);
|
||||
else
|
||||
size = DIV_ROUND_UP_ULL(obj->size, I915_GTT_PAGE_SIZE);
|
||||
|
||||
size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE);
|
||||
|
||||
if (HAS_LMEM(i915))
|
||||
dpt_obj = i915_gem_object_create_lmem(i915, size, 0);
|
||||
else
|
||||
dpt_obj = i915_gem_object_create_stolen(i915, size);
|
||||
if (IS_ERR(dpt_obj))
|
||||
return ERR_CAST(dpt_obj);
|
||||
|
||||
ret = i915_gem_object_set_cache_level(dpt_obj, I915_CACHE_NONE);
|
||||
if (ret) {
|
||||
i915_gem_object_put(dpt_obj);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
dpt = kzalloc(sizeof(*dpt), GFP_KERNEL);
|
||||
if (!dpt) {
|
||||
i915_gem_object_put(dpt_obj);
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
|
||||
vm = &dpt->vm;
|
||||
|
||||
vm->gt = &i915->gt;
|
||||
vm->i915 = i915;
|
||||
vm->dma = i915->drm.dev;
|
||||
vm->total = (size / sizeof(gen8_pte_t)) * I915_GTT_PAGE_SIZE;
|
||||
vm->is_dpt = true;
|
||||
|
||||
i915_address_space_init(vm, VM_CLASS_DPT);
|
||||
|
||||
vm->insert_page = dpt_insert_page;
|
||||
vm->clear_range = dpt_clear_range;
|
||||
vm->insert_entries = dpt_insert_entries;
|
||||
vm->cleanup = dpt_cleanup;
|
||||
|
||||
vm->vma_ops.bind_vma = dpt_bind_vma;
|
||||
vm->vma_ops.unbind_vma = dpt_unbind_vma;
|
||||
vm->vma_ops.set_pages = ggtt_set_pages;
|
||||
vm->vma_ops.clear_pages = clear_pages;
|
||||
|
||||
vm->pte_encode = gen8_ggtt_pte_encode;
|
||||
|
||||
dpt->obj = dpt_obj;
|
||||
|
||||
return &dpt->vm;
|
||||
}
|
||||
|
||||
void intel_dpt_destroy(struct i915_address_space *vm)
|
||||
{
|
||||
struct i915_dpt *dpt = i915_vm_to_dpt(vm);
|
||||
|
||||
i915_vm_close(&dpt->vm);
|
||||
}
|
||||
19
drivers/gpu/drm/i915/display/intel_dpt.h
Normal file
19
drivers/gpu/drm/i915/display/intel_dpt.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DPT_H__
|
||||
#define __INTEL_DPT_H__
|
||||
|
||||
struct i915_address_space;
|
||||
struct i915_vma;
|
||||
struct intel_framebuffer;
|
||||
|
||||
void intel_dpt_destroy(struct i915_address_space *vm);
|
||||
struct i915_vma *intel_dpt_pin(struct i915_address_space *vm);
|
||||
void intel_dpt_unpin(struct i915_address_space *vm);
|
||||
struct i915_address_space *
|
||||
intel_dpt_create(struct intel_framebuffer *fb);
|
||||
|
||||
#endif /* __INTEL_DPT_H__ */
|
||||
485
drivers/gpu/drm/i915/display/intel_drrs.c
Normal file
485
drivers/gpu/drm/i915/display/intel_drrs.c
Normal file
@@ -0,0 +1,485 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_de.h"
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_panel.h"
|
||||
|
||||
/**
|
||||
* DOC: Display Refresh Rate Switching (DRRS)
|
||||
*
|
||||
* Display Refresh Rate Switching (DRRS) is a power conservation feature
|
||||
* which enables swtching between low and high refresh rates,
|
||||
* dynamically, based on the usage scenario. This feature is applicable
|
||||
* for internal panels.
|
||||
*
|
||||
* Indication that the panel supports DRRS is given by the panel EDID, which
|
||||
* would list multiple refresh rates for one resolution.
|
||||
*
|
||||
* DRRS is of 2 types - static and seamless.
|
||||
* Static DRRS involves changing refresh rate (RR) by doing a full modeset
|
||||
* (may appear as a blink on screen) and is used in dock-undock scenario.
|
||||
* Seamless DRRS involves changing RR without any visual effect to the user
|
||||
* and can be used during normal system usage. This is done by programming
|
||||
* certain registers.
|
||||
*
|
||||
* Support for static/seamless DRRS may be indicated in the VBT based on
|
||||
* inputs from the panel spec.
|
||||
*
|
||||
* DRRS saves power by switching to low RR based on usage scenarios.
|
||||
*
|
||||
* The implementation is based on frontbuffer tracking implementation. When
|
||||
* there is a disturbance on the screen triggered by user activity or a periodic
|
||||
* system activity, DRRS is disabled (RR is changed to high RR). When there is
|
||||
* no movement on screen, after a timeout of 1 second, a switch to low RR is
|
||||
* made.
|
||||
*
|
||||
* For integration with frontbuffer tracking code, intel_edp_drrs_invalidate()
|
||||
* and intel_edp_drrs_flush() are called.
|
||||
*
|
||||
* DRRS can be further extended to support other internal panels and also
|
||||
* the scenario of video playback wherein RR is set based on the rate
|
||||
* requested by userspace.
|
||||
*/
|
||||
|
||||
void
|
||||
intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
int output_bpp, bool constant_n)
|
||||
{
|
||||
struct intel_connector *intel_connector = intel_dp->attached_connector;
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
int pixel_clock;
|
||||
|
||||
if (pipe_config->vrr.enable)
|
||||
return;
|
||||
|
||||
/*
|
||||
* DRRS and PSR can't be enable together, so giving preference to PSR
|
||||
* as it allows more power-savings by complete shutting down display,
|
||||
* so to guarantee this, intel_dp_drrs_compute_config() must be called
|
||||
* after intel_psr_compute_config().
|
||||
*/
|
||||
if (pipe_config->has_psr)
|
||||
return;
|
||||
|
||||
if (!intel_connector->panel.downclock_mode ||
|
||||
dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
|
||||
return;
|
||||
|
||||
pipe_config->has_drrs = true;
|
||||
|
||||
pixel_clock = intel_connector->panel.downclock_mode->clock;
|
||||
if (pipe_config->splitter.enable)
|
||||
pixel_clock /= pipe_config->splitter.link_count;
|
||||
|
||||
intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock,
|
||||
pipe_config->port_clock, &pipe_config->dp_m2_n2,
|
||||
constant_n, pipe_config->fec_enable);
|
||||
|
||||
/* FIXME: abstract this better */
|
||||
if (pipe_config->splitter.enable)
|
||||
pipe_config->dp_m2_n2.gmch_m *= pipe_config->splitter.link_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_dp_set_drrs_state - program registers for RR switch to take effect
|
||||
* @dev_priv: i915 device
|
||||
* @crtc_state: a pointer to the active intel_crtc_state
|
||||
* @refresh_rate: RR to be programmed
|
||||
*
|
||||
* This function gets called when refresh rate (RR) has to be changed from
|
||||
* one frequency to another. Switches can be between high and low RR
|
||||
* supported by the panel or to any other RR based on media playback (in
|
||||
* this case, RR value needs to be passed from user space).
|
||||
*
|
||||
* The caller of this function needs to take a lock on dev_priv->drrs.
|
||||
*/
|
||||
static void intel_dp_set_drrs_state(struct drm_i915_private *dev_priv,
|
||||
const struct intel_crtc_state *crtc_state,
|
||||
int refresh_rate)
|
||||
{
|
||||
struct intel_dp *intel_dp = dev_priv->drrs.dp;
|
||||
struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
|
||||
enum drrs_refresh_rate_type index = DRRS_HIGH_RR;
|
||||
|
||||
if (refresh_rate <= 0) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Refresh rate should be positive non-zero.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (intel_dp == NULL) {
|
||||
drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!crtc) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS: intel_crtc not initialized\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) {
|
||||
drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode) ==
|
||||
refresh_rate)
|
||||
index = DRRS_LOW_RR;
|
||||
|
||||
if (index == dev_priv->drrs.refresh_rate_type) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS requested for previously set RR...ignoring\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!crtc_state->hw.active) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"eDP encoder disabled. CRTC not Active\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) {
|
||||
switch (index) {
|
||||
case DRRS_HIGH_RR:
|
||||
intel_dp_set_m_n(crtc_state, M1_N1);
|
||||
break;
|
||||
case DRRS_LOW_RR:
|
||||
intel_dp_set_m_n(crtc_state, M2_N2);
|
||||
break;
|
||||
case DRRS_MAX_RR:
|
||||
default:
|
||||
drm_err(&dev_priv->drm,
|
||||
"Unsupported refreshrate type\n");
|
||||
}
|
||||
} else if (DISPLAY_VER(dev_priv) > 6) {
|
||||
i915_reg_t reg = PIPECONF(crtc_state->cpu_transcoder);
|
||||
u32 val;
|
||||
|
||||
val = intel_de_read(dev_priv, reg);
|
||||
if (index > DRRS_HIGH_RR) {
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
val |= PIPECONF_EDP_RR_MODE_SWITCH_VLV;
|
||||
else
|
||||
val |= PIPECONF_EDP_RR_MODE_SWITCH;
|
||||
} else {
|
||||
if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv))
|
||||
val &= ~PIPECONF_EDP_RR_MODE_SWITCH_VLV;
|
||||
else
|
||||
val &= ~PIPECONF_EDP_RR_MODE_SWITCH;
|
||||
}
|
||||
intel_de_write(dev_priv, reg, val);
|
||||
}
|
||||
|
||||
dev_priv->drrs.refresh_rate_type = index;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n",
|
||||
refresh_rate);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_edp_drrs_enable_locked(struct intel_dp *intel_dp)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
dev_priv->drrs.busy_frontbuffer_bits = 0;
|
||||
dev_priv->drrs.dp = intel_dp;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_enable - init drrs struct if supported
|
||||
* @intel_dp: DP struct
|
||||
* @crtc_state: A pointer to the active crtc state.
|
||||
*
|
||||
* Initializes frontbuffer_bits and drrs.dp
|
||||
*/
|
||||
void intel_edp_drrs_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (!crtc_state->has_drrs)
|
||||
return;
|
||||
|
||||
drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n");
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
if (dev_priv->drrs.dp) {
|
||||
drm_warn(&dev_priv->drm, "DRRS already enabled\n");
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
intel_edp_drrs_enable_locked(intel_dp);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
static void
|
||||
intel_edp_drrs_disable_locked(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR) {
|
||||
int refresh;
|
||||
|
||||
refresh = drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode);
|
||||
intel_dp_set_drrs_state(dev_priv, crtc_state, refresh);
|
||||
}
|
||||
|
||||
dev_priv->drrs.dp = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_disable - Disable DRRS
|
||||
* @intel_dp: DP struct
|
||||
* @old_crtc_state: Pointer to old crtc_state.
|
||||
*
|
||||
*/
|
||||
void intel_edp_drrs_disable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *old_crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (!old_crtc_state->has_drrs)
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
if (!dev_priv->drrs.dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
intel_edp_drrs_disable_locked(intel_dp, old_crtc_state);
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
|
||||
cancel_delayed_work_sync(&dev_priv->drrs.work);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_update - Update DRRS state
|
||||
* @intel_dp: Intel DP
|
||||
* @crtc_state: new CRTC state
|
||||
*
|
||||
* This function will update DRRS states, disabling or enabling DRRS when
|
||||
* executing fastsets. For full modeset, intel_edp_drrs_disable() and
|
||||
* intel_edp_drrs_enable() should be called instead.
|
||||
*/
|
||||
void
|
||||
intel_edp_drrs_update(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = dp_to_i915(intel_dp);
|
||||
|
||||
if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT)
|
||||
return;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
/* New state matches current one? */
|
||||
if (crtc_state->has_drrs == !!dev_priv->drrs.dp)
|
||||
goto unlock;
|
||||
|
||||
if (crtc_state->has_drrs)
|
||||
intel_edp_drrs_enable_locked(intel_dp);
|
||||
else
|
||||
intel_edp_drrs_disable_locked(intel_dp, crtc_state);
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
static void intel_edp_drrs_downclock_work(struct work_struct *work)
|
||||
{
|
||||
struct drm_i915_private *dev_priv =
|
||||
container_of(work, typeof(*dev_priv), drrs.work.work);
|
||||
struct intel_dp *intel_dp;
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
|
||||
if (!intel_dp)
|
||||
goto unlock;
|
||||
|
||||
/*
|
||||
* The delayed work can race with an invalidate hence we need to
|
||||
* recheck.
|
||||
*/
|
||||
|
||||
if (dev_priv->drrs.busy_frontbuffer_bits)
|
||||
goto unlock;
|
||||
|
||||
if (dev_priv->drrs.refresh_rate_type != DRRS_LOW_RR) {
|
||||
struct drm_crtc *crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.downclock_mode));
|
||||
}
|
||||
|
||||
unlock:
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_invalidate - Disable Idleness DRRS
|
||||
* @dev_priv: i915 device
|
||||
* @frontbuffer_bits: frontbuffer plane tracking bits
|
||||
*
|
||||
* This function gets called everytime rendering on the given planes start.
|
||||
* Hence DRRS needs to be Upclocked, i.e. (LOW_RR -> HIGH_RR).
|
||||
*
|
||||
* Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
|
||||
*/
|
||||
void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits)
|
||||
{
|
||||
struct intel_dp *intel_dp;
|
||||
struct drm_crtc *crtc;
|
||||
enum pipe pipe;
|
||||
|
||||
if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&dev_priv->drrs.work);
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
if (!intel_dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
pipe = to_intel_crtc(crtc)->pipe;
|
||||
|
||||
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
|
||||
dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits;
|
||||
|
||||
/* invalidate means busy screen hence upclock */
|
||||
if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
|
||||
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_edp_drrs_flush - Restart Idleness DRRS
|
||||
* @dev_priv: i915 device
|
||||
* @frontbuffer_bits: frontbuffer plane tracking bits
|
||||
*
|
||||
* This function gets called every time rendering on the given planes has
|
||||
* completed or flip on a crtc is completed. So DRRS should be upclocked
|
||||
* (LOW_RR -> HIGH_RR). And also Idleness detection should be started again,
|
||||
* if no other planes are dirty.
|
||||
*
|
||||
* Dirty frontbuffers relevant to DRRS are tracked in busy_frontbuffer_bits.
|
||||
*/
|
||||
void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits)
|
||||
{
|
||||
struct intel_dp *intel_dp;
|
||||
struct drm_crtc *crtc;
|
||||
enum pipe pipe;
|
||||
|
||||
if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED)
|
||||
return;
|
||||
|
||||
cancel_delayed_work(&dev_priv->drrs.work);
|
||||
|
||||
mutex_lock(&dev_priv->drrs.mutex);
|
||||
|
||||
intel_dp = dev_priv->drrs.dp;
|
||||
if (!intel_dp) {
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
crtc = dp_to_dig_port(intel_dp)->base.base.crtc;
|
||||
pipe = to_intel_crtc(crtc)->pipe;
|
||||
|
||||
frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe);
|
||||
dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits;
|
||||
|
||||
/* flush means busy screen hence upclock */
|
||||
if (frontbuffer_bits && dev_priv->drrs.refresh_rate_type == DRRS_LOW_RR)
|
||||
intel_dp_set_drrs_state(dev_priv, to_intel_crtc(crtc)->config,
|
||||
drm_mode_vrefresh(intel_dp->attached_connector->panel.fixed_mode));
|
||||
|
||||
/*
|
||||
* flush also means no more activity hence schedule downclock, if all
|
||||
* other fbs are quiescent too
|
||||
*/
|
||||
if (!dev_priv->drrs.busy_frontbuffer_bits)
|
||||
schedule_delayed_work(&dev_priv->drrs.work,
|
||||
msecs_to_jiffies(1000));
|
||||
mutex_unlock(&dev_priv->drrs.mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* intel_dp_drrs_init - Init basic DRRS work and mutex.
|
||||
* @connector: eDP connector
|
||||
* @fixed_mode: preferred mode of panel
|
||||
*
|
||||
* This function is called only once at driver load to initialize basic
|
||||
* DRRS stuff.
|
||||
*
|
||||
* Returns:
|
||||
* Downclock mode if panel supports it, else return NULL.
|
||||
* DRRS support is determined by the presence of downclock mode (apart
|
||||
* from VBT setting).
|
||||
*/
|
||||
struct drm_display_mode *
|
||||
intel_dp_drrs_init(struct intel_connector *connector,
|
||||
struct drm_display_mode *fixed_mode)
|
||||
{
|
||||
struct drm_i915_private *dev_priv = to_i915(connector->base.dev);
|
||||
struct intel_encoder *encoder = connector->encoder;
|
||||
struct drm_display_mode *downclock_mode = NULL;
|
||||
|
||||
INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_edp_drrs_downclock_work);
|
||||
mutex_init(&dev_priv->drrs.mutex);
|
||||
|
||||
if (DISPLAY_VER(dev_priv) <= 6) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS supported for Gen7 and above\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((DISPLAY_VER(dev_priv) < 8 && !HAS_GMCH(dev_priv)) &&
|
||||
encoder->port != PORT_A) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"DRRS only supported on eDP port A\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) {
|
||||
drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode);
|
||||
if (!downclock_mode) {
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"Downclock mode is not found. DRRS not supported\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev_priv->drrs.type = dev_priv->vbt.drrs_type;
|
||||
|
||||
dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR;
|
||||
drm_dbg_kms(&dev_priv->drm,
|
||||
"seamless DRRS supported for eDP panel.\n");
|
||||
return downclock_mode;
|
||||
}
|
||||
32
drivers/gpu/drm/i915/display/intel_drrs.h
Normal file
32
drivers/gpu/drm/i915/display/intel_drrs.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
/*
|
||||
* Copyright © 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#ifndef __INTEL_DRRS_H__
|
||||
#define __INTEL_DRRS_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct drm_i915_private;
|
||||
struct intel_crtc_state;
|
||||
struct intel_connector;
|
||||
struct intel_dp;
|
||||
|
||||
void intel_edp_drrs_enable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_edp_drrs_disable(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_edp_drrs_update(struct intel_dp *intel_dp,
|
||||
const struct intel_crtc_state *crtc_state);
|
||||
void intel_edp_drrs_invalidate(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
void intel_edp_drrs_flush(struct drm_i915_private *dev_priv,
|
||||
unsigned int frontbuffer_bits);
|
||||
void intel_dp_drrs_compute_config(struct intel_dp *intel_dp,
|
||||
struct intel_crtc_state *pipe_config,
|
||||
int output_bpp, bool constant_n);
|
||||
struct drm_display_mode *intel_dp_drrs_init(struct intel_connector *connector,
|
||||
struct drm_display_mode *fixed_mode);
|
||||
|
||||
#endif /* __INTEL_DRRS_H__ */
|
||||
@@ -62,6 +62,7 @@
|
||||
#include "intel_display_types.h"
|
||||
#include "intel_fbc.h"
|
||||
#include "intel_frontbuffer.h"
|
||||
#include "intel_drrs.h"
|
||||
#include "intel_psr.h"
|
||||
|
||||
/**
|
||||
|
||||
@@ -162,7 +162,6 @@ retry:
|
||||
/* Immediately discard the backing storage */
|
||||
void i915_gem_object_truncate(struct drm_i915_gem_object *obj)
|
||||
{
|
||||
drm_gem_free_mmap_offset(&obj->base);
|
||||
if (obj->ops->truncate)
|
||||
obj->ops->truncate(obj);
|
||||
}
|
||||
|
||||
@@ -133,7 +133,7 @@ static int guc_action_slpc_unset_param(struct intel_guc *guc, u8 id)
|
||||
{
|
||||
u32 request[] = {
|
||||
GUC_ACTION_HOST2GUC_PC_SLPC_REQUEST,
|
||||
SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 2),
|
||||
SLPC_EVENT(SLPC_EVENT_PARAMETER_UNSET, 1),
|
||||
id,
|
||||
};
|
||||
|
||||
|
||||
@@ -108,6 +108,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
|
||||
/* Comet Lake V PCH is based on KBP, which is SPT compatible */
|
||||
return PCH_SPT;
|
||||
case INTEL_PCH_ICP_DEVICE_ID_TYPE:
|
||||
case INTEL_PCH_ICP2_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n");
|
||||
drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv));
|
||||
return PCH_ICP;
|
||||
@@ -123,7 +124,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id)
|
||||
!IS_GEN9_BC(dev_priv));
|
||||
return PCH_TGP;
|
||||
case INTEL_PCH_JSP_DEVICE_ID_TYPE:
|
||||
case INTEL_PCH_JSP2_DEVICE_ID_TYPE:
|
||||
drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n");
|
||||
drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv));
|
||||
return PCH_JSP;
|
||||
|
||||
@@ -50,11 +50,11 @@ enum intel_pch {
|
||||
#define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680
|
||||
#define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380
|
||||
#define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480
|
||||
#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880
|
||||
#define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00
|
||||
#define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080
|
||||
#define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380
|
||||
#define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80
|
||||
#define INTEL_PCH_JSP2_DEVICE_ID_TYPE 0x3880
|
||||
#define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80
|
||||
#define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180
|
||||
#define INTEL_PCH_P2X_DEVICE_ID_TYPE 0x7100
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include <video/mipi_display.h>
|
||||
#include <video/videomode.h>
|
||||
@@ -980,8 +981,10 @@ static int mtk_dsi_bind(struct device *dev, struct device *master, void *data)
|
||||
struct mtk_dsi *dsi = dev_get_drvdata(dev);
|
||||
|
||||
ret = mtk_dsi_encoder_init(drm, dsi);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return device_reset_optional(dev);
|
||||
}
|
||||
|
||||
static void mtk_dsi_unbind(struct device *dev, struct device *master,
|
||||
|
||||
@@ -361,7 +361,17 @@ static void mxsfb_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
bridge_state =
|
||||
drm_atomic_get_new_bridge_state(state,
|
||||
mxsfb->bridge);
|
||||
bus_format = bridge_state->input_bus_cfg.format;
|
||||
if (!bridge_state)
|
||||
bus_format = MEDIA_BUS_FMT_FIXED;
|
||||
else
|
||||
bus_format = bridge_state->input_bus_cfg.format;
|
||||
|
||||
if (bus_format == MEDIA_BUS_FMT_FIXED) {
|
||||
dev_warn_once(drm->dev,
|
||||
"Bridge does not provide bus format, assuming MEDIA_BUS_FMT_RGB888_1X24.\n"
|
||||
"Please fix bridge driver by handling atomic_get_input_bus_fmts.\n");
|
||||
bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is no bridge, use bus format from connector */
|
||||
|
||||
@@ -658,8 +658,10 @@ int sun8i_hdmi_phy_get(struct sun8i_dw_hdmi *hdmi, struct device_node *node)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
phy = platform_get_drvdata(pdev);
|
||||
if (!phy)
|
||||
if (!phy) {
|
||||
put_device(&pdev->dev);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
hdmi->phy = phy;
|
||||
|
||||
|
||||
@@ -88,6 +88,44 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
|
||||
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
|
||||
}
|
||||
|
||||
static void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (readl(privdata->mmio + AMD_P2C_MSG(4))) {
|
||||
writel(0, privdata->mmio + AMD_P2C_MSG(4));
|
||||
writel(0xf, privdata->mmio + AMD_P2C_MSG(5));
|
||||
}
|
||||
}
|
||||
|
||||
static void amd_sfh_clear_intr(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (privdata->mp2_ops->clear_intr)
|
||||
privdata->mp2_ops->clear_intr(privdata);
|
||||
}
|
||||
|
||||
static irqreturn_t amd_sfh_irq_handler(int irq, void *data)
|
||||
{
|
||||
amd_sfh_clear_intr(data);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
int rc;
|
||||
|
||||
pci_intx(privdata->pdev, true);
|
||||
|
||||
rc = devm_request_irq(&privdata->pdev->dev, privdata->pdev->irq,
|
||||
amd_sfh_irq_handler, 0, DRIVER_NAME, privdata);
|
||||
if (rc) {
|
||||
dev_err(&privdata->pdev->dev, "failed to request irq %d err=%d\n",
|
||||
privdata->pdev->irq, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
|
||||
{
|
||||
union sfh_cmd_param cmd_param;
|
||||
@@ -192,6 +230,8 @@ static void amd_mp2_pci_remove(void *privdata)
|
||||
struct amd_mp2_dev *mp2 = privdata;
|
||||
amd_sfh_hid_client_deinit(privdata);
|
||||
mp2->mp2_ops->stop_all(mp2);
|
||||
pci_intx(mp2->pdev, false);
|
||||
amd_sfh_clear_intr(mp2);
|
||||
}
|
||||
|
||||
static const struct amd_mp2_ops amd_sfh_ops_v2 = {
|
||||
@@ -199,6 +239,8 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
|
||||
.stop = amd_stop_sensor_v2,
|
||||
.stop_all = amd_stop_all_sensor_v2,
|
||||
.response = amd_sfh_wait_response_v2,
|
||||
.clear_intr = amd_sfh_clear_intr_v2,
|
||||
.init_intr = amd_sfh_irq_init_v2,
|
||||
};
|
||||
|
||||
static const struct amd_mp2_ops amd_sfh_ops = {
|
||||
@@ -224,6 +266,14 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata)
|
||||
}
|
||||
}
|
||||
|
||||
static int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
|
||||
{
|
||||
if (privdata->mp2_ops->init_intr)
|
||||
return privdata->mp2_ops->init_intr(privdata);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
{
|
||||
struct amd_mp2_dev *privdata;
|
||||
@@ -257,9 +307,20 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
|
||||
|
||||
mp2_select_ops(privdata);
|
||||
|
||||
rc = amd_sfh_hid_client_init(privdata);
|
||||
if (rc)
|
||||
rc = amd_sfh_irq_init(privdata);
|
||||
if (rc) {
|
||||
dev_err(&pdev->dev, "amd_sfh_irq_init failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = amd_sfh_hid_client_init(privdata);
|
||||
if (rc) {
|
||||
amd_sfh_clear_intr(privdata);
|
||||
dev_err(&pdev->dev, "amd_sfh_hid_client_init failed\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
amd_sfh_clear_intr(privdata);
|
||||
|
||||
return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
|
||||
}
|
||||
@@ -287,6 +348,9 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
|
||||
amd_sfh_clear_intr(mp2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -310,6 +374,9 @@ static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
cancel_delayed_work_sync(&cl_data->work_buffer);
|
||||
amd_sfh_clear_intr(mp2);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -140,5 +140,7 @@ struct amd_mp2_ops {
|
||||
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
|
||||
void (*stop_all)(struct amd_mp2_dev *privdata);
|
||||
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
|
||||
void (*clear_intr)(struct amd_mp2_dev *privdata);
|
||||
int (*init_intr)(struct amd_mp2_dev *privdata);
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -825,7 +825,9 @@ static const char *keys[KEY_MAX + 1] = {
|
||||
[KEY_F22] = "F22", [KEY_F23] = "F23",
|
||||
[KEY_F24] = "F24", [KEY_PLAYCD] = "PlayCD",
|
||||
[KEY_PAUSECD] = "PauseCD", [KEY_PROG3] = "Prog3",
|
||||
[KEY_PROG4] = "Prog4", [KEY_SUSPEND] = "Suspend",
|
||||
[KEY_PROG4] = "Prog4",
|
||||
[KEY_ALL_APPLICATIONS] = "AllApplications",
|
||||
[KEY_SUSPEND] = "Suspend",
|
||||
[KEY_CLOSE] = "Close", [KEY_PLAY] = "Play",
|
||||
[KEY_FASTFORWARD] = "FastForward", [KEY_BASSBOOST] = "BassBoost",
|
||||
[KEY_PRINT] = "Print", [KEY_HP] = "HP",
|
||||
@@ -934,6 +936,7 @@ static const char *keys[KEY_MAX + 1] = {
|
||||
[KEY_ASSISTANT] = "Assistant",
|
||||
[KEY_KBD_LAYOUT_NEXT] = "KbdLayoutNext",
|
||||
[KEY_EMOJI_PICKER] = "EmojiPicker",
|
||||
[KEY_DICTATE] = "Dictate",
|
||||
[KEY_BRIGHTNESS_MIN] = "BrightnessMin",
|
||||
[KEY_BRIGHTNESS_MAX] = "BrightnessMax",
|
||||
[KEY_BRIGHTNESS_AUTO] = "BrightnessAuto",
|
||||
|
||||
@@ -991,6 +991,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
case 0x0cd: map_key_clear(KEY_PLAYPAUSE); break;
|
||||
case 0x0cf: map_key_clear(KEY_VOICECOMMAND); break;
|
||||
|
||||
case 0x0d8: map_key_clear(KEY_DICTATE); break;
|
||||
case 0x0d9: map_key_clear(KEY_EMOJI_PICKER); break;
|
||||
|
||||
case 0x0e0: map_abs_clear(ABS_VOLUME); break;
|
||||
@@ -1082,6 +1083,8 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
||||
|
||||
case 0x29d: map_key_clear(KEY_KBD_LAYOUT_NEXT); break;
|
||||
|
||||
case 0x2a2: map_key_clear(KEY_ALL_APPLICATIONS); break;
|
||||
|
||||
case 0x2c7: map_key_clear(KEY_KBDINPUTASSIST_PREV); break;
|
||||
case 0x2c8: map_key_clear(KEY_KBDINPUTASSIST_NEXT); break;
|
||||
case 0x2c9: map_key_clear(KEY_KBDINPUTASSIST_PREVGROUP); break;
|
||||
|
||||
@@ -488,7 +488,7 @@ config I2C_BRCMSTB
|
||||
|
||||
config I2C_CADENCE
|
||||
tristate "Cadence I2C Controller"
|
||||
depends on ARCH_ZYNQ || ARM64 || XTENSA
|
||||
depends on ARCH_ZYNQ || ARM64 || XTENSA || COMPILE_TEST
|
||||
help
|
||||
Say yes here to select Cadence I2C Host Controller. This controller is
|
||||
e.g. used by Xilinx Zynq.
|
||||
@@ -677,7 +677,7 @@ config I2C_IMG
|
||||
|
||||
config I2C_IMX
|
||||
tristate "IMX I2C interface"
|
||||
depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE
|
||||
depends on ARCH_MXC || ARCH_LAYERSCAPE || COLDFIRE || COMPILE_TEST
|
||||
select I2C_SLAVE
|
||||
help
|
||||
Say Y here if you want to use the IIC bus controller on
|
||||
@@ -921,7 +921,7 @@ config I2C_QCOM_GENI
|
||||
|
||||
config I2C_QUP
|
||||
tristate "Qualcomm QUP based I2C controller"
|
||||
depends on ARCH_QCOM
|
||||
depends on ARCH_QCOM || COMPILE_TEST
|
||||
help
|
||||
If you say yes to this option, support will be included for the
|
||||
built-in I2C interface on the Qualcomm SoCs.
|
||||
|
||||
@@ -23,6 +23,11 @@
|
||||
#define BCM2835_I2C_FIFO 0x10
|
||||
#define BCM2835_I2C_DIV 0x14
|
||||
#define BCM2835_I2C_DEL 0x18
|
||||
/*
|
||||
* 16-bit field for the number of SCL cycles to wait after rising SCL
|
||||
* before deciding the slave is not responding. 0 disables the
|
||||
* timeout detection.
|
||||
*/
|
||||
#define BCM2835_I2C_CLKT 0x1c
|
||||
|
||||
#define BCM2835_I2C_C_READ BIT(0)
|
||||
@@ -477,6 +482,12 @@ static int bcm2835_i2c_probe(struct platform_device *pdev)
|
||||
adap->dev.of_node = pdev->dev.of_node;
|
||||
adap->quirks = of_device_get_match_data(&pdev->dev);
|
||||
|
||||
/*
|
||||
* Disable the hardware clock stretching timeout. SMBUS
|
||||
* specifies a limit for how long the device can stretch the
|
||||
* clock, but core I2C doesn't.
|
||||
*/
|
||||
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_CLKT, 0);
|
||||
bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, 0);
|
||||
|
||||
ret = i2c_add_adapter(adap);
|
||||
|
||||
@@ -343,7 +343,8 @@ struct bus_type i3c_bus_type = {
|
||||
static enum i3c_addr_slot_status
|
||||
i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
|
||||
{
|
||||
int status, bitpos = addr * 2;
|
||||
unsigned long status;
|
||||
int bitpos = addr * 2;
|
||||
|
||||
if (addr > I2C_MAX_ADDR)
|
||||
return I3C_ADDR_SLOT_RSVD;
|
||||
|
||||
@@ -793,6 +793,10 @@ static int dw_i3c_master_daa(struct i3c_master_controller *m)
|
||||
return -ENOMEM;
|
||||
|
||||
pos = dw_i3c_master_get_free_pos(master);
|
||||
if (pos < 0) {
|
||||
dw_i3c_master_free_xfer(xfer);
|
||||
return pos;
|
||||
}
|
||||
cmd = &xfer->cmds[0];
|
||||
cmd->cmd_hi = 0x1;
|
||||
cmd->cmd_lo = COMMAND_PORT_DEV_COUNT(master->maxdevs - pos) |
|
||||
|
||||
@@ -160,9 +160,7 @@ static int hci_dat_v1_get_index(struct i3c_hci *hci, u8 dev_addr)
|
||||
unsigned int dat_idx;
|
||||
u32 dat_w0;
|
||||
|
||||
for (dat_idx = find_first_bit(hci->DAT_data, hci->DAT_entries);
|
||||
dat_idx < hci->DAT_entries;
|
||||
dat_idx = find_next_bit(hci->DAT_data, hci->DAT_entries, dat_idx)) {
|
||||
for_each_set_bit(dat_idx, hci->DAT_data, hci->DAT_entries) {
|
||||
dat_w0 = dat_w0_read(dat_idx);
|
||||
if (FIELD_GET(DAT_0_DYNAMIC_ADDRESS, dat_w0) == dev_addr)
|
||||
return dat_idx;
|
||||
|
||||
@@ -2285,6 +2285,12 @@ int input_register_device(struct input_dev *dev)
|
||||
/* KEY_RESERVED is not supposed to be transmitted to userspace. */
|
||||
__clear_bit(KEY_RESERVED, dev->keybit);
|
||||
|
||||
/* Buttonpads should not map BTN_RIGHT and/or BTN_MIDDLE. */
|
||||
if (test_bit(INPUT_PROP_BUTTONPAD, dev->propbit)) {
|
||||
__clear_bit(BTN_RIGHT, dev->keybit);
|
||||
__clear_bit(BTN_MIDDLE, dev->keybit);
|
||||
}
|
||||
|
||||
/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
|
||||
input_cleanse_bitmasks(dev);
|
||||
|
||||
|
||||
@@ -556,7 +556,7 @@ config KEYBOARD_PMIC8XXX
|
||||
|
||||
config KEYBOARD_SAMSUNG
|
||||
tristate "Samsung keypad support"
|
||||
depends on HAVE_CLK
|
||||
depends on HAS_IOMEM && HAVE_CLK
|
||||
select INPUT_MATRIXKMAP
|
||||
help
|
||||
Say Y here if you want to use the keypad on your Samsung mobile
|
||||
|
||||
@@ -186,55 +186,21 @@ static int elan_get_fwinfo(u16 ic_type, u8 iap_version, u16 *validpage_count,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int elan_enable_power(struct elan_tp_data *data)
|
||||
static int elan_set_power(struct elan_tp_data *data, bool on)
|
||||
{
|
||||
int repeat = ETP_RETRY_COUNT;
|
||||
int error;
|
||||
|
||||
error = regulator_enable(data->vcc);
|
||||
if (error) {
|
||||
dev_err(&data->client->dev,
|
||||
"failed to enable regulator: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
do {
|
||||
error = data->ops->power_control(data->client, true);
|
||||
error = data->ops->power_control(data->client, on);
|
||||
if (error >= 0)
|
||||
return 0;
|
||||
|
||||
msleep(30);
|
||||
} while (--repeat > 0);
|
||||
|
||||
dev_err(&data->client->dev, "failed to enable power: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int elan_disable_power(struct elan_tp_data *data)
|
||||
{
|
||||
int repeat = ETP_RETRY_COUNT;
|
||||
int error;
|
||||
|
||||
do {
|
||||
error = data->ops->power_control(data->client, false);
|
||||
if (!error) {
|
||||
error = regulator_disable(data->vcc);
|
||||
if (error) {
|
||||
dev_err(&data->client->dev,
|
||||
"failed to disable regulator: %d\n",
|
||||
error);
|
||||
/* Attempt to power the chip back up */
|
||||
data->ops->power_control(data->client, true);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
msleep(30);
|
||||
} while (--repeat > 0);
|
||||
|
||||
dev_err(&data->client->dev, "failed to disable power: %d\n", error);
|
||||
dev_err(&data->client->dev, "failed to set power %s: %d\n",
|
||||
on ? "on" : "off", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -1399,9 +1365,19 @@ static int __maybe_unused elan_suspend(struct device *dev)
|
||||
/* Enable wake from IRQ */
|
||||
data->irq_wake = (enable_irq_wake(client->irq) == 0);
|
||||
} else {
|
||||
ret = elan_disable_power(data);
|
||||
ret = elan_set_power(data, false);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = regulator_disable(data->vcc);
|
||||
if (ret) {
|
||||
dev_err(dev, "error %d disabling regulator\n", ret);
|
||||
/* Attempt to power the chip back up */
|
||||
elan_set_power(data, true);
|
||||
}
|
||||
}
|
||||
|
||||
err:
|
||||
mutex_unlock(&data->sysfs_mutex);
|
||||
return ret;
|
||||
}
|
||||
@@ -1412,12 +1388,18 @@ static int __maybe_unused elan_resume(struct device *dev)
|
||||
struct elan_tp_data *data = i2c_get_clientdata(client);
|
||||
int error;
|
||||
|
||||
if (device_may_wakeup(dev) && data->irq_wake) {
|
||||
if (!device_may_wakeup(dev)) {
|
||||
error = regulator_enable(data->vcc);
|
||||
if (error) {
|
||||
dev_err(dev, "error %d enabling regulator\n", error);
|
||||
goto err;
|
||||
}
|
||||
} else if (data->irq_wake) {
|
||||
disable_irq_wake(client->irq);
|
||||
data->irq_wake = false;
|
||||
}
|
||||
|
||||
error = elan_enable_power(data);
|
||||
error = elan_set_power(data, true);
|
||||
if (error) {
|
||||
dev_err(dev, "power up when resuming failed: %d\n", error);
|
||||
goto err;
|
||||
|
||||
@@ -131,7 +131,8 @@ static void titsc_step_config(struct titsc *ts_dev)
|
||||
u32 stepenable;
|
||||
|
||||
config = STEPCONFIG_MODE_HWSYNC |
|
||||
STEPCONFIG_AVG_16 | ts_dev->bit_xp;
|
||||
STEPCONFIG_AVG_16 | ts_dev->bit_xp |
|
||||
STEPCONFIG_INM_ADCREFM;
|
||||
switch (ts_dev->wires) {
|
||||
case 4:
|
||||
config |= STEPCONFIG_INP(ts_dev->inp_yp) | ts_dev->bit_xn;
|
||||
@@ -195,7 +196,10 @@ static void titsc_step_config(struct titsc *ts_dev)
|
||||
STEPCONFIG_OPENDLY);
|
||||
|
||||
end_step++;
|
||||
config |= STEPCONFIG_INP(ts_dev->inp_yn);
|
||||
config = STEPCONFIG_MODE_HWSYNC |
|
||||
STEPCONFIG_AVG_16 | ts_dev->bit_yp |
|
||||
ts_dev->bit_xn | STEPCONFIG_INM_ADCREFM |
|
||||
STEPCONFIG_INP(ts_dev->inp_yn);
|
||||
titsc_writel(ts_dev, REG_STEPCONFIG(end_step), config);
|
||||
titsc_writel(ts_dev, REG_STEPDELAY(end_step),
|
||||
STEPCONFIG_OPENDLY);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
extern irqreturn_t amd_iommu_int_thread(int irq, void *data);
|
||||
extern irqreturn_t amd_iommu_int_handler(int irq, void *data);
|
||||
extern void amd_iommu_apply_erratum_63(u16 devid);
|
||||
extern void amd_iommu_restart_event_logging(struct amd_iommu *iommu);
|
||||
extern void amd_iommu_reset_cmd_buffer(struct amd_iommu *iommu);
|
||||
extern int amd_iommu_init_devices(void);
|
||||
extern void amd_iommu_uninit_devices(void);
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
#define PASID_MASK 0x0000ffff
|
||||
|
||||
/* MMIO status bits */
|
||||
#define MMIO_STATUS_EVT_OVERFLOW_INT_MASK (1 << 0)
|
||||
#define MMIO_STATUS_EVT_INT_MASK (1 << 1)
|
||||
#define MMIO_STATUS_COM_WAIT_INT_MASK (1 << 2)
|
||||
#define MMIO_STATUS_PPR_INT_MASK (1 << 6)
|
||||
|
||||
@@ -655,6 +655,16 @@ static int __init alloc_command_buffer(struct amd_iommu *iommu)
|
||||
return iommu->cmd_buf ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function restarts event logging in case the IOMMU experienced
|
||||
* an event log buffer overflow.
|
||||
*/
|
||||
void amd_iommu_restart_event_logging(struct amd_iommu *iommu)
|
||||
{
|
||||
iommu_feature_disable(iommu, CONTROL_EVT_LOG_EN);
|
||||
iommu_feature_enable(iommu, CONTROL_EVT_LOG_EN);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function resets the command buffer if the IOMMU stopped fetching
|
||||
* commands from it.
|
||||
|
||||
@@ -519,12 +519,6 @@ static void v1_free_pgtable(struct io_pgtable *iop)
|
||||
|
||||
dom = container_of(pgtable, struct protection_domain, iop);
|
||||
|
||||
/* Update data structure */
|
||||
amd_iommu_domain_clr_pt_root(dom);
|
||||
|
||||
/* Make changes visible to IOMMUs */
|
||||
amd_iommu_domain_update(dom);
|
||||
|
||||
/* Page-table is not visible to IOMMU anymore, so free it */
|
||||
BUG_ON(pgtable->mode < PAGE_MODE_NONE ||
|
||||
pgtable->mode > PAGE_MODE_6_LEVEL);
|
||||
@@ -532,6 +526,12 @@ static void v1_free_pgtable(struct io_pgtable *iop)
|
||||
root = (unsigned long)pgtable->root;
|
||||
freelist = free_sub_pt(root, pgtable->mode, freelist);
|
||||
|
||||
/* Update data structure */
|
||||
amd_iommu_domain_clr_pt_root(dom);
|
||||
|
||||
/* Make changes visible to IOMMUs */
|
||||
amd_iommu_domain_update(dom);
|
||||
|
||||
free_page_list(freelist);
|
||||
}
|
||||
|
||||
|
||||
@@ -742,7 +742,8 @@ amd_iommu_set_pci_msi_domain(struct device *dev, struct amd_iommu *iommu) { }
|
||||
#endif /* !CONFIG_IRQ_REMAP */
|
||||
|
||||
#define AMD_IOMMU_INT_MASK \
|
||||
(MMIO_STATUS_EVT_INT_MASK | \
|
||||
(MMIO_STATUS_EVT_OVERFLOW_INT_MASK | \
|
||||
MMIO_STATUS_EVT_INT_MASK | \
|
||||
MMIO_STATUS_PPR_INT_MASK | \
|
||||
MMIO_STATUS_GALOG_INT_MASK)
|
||||
|
||||
@@ -752,7 +753,7 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
|
||||
u32 status = readl(iommu->mmio_base + MMIO_STATUS_OFFSET);
|
||||
|
||||
while (status & AMD_IOMMU_INT_MASK) {
|
||||
/* Enable EVT and PPR and GA interrupts again */
|
||||
/* Enable interrupt sources again */
|
||||
writel(AMD_IOMMU_INT_MASK,
|
||||
iommu->mmio_base + MMIO_STATUS_OFFSET);
|
||||
|
||||
@@ -773,6 +774,11 @@ irqreturn_t amd_iommu_int_thread(int irq, void *data)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (status & MMIO_STATUS_EVT_OVERFLOW_INT_MASK) {
|
||||
pr_info_ratelimited("IOMMU event log overflow\n");
|
||||
amd_iommu_restart_event_logging(iommu);
|
||||
}
|
||||
|
||||
/*
|
||||
* Hardware bug: ERBT1312
|
||||
* When re-enabling interrupt (by writing 1
|
||||
|
||||
@@ -2651,7 +2651,7 @@ static struct dmar_domain *dmar_insert_one_dev_info(struct intel_iommu *iommu,
|
||||
spin_unlock_irqrestore(&device_domain_lock, flags);
|
||||
|
||||
/* PASID table is mandatory for a PCI device in scalable mode. */
|
||||
if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
|
||||
if (sm_supported(iommu) && !dev_is_real_dma_subdevice(dev)) {
|
||||
ret = intel_pasid_alloc_table(dev);
|
||||
if (ret) {
|
||||
dev_err(dev, "PASID table allocation failed\n");
|
||||
|
||||
@@ -808,8 +808,10 @@ static struct tegra_smmu *tegra_smmu_find(struct device_node *np)
|
||||
return NULL;
|
||||
|
||||
mc = platform_get_drvdata(pdev);
|
||||
if (!mc)
|
||||
if (!mc) {
|
||||
put_device(&pdev->dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mc->smmu;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,8 @@ static int xilinx_nor_setup(struct spi_nor *nor,
|
||||
/* Flash in Power of 2 mode */
|
||||
nor->page_size = (nor->page_size == 264) ? 256 : 512;
|
||||
nor->mtd.writebufsize = nor->page_size;
|
||||
nor->mtd.size = 8 * nor->page_size * nor->info->n_sectors;
|
||||
nor->params->size = 8 * nor->page_size * nor->info->n_sectors;
|
||||
nor->mtd.size = nor->params->size;
|
||||
nor->mtd.erasesize = 8 * nor->page_size;
|
||||
} else {
|
||||
/* Flash in Default addressing mode */
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user