From 36b4af56727e9b0ded04d1a2a15baecb072d9da9 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 5 Dec 2023 21:16:32 +0100 Subject: [PATCH 1/2] Allwinner: u-boot: Improve DRAM size detection on H6 --- ...am-size-detection-for-some-H6-boards.patch | 46 +++++++++++++++++++ .../patches/u-boot/0014-unreliable-dram.patch | 40 ---------------- 2 files changed, 46 insertions(+), 40 deletions(-) create mode 100644 projects/Allwinner/patches/u-boot/0014-sunxi-dram-Fix-incorrect-ram-size-detection-for-some-H6-boards.patch delete mode 100644 projects/Allwinner/patches/u-boot/0014-unreliable-dram.patch diff --git a/projects/Allwinner/patches/u-boot/0014-sunxi-dram-Fix-incorrect-ram-size-detection-for-some-H6-boards.patch b/projects/Allwinner/patches/u-boot/0014-sunxi-dram-Fix-incorrect-ram-size-detection-for-some-H6-boards.patch new file mode 100644 index 0000000000..ac90fa5eab --- /dev/null +++ b/projects/Allwinner/patches/u-boot/0014-sunxi-dram-Fix-incorrect-ram-size-detection-for-some-H6-boards.patch @@ -0,0 +1,46 @@ +From: Gunjan Gupta +Subject: [PATCH 1/1] sunxi: dram: Fix incorrect ram size detection for some H6 + boards +Date: Sun, 1 Oct 2023 21:43:32 +0530 + +On some H6 boards like Orange Pi 3 LTS, some times U-Boot fails to detect +ram size correctly. Instead of 2GB thats available, it detects 4GB of ram +and then SPL just hangs there making board not to boot further. + +On debugging, I found that the rows value were being determined correctly, +but columns were sometimes off by one value. I found that adding some +delay after the mctl_core_init call along with making use of dsb in the +start of the mctl_mem_matches solves the issue. + +Signed-off-by: Gunjan Gupta +--- + + arch/arm/mach-sunxi/dram_helpers.c | 1 + + arch/arm/mach-sunxi/dram_sun50i_h6.c | 2 ++ + 2 files changed, 3 insertions(+) + +diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c +index cdf2750f1c..5758c58e07 100644 +--- a/arch/arm/mach-sunxi/dram_helpers.c ++++ b/arch/arm/mach-sunxi/dram_helpers.c +@@ -32,6 +32,7 @@ void mctl_await_completion(u32 *reg, u32 mask, u32 val) + #ifndef CONFIG_MACH_SUNIV + bool mctl_mem_matches(u32 offset) + { ++ dsb(); + /* Try to write different values to RAM at two addresses */ + writel(0, CFG_SYS_SDRAM_BASE); + writel(0xaa55aa55, (ulong)CFG_SYS_SDRAM_BASE + offset); +diff --git a/arch/arm/mach-sunxi/dram_sun50i_h6.c b/arch/arm/mach-sunxi/dram_sun50i_h6.c +index bff2e42513..a031a845f5 100644 +--- a/arch/arm/mach-sunxi/dram_sun50i_h6.c ++++ b/arch/arm/mach-sunxi/dram_sun50i_h6.c +@@ -623,6 +623,8 @@ static void mctl_auto_detect_dram_size(struct dram_para *para) + para->cols = 11; + mctl_core_init(para); + ++ udelay(50); ++ + for (para->cols = 8; para->cols < 11; para->cols++) { + /* 8 bits per byte and 16/32 bit width */ + if (mctl_mem_matches(1 << (para->cols + 1 + diff --git a/projects/Allwinner/patches/u-boot/0014-unreliable-dram.patch b/projects/Allwinner/patches/u-boot/0014-unreliable-dram.patch deleted file mode 100644 index 222c60b429..0000000000 --- a/projects/Allwinner/patches/u-boot/0014-unreliable-dram.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: megous@megous.com -Date: Mon, 29 Jul 2019 01:39:42 +0200 -Subject: [U-Boot] [PATCH] Fix unreliable detection of DRAM size on Orange Pi 3 - -From: Ondrej Jirman - -Orange Pi 3 has 2 GiB of DRAM, that sometime get misdetected -as 4 GiB, due to false negative result from mctl_mem_matches() -when detecting number of column address bits. This leads to -u-boot detecting more address bits than there are and the -boot process hangs shortly after. - -In mctl_mem_matches() we need to wait for each write to finish, -separately. Without this, the check is not reliable for some -unknown reason, probably having to do with unpredictable memory -access ordering. - -Patch was made with help from André Przywara, who noticed that -my original idea about detection failing due to read-back from -cache without involving DRAM was false, because data cache is -still of at the time of the DRAM size autodetection. - -Signed-off-by: Ondrej Jirman -Cc: André Przywara ---- - arch/arm/mach-sunxi/dram_helpers.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/arch/arm/mach-sunxi/dram_helpers.c b/arch/arm/mach-sunxi/dram_helpers.c -index 239ab421a8..6dba448638 100644 ---- a/arch/arm/mach-sunxi/dram_helpers.c -+++ b/arch/arm/mach-sunxi/dram_helpers.c -@@ -30,6 +30,7 @@ bool mctl_mem_matches(u32 offset) - { - /* Try to write different values to RAM at two addresses */ - writel(0, CONFIG_SYS_SDRAM_BASE); -+ dsb(); - writel(0xaa55aa55, (ulong)CONFIG_SYS_SDRAM_BASE + offset); - dsb(); - /* Check if the same value is actually observed when reading back */ From 9dca4851789d28b32e4f3d237987701cf5f117e6 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 5 Dec 2023 21:17:19 +0100 Subject: [PATCH 2/2] Allwinner: linux: Fix deinterlacer and H265 decoding --- ...-h265-Fix-configuring-bitstream-size.patch | 65 ++++++++ ...ia-sunxi-sun8i-di-fix-race-condition.patch | 150 ++++++++++++++++++ 2 files changed, 215 insertions(+) create mode 100644 projects/Allwinner/patches/linux/0106-media-cedrus-h265-Fix-configuring-bitstream-size.patch create mode 100644 projects/Allwinner/patches/linux/0107-wip-media-sunxi-sun8i-di-fix-race-condition.patch diff --git a/projects/Allwinner/patches/linux/0106-media-cedrus-h265-Fix-configuring-bitstream-size.patch b/projects/Allwinner/patches/linux/0106-media-cedrus-h265-Fix-configuring-bitstream-size.patch new file mode 100644 index 0000000000..b310d2e281 --- /dev/null +++ b/projects/Allwinner/patches/linux/0106-media-cedrus-h265-Fix-configuring-bitstream-size.patch @@ -0,0 +1,65 @@ +From 6fba61d436ed9d610e1001860e2fcdf2ccf96803 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Sat, 7 Oct 2023 08:36:47 +0200 +Subject: [PATCH 14/23] media: cedrus: h265: Fix configuring bitstream size + +bit_size field holds size of slice, not slice + header. Because of HW +quirks, driver can't program in just slice, but also preceeding header. +But that means that currently used bit_size is wrong (too small). +Instead, just use size of whole buffer. There is no harm in doing this. + +Fixes: 86caab29da78 ("media: cedrus: Add HEVC/H.265 decoding support") +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +index fc9297232456..16c822637dc6 100644 +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -454,11 +454,11 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + unsigned int ctb_addr_x, ctb_addr_y; + struct cedrus_buffer *cedrus_buf; + dma_addr_t src_buf_addr; +- dma_addr_t src_buf_end_addr; + u32 chroma_log2_weight_denom; + u32 num_entry_point_offsets; + u32 output_pic_list_index; + u32 pic_order_cnt[2]; ++ size_t slice_bytes; + u8 padding; + int count; + u32 reg; +@@ -468,6 +468,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + decode_params = run->h265.decode_params; + pred_weight_table = &slice_params->pred_weight_table; + num_entry_point_offsets = slice_params->num_entry_point_offsets; ++ slice_bytes = vb2_get_plane_payload(&run->src->vb2_buf, 0); + + /* + * If entry points offsets are present, we should get them +@@ -490,7 +491,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + + cedrus_write(dev, VE_DEC_H265_BITS_OFFSET, 0); + +- reg = slice_params->bit_size; ++ reg = slice_bytes * 8; + cedrus_write(dev, VE_DEC_H265_BITS_LEN, reg); + + /* Source beginning and end addresses. */ +@@ -504,10 +505,7 @@ static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run) + + cedrus_write(dev, VE_DEC_H265_BITS_ADDR, reg); + +- src_buf_end_addr = src_buf_addr + +- DIV_ROUND_UP(slice_params->bit_size, 8); +- +- reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_end_addr); ++ reg = VE_DEC_H265_BITS_END_ADDR_BASE(src_buf_addr + slice_bytes); + cedrus_write(dev, VE_DEC_H265_BITS_END_ADDR, reg); + + /* Coding tree block address */ +-- +2.42.0 + diff --git a/projects/Allwinner/patches/linux/0107-wip-media-sunxi-sun8i-di-fix-race-condition.patch b/projects/Allwinner/patches/linux/0107-wip-media-sunxi-sun8i-di-fix-race-condition.patch new file mode 100644 index 0000000000..930d16577f --- /dev/null +++ b/projects/Allwinner/patches/linux/0107-wip-media-sunxi-sun8i-di-fix-race-condition.patch @@ -0,0 +1,150 @@ +From 239ce64f28fce7cc035a857bb5ed6f51ad6795c8 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Thu, 19 Oct 2023 19:16:18 +0200 +Subject: [PATCH] wip: media: sunxi: sun8i-di: fix race condition + +Signed-off-by: Jernej Skrabec +--- + .../media/platform/sunxi/sun8i-di/sun8i-di.c | 69 ++++++++++--------- + 1 file changed, 35 insertions(+), 34 deletions(-) + +diff --git a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c +index 90ab1d77b6a5..f7ff0937828c 100644 +--- a/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c ++++ b/drivers/media/platform/sunxi/sun8i-di/sun8i-di.c +@@ -66,6 +66,7 @@ static void deinterlace_device_run(void *priv) + struct vb2_v4l2_buffer *src, *dst; + unsigned int hstep, vstep; + dma_addr_t addr; ++ int i; + + src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx); + dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx); +@@ -160,6 +161,26 @@ static void deinterlace_device_run(void *priv) + deinterlace_write(dev, DEINTERLACE_CH1_HORZ_FACT, hstep); + deinterlace_write(dev, DEINTERLACE_CH1_VERT_FACT, vstep); + ++ /* neutral filter coefficients */ ++ deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL, ++ DEINTERLACE_FRM_CTRL_COEF_ACCESS); ++ readl_poll_timeout(dev->base + DEINTERLACE_STATUS, val, ++ val & DEINTERLACE_STATUS_COEF_STATUS, 2, 40); ++ ++ for (i = 0; i < 32; i++) { ++ deinterlace_write(dev, DEINTERLACE_CH0_HORZ_COEF0 + i * 4, ++ DEINTERLACE_IDENTITY_COEF); ++ deinterlace_write(dev, DEINTERLACE_CH0_VERT_COEF + i * 4, ++ DEINTERLACE_IDENTITY_COEF); ++ deinterlace_write(dev, DEINTERLACE_CH1_HORZ_COEF0 + i * 4, ++ DEINTERLACE_IDENTITY_COEF); ++ deinterlace_write(dev, DEINTERLACE_CH1_VERT_COEF + i * 4, ++ DEINTERLACE_IDENTITY_COEF); ++ } ++ ++ deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL, ++ DEINTERLACE_FRM_CTRL_COEF_ACCESS, 0); ++ + deinterlace_clr_set_bits(dev, DEINTERLACE_FIELD_CTRL, + DEINTERLACE_FIELD_CTRL_FIELD_CNT_MSK, + DEINTERLACE_FIELD_CTRL_FIELD_CNT(ctx->field)); +@@ -248,7 +269,6 @@ static irqreturn_t deinterlace_irq(int irq, void *data) + static void deinterlace_init(struct deinterlace_dev *dev) + { + u32 val; +- int i; + + deinterlace_write(dev, DEINTERLACE_BYPASS, + DEINTERLACE_BYPASS_CSC); +@@ -284,27 +304,7 @@ static void deinterlace_init(struct deinterlace_dev *dev) + + deinterlace_clr_set_bits(dev, DEINTERLACE_CHROMA_DIFF, + DEINTERLACE_CHROMA_DIFF_TH_MSK, +- DEINTERLACE_CHROMA_DIFF_TH(5)); +- +- /* neutral filter coefficients */ +- deinterlace_set_bits(dev, DEINTERLACE_FRM_CTRL, +- DEINTERLACE_FRM_CTRL_COEF_ACCESS); +- readl_poll_timeout(dev->base + DEINTERLACE_STATUS, val, +- val & DEINTERLACE_STATUS_COEF_STATUS, 2, 40); +- +- for (i = 0; i < 32; i++) { +- deinterlace_write(dev, DEINTERLACE_CH0_HORZ_COEF0 + i * 4, +- DEINTERLACE_IDENTITY_COEF); +- deinterlace_write(dev, DEINTERLACE_CH0_VERT_COEF + i * 4, +- DEINTERLACE_IDENTITY_COEF); +- deinterlace_write(dev, DEINTERLACE_CH1_HORZ_COEF0 + i * 4, +- DEINTERLACE_IDENTITY_COEF); +- deinterlace_write(dev, DEINTERLACE_CH1_VERT_COEF + i * 4, +- DEINTERLACE_IDENTITY_COEF); +- } +- +- deinterlace_clr_set_bits(dev, DEINTERLACE_FRM_CTRL, +- DEINTERLACE_FRM_CTRL_COEF_ACCESS, 0); ++ DEINTERLACE_CHROMA_DIFF_TH(31)); + } + + static inline struct deinterlace_ctx *deinterlace_file2ctx(struct file *file) +@@ -929,11 +929,18 @@ static int deinterlace_runtime_resume(struct device *device) + return ret; + } + ++ ret = reset_control_deassert(dev->rstc); ++ if (ret) { ++ dev_err(dev->dev, "Failed to apply reset\n"); ++ ++ goto err_exclusive_rate; ++ } ++ + ret = clk_prepare_enable(dev->bus_clk); + if (ret) { + dev_err(dev->dev, "Failed to enable bus clock\n"); + +- goto err_exclusive_rate; ++ goto err_rst; + } + + ret = clk_prepare_enable(dev->mod_clk); +@@ -950,23 +957,16 @@ static int deinterlace_runtime_resume(struct device *device) + goto err_mod_clk; + } + +- ret = reset_control_deassert(dev->rstc); +- if (ret) { +- dev_err(dev->dev, "Failed to apply reset\n"); +- +- goto err_ram_clk; +- } +- + deinterlace_init(dev); + + return 0; + +-err_ram_clk: +- clk_disable_unprepare(dev->ram_clk); + err_mod_clk: + clk_disable_unprepare(dev->mod_clk); + err_bus_clk: + clk_disable_unprepare(dev->bus_clk); ++err_rst: ++ reset_control_assert(dev->rstc); + err_exclusive_rate: + clk_rate_exclusive_put(dev->mod_clk); + +@@ -977,11 +977,12 @@ static int deinterlace_runtime_suspend(struct device *device) + { + struct deinterlace_dev *dev = dev_get_drvdata(device); + +- reset_control_assert(dev->rstc); +- + clk_disable_unprepare(dev->ram_clk); + clk_disable_unprepare(dev->mod_clk); + clk_disable_unprepare(dev->bus_clk); ++ ++ reset_control_assert(dev->rstc); ++ + clk_rate_exclusive_put(dev->mod_clk); + + return 0; +-- +2.42.0 +