From a51d13fed28dc28eb69c575c660c9f1667a0a57f Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Fri, 21 Aug 2020 10:08:34 +0900 Subject: [PATCH 01/16] Revert "WORKAROUND: security: smack: Allow ptracing even processes in onlycap set" This reverts commit 38b1ae4b960c310b02d7d6935b97d289f0326800. Now crash-worker has System::Privileged privilege, so not anymore ptrace related workaround is necessary. So revert the workaround. Change-Id: I42b535e4152eb742df011a5a08324764b49f989a Signed-off-by: Seung-Woo Kim --- security/smack/smack_lsm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 7c5adf2..12c0fa8 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -442,8 +442,6 @@ static int smk_ptrace_rule_check(struct task_struct *tracer, rc = 0; else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) rc = -EACCES; - else if (smack_ptrace_rule == SMACK_PTRACE_EXACT) - rc = capable(CAP_SYS_PTRACE) != 0 ? 0 : -EACCES; else if (smack_privileged_cred(CAP_SYS_PTRACE, tracercred)) rc = 0; else -- 2.7.4 From cad4c208fb4555786244483ce0f917847677e6ef Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Mon, 3 Aug 2020 14:44:43 +0900 Subject: [PATCH 02/16] mm: memcontrol: Add force_reclaim to reclaim tasks' memory in memcg These days, platforms tend to manage memory on low memory state like andloid's lowmemory killer. These platforms might want to reclaim memory from background tasks as well as kill victims to guarantee free memory at use space level. This patch provides an interface to reclaim a given memcg. After platform's low memory handler moves tasks that the platform wants to reclaim to a memcg and decides how many pages should be reclaimed, it can reclaim the pages from the tasks by writing the number of pages at memory.force_reclaim. Signed-off-by: Hyunhee Kim Signed-off-by: Kyungmin Park [dwoo08.lee: ported from mailing list https://www.spinics.net/lists/cgroups/msg07874.html] Change-Id: I40b1322dfe2628ca306690a15958881b3026606f Signed-off-by: Dongwoo Lee --- mm/memcontrol.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/mm/memcontrol.c b/mm/memcontrol.c index a3f4c35..704e812 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -3367,6 +3367,36 @@ static ssize_t mem_cgroup_force_empty_write(struct kernfs_open_file *of, return mem_cgroup_force_empty(memcg) ?: nbytes; } +#ifdef CONFIG_MEMCG_SWAP +static int mem_cgroup_force_reclaim(struct cgroup_subsys_state *css, + struct cftype *cft, u64 val) +{ + struct mem_cgroup *memcg = mem_cgroup_from_css(css); + unsigned long nr_to_reclaim = val; + unsigned long total = 0; + int loop; + + for (loop = 0; loop < MEM_CGROUP_MAX_RECLAIM_LOOPS; loop++) { + total += try_to_free_mem_cgroup_pages(memcg, nr_to_reclaim, + GFP_KERNEL, true); + + /* + * If nothing was reclaimed after two attempts, there + * may be no reclaimable pages in this hierarchy. + * If more than nr_to_reclaim pages were already reclaimed, + * finish force reclaim. + */ + if (loop && (!total || total > nr_to_reclaim)) + break; + } + + pr_info("%s: [Mem_reclaim] Loop: %d - Total_reclaimed: %lu - nr_to_reclaim: %lu\n", + __func__, loop, total, nr_to_reclaim); + + return total; +} +#endif + static u64 mem_cgroup_hierarchy_read(struct cgroup_subsys_state *css, struct cftype *cft) { @@ -7309,6 +7339,10 @@ static struct cftype memsw_cgroup_files[] = { .write = mem_cgroup_reset, .read_u64 = mem_cgroup_read_u64, }, + { + .name = "force_reclaim", + .write_u64 = mem_cgroup_force_reclaim, + }, { }, /* terminate */ }; -- 2.7.4 From 84c7edd09cdad19c99ceec4a85ea80c51b146403 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 24 Aug 2020 11:33:04 +0900 Subject: [PATCH 03/16] ARM: tizen_bcm2711_defconfig: Enable RTL8192CU config as module Enable RTL8192CU configuration as module. Change-Id: Ibe38cc889d5e2973028b28615a2210f87056763f Signed-off-by: Jaehoon Chung --- arch/arm/configs/tizen_bcm2711_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tizen_bcm2711_defconfig b/arch/arm/configs/tizen_bcm2711_defconfig index 7557de2..565611b 100644 --- a/arch/arm/configs/tizen_bcm2711_defconfig +++ b/arch/arm/configs/tizen_bcm2711_defconfig @@ -256,6 +256,7 @@ CONFIG_RT2800USB=y CONFIG_RT2800USB_RT3573=y CONFIG_RT2800USB_RT53XX=y CONFIG_RT2800USB_RT55XX=y +CONFIG_RTL8192CU=m CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=y -- 2.7.4 From 3145de08493ffd1f1a0dd84645b69163c359c0e9 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Mon, 24 Aug 2020 11:34:08 +0900 Subject: [PATCH 04/16] ARM64: tizen_bcm2711_defconfig: Enable RTL8192CU config as module Enable RTL8192CU configuration as module. Change-Id: I4597976b08b9e1e98d61f42da674c28c5e476f10 Signed-off-by: Jaehoon Chung --- arch/arm64/configs/tizen_bcm2711_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/configs/tizen_bcm2711_defconfig b/arch/arm64/configs/tizen_bcm2711_defconfig index 5a03773..3928257 100644 --- a/arch/arm64/configs/tizen_bcm2711_defconfig +++ b/arch/arm64/configs/tizen_bcm2711_defconfig @@ -249,6 +249,7 @@ CONFIG_BRCMFMAC=m CONFIG_BRCMDBG=y CONFIG_RT2X00=y CONFIG_RT2500USB=y +CONFIG_RTL8192CU=m CONFIG_INPUT_MOUSEDEV=y CONFIG_INPUT_JOYDEV=m CONFIG_INPUT_EVDEV=y -- 2.7.4 From c574d1c74096eeab487296ed3afed630f2ae1a05 Mon Sep 17 00:00:00 2001 From: Dongwoo Lee Date: Fri, 21 Aug 2020 20:53:46 +0900 Subject: [PATCH 05/16] Revert "block: zram: Add support for dynamic compressor switch" Since dynamic compress switch increases memory usage of meta data along with the size of zram, in order to saving memory, this reverts commit '2aab8469d74f ("block: zram Add support for dynamic compressor switch")' Change-Id: Idd6e1f6f938ca2ebb24ba3e8c65a838bf8fc84d4 Signed-off-by: Dongwoo Lee --- drivers/block/zram/zcomp.c | 84 +++++++++++++------------------------------ drivers/block/zram/zcomp.h | 6 ++-- drivers/block/zram/zram_drv.c | 54 +++++++++++----------------- drivers/block/zram/zram_drv.h | 2 -- 4 files changed, 48 insertions(+), 98 deletions(-) diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c index a02f08d..1a8564a 100644 --- a/drivers/block/zram/zcomp.c +++ b/drivers/block/zram/zcomp.c @@ -63,6 +63,24 @@ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp) return zstrm; } +bool zcomp_available_algorithm(const char *comp) +{ + int i; + + i = __sysfs_match_string(backends, -1, comp); + if (i >= 0) + return true; + + /* + * Crypto does not ignore a trailing new line symbol, + * so make sure you don't supply a string containing + * one. + * This also means that we permit zcomp initialisation + * with any compressing algorithm known to crypto api. + */ + return crypto_has_comp(comp, 0, 0) == 1; +} + /* show available compressors */ ssize_t zcomp_available_show(const char *comp, char *buf) { @@ -184,43 +202,29 @@ cleanup: return ret; } -static void zcomp_destroy(struct zcomp *comp) +void zcomp_destroy(struct zcomp *comp) { cpuhp_state_remove_instance(CPUHP_ZCOMP_PREPARE, &comp->node); free_percpu(comp->stream); kfree(comp); } -void zcomp_reset(struct list_head *blist) -{ - struct list_head *curr, *next; - struct zcomp *comp; - int i; - - list_for_each_safe(curr, next, blist) { - comp = list_entry(curr, struct zcomp, list); - list_del(&comp->list); - - i = __sysfs_match_string(backends, -1, comp->name); - if (i < 0) - kfree(comp->name); - - zcomp_destroy(comp); - } -} - /* + * search available compressors for requested algorithm. * allocate new zcomp and initialize it. return compressing * backend pointer or ERR_PTR if things went bad. ERR_PTR(-EINVAL) * if requested algorithm is not supported, ERR_PTR(-ENOMEM) in * case of allocation error, or any other error potentially * returned by zcomp_init(). */ -static struct zcomp *zcomp_create(const char *compress) +struct zcomp *zcomp_create(const char *compress) { struct zcomp *comp; int error; + if (!zcomp_available_algorithm(compress)) + return ERR_PTR(-EINVAL); + comp = kzalloc(sizeof(struct zcomp), GFP_KERNEL); if (!comp) return ERR_PTR(-ENOMEM); @@ -233,43 +237,3 @@ static struct zcomp *zcomp_create(const char *compress) } return comp; } - -struct zcomp *zcomp_get_instance(struct list_head *blist, const char *name) -{ - struct zcomp *comp; - const char *comp_name = NULL; - int i; - - list_for_each_entry(comp, blist, list) - if (sysfs_streq(name, comp->name)) - return comp; - - i = __sysfs_match_string(backends, -1, name); - if (i >= 0) - comp_name = backends[i]; - else { - /* - * Crypto does not ignore a trailing new line symbol, - * so make sure you don't supply a string containing - * one. - * This also means that we permit zcomp initialisation - * with any compressing algorithm known to crypto api. - */ - if (crypto_has_comp(name, 0, 0) == 1) - comp_name = kstrdup(name, GFP_KERNEL); - else - return ERR_PTR(-ENOENT); - } - - comp = zcomp_create(comp_name); - if (IS_ERR(comp)) { - pr_err("Cannot initialise %s compressing backend\n", name); - if (i < 0) - kfree(comp_name); - return comp; - } - - list_add(&comp->list, blist); - - return comp; -} diff --git a/drivers/block/zram/zcomp.h b/drivers/block/zram/zcomp.h index aff688d..1806475 100644 --- a/drivers/block/zram/zcomp.h +++ b/drivers/block/zram/zcomp.h @@ -17,15 +17,15 @@ struct zcomp { struct zcomp_strm * __percpu *stream; const char *name; struct hlist_node node; - struct list_head list; }; int zcomp_cpu_up_prepare(unsigned int cpu, struct hlist_node *node); int zcomp_cpu_dead(unsigned int cpu, struct hlist_node *node); ssize_t zcomp_available_show(const char *comp, char *buf); +bool zcomp_available_algorithm(const char *comp); -struct zcomp *zcomp_get_instance(struct list_head *blist, const char *name); -void zcomp_reset(struct list_head *blist); +struct zcomp *zcomp_create(const char *comp); +void zcomp_destroy(struct zcomp *comp); struct zcomp_strm *zcomp_stream_get(struct zcomp *comp); void zcomp_stream_put(struct zcomp *comp); diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c index 6335e66..1bf4a90 100644 --- a/drivers/block/zram/zram_drv.c +++ b/drivers/block/zram/zram_drv.c @@ -121,17 +121,6 @@ static unsigned long zram_get_element(struct zram *zram, u32 index) return zram->table[index].element; } -static inline void zram_set_compressor(struct zram *zram, u32 index, - struct zcomp *comp) -{ - zram->table[index].compressor = comp; -} - -static struct zcomp *zram_get_compressor(struct zram *zram, u32 index) -{ - return zram->table[index].compressor; -} - static size_t zram_get_obj_size(struct zram *zram, u32 index) { return zram->table[index].flags & (BIT(ZRAM_FLAG_SHIFT) - 1); @@ -996,7 +985,6 @@ static ssize_t comp_algorithm_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { struct zram *zram = dev_to_zram(dev); - struct zcomp *comp; char compressor[ARRAY_SIZE(zram->compressor)]; size_t sz; @@ -1006,12 +994,16 @@ static ssize_t comp_algorithm_store(struct device *dev, if (sz > 0 && compressor[sz - 1] == '\n') compressor[sz - 1] = 0x00; - comp = zcomp_get_instance(&zram->backend_list, compressor); - if (IS_ERR_OR_NULL(comp)) + if (!zcomp_available_algorithm(compressor)) return -EINVAL; down_write(&zram->init_lock); - zram->comp = comp; + if (init_done(zram)) { + up_write(&zram->init_lock); + pr_info("Can't change algorithm for initialized device\n"); + return -EBUSY; + } + strcpy(zram->compressor, compressor); up_write(&zram->init_lock); return len; @@ -1206,7 +1198,6 @@ static void zram_free_page(struct zram *zram, size_t index) return; zs_free(zram->mem_pool, handle); - zram->table[index].compressor = NULL; atomic64_sub(zram_get_obj_size(zram, index), &zram->stats.compr_data_size); @@ -1262,13 +1253,12 @@ static int __zram_bvec_read(struct zram *zram, struct page *page, u32 index, kunmap_atomic(dst); ret = 0; } else { - struct zcomp *comp = zram_get_compressor(zram, index); - struct zcomp_strm *zstrm = zcomp_stream_get(comp); + struct zcomp_strm *zstrm = zcomp_stream_get(zram->comp); dst = kmap_atomic(page); ret = zcomp_decompress(zstrm, src, size, dst); kunmap_atomic(dst); - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); } zs_unmap_object(zram->mem_pool, handle); zram_slot_unlock(zram, index); @@ -1322,7 +1312,6 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, unsigned int comp_len = 0; void *src, *dst, *mem; struct zcomp_strm *zstrm; - struct zcomp *comp = NULL; struct page *page = bvec->bv_page; unsigned long element = 0; enum zram_pageflags flags = 0; @@ -1338,14 +1327,13 @@ static int __zram_bvec_write(struct zram *zram, struct bio_vec *bvec, kunmap_atomic(mem); compress_again: - comp = zram->comp; - zstrm = zcomp_stream_get(comp); + zstrm = zcomp_stream_get(zram->comp); src = kmap_atomic(page); ret = zcomp_compress(zstrm, src, &comp_len); kunmap_atomic(src); if (unlikely(ret)) { - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); pr_err("Compression failed! err=%d\n", ret); zs_free(zram->mem_pool, handle); return ret; @@ -1373,7 +1361,7 @@ compress_again: __GFP_HIGHMEM | __GFP_MOVABLE); if (!handle) { - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); atomic64_inc(&zram->stats.writestall); handle = zs_malloc(zram->mem_pool, comp_len, GFP_NOIO | __GFP_HIGHMEM | @@ -1387,7 +1375,7 @@ compress_again: update_used_max(zram, alloced_pages); if (zram->limit_pages && alloced_pages > zram->limit_pages) { - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); zs_free(zram->mem_pool, handle); return -ENOMEM; } @@ -1401,7 +1389,7 @@ compress_again: if (comp_len == PAGE_SIZE) kunmap_atomic(src); - zcomp_stream_put(comp); + zcomp_stream_put(zram->comp); zs_unmap_object(zram->mem_pool, handle); atomic64_add(comp_len, &zram->stats.compr_data_size); out: @@ -1423,8 +1411,6 @@ out: } else { zram_set_handle(zram, index, handle); zram_set_obj_size(zram, index, comp_len); - if (comp_len < PAGE_SIZE) - zram_set_compressor(zram, index, comp); } zram_slot_unlock(zram, index); @@ -1689,6 +1675,7 @@ out: static void zram_reset_device(struct zram *zram) { + struct zcomp *comp; u64 disksize; down_write(&zram->init_lock); @@ -1700,6 +1687,7 @@ static void zram_reset_device(struct zram *zram) return; } + comp = zram->comp; disksize = zram->disksize; zram->disksize = 0; @@ -1710,8 +1698,7 @@ static void zram_reset_device(struct zram *zram) /* I/O operation under all of CPU are done so let's free */ zram_meta_free(zram, disksize); memset(&zram->stats, 0, sizeof(zram->stats)); - zram->comp = NULL; - zcomp_reset(&zram->backend_list); + zcomp_destroy(comp); reset_bdev(zram); } @@ -1740,8 +1727,10 @@ static ssize_t disksize_store(struct device *dev, goto out_unlock; } - comp = zcomp_get_instance(&zram->backend_list, zram->compressor); - if (IS_ERR_OR_NULL(comp)) { + comp = zcomp_create(zram->compressor); + if (IS_ERR(comp)) { + pr_err("Cannot initialise %s compressing backend\n", + zram->compressor); err = PTR_ERR(comp); goto out_free_meta; } @@ -1964,7 +1953,6 @@ static int zram_add(void) device_add_disk(NULL, zram->disk, zram_disk_attr_groups); strlcpy(zram->compressor, default_compressor, sizeof(zram->compressor)); - INIT_LIST_HEAD(&zram->backend_list); zram_debugfs_register(zram); pr_info("Added device: %s\n", zram->disk->disk_name); diff --git a/drivers/block/zram/zram_drv.h b/drivers/block/zram/zram_drv.h index 83b320f..f2fd46d 100644 --- a/drivers/block/zram/zram_drv.h +++ b/drivers/block/zram/zram_drv.h @@ -63,7 +63,6 @@ struct zram_table_entry { unsigned long element; }; unsigned long flags; - struct zcomp *compressor; #ifdef CONFIG_ZRAM_MEMORY_TRACKING ktime_t ac_time; #endif @@ -113,7 +112,6 @@ struct zram { * zram is claimed so open request will be failed */ bool claim; /* Protected by bdev->bd_mutex */ - struct list_head backend_list; struct file *backing_dev; #ifdef CONFIG_ZRAM_WRITEBACK spinlock_t wb_limit_lock; -- 2.7.4 From d9cbf6ebd428f00a5ca5655d6fdc03504bbceed0 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 10 Sep 2020 13:25:20 +0900 Subject: [PATCH 06/16] ARM: configs: tizen_bcm2711_defconfig: Enable VIDEO_CODEC_BCM2835 To support v4l2 codec device, enable VIDEO_CODEC_BCM2835. Change-Id: I7f7147901b77b3ff01afc1a7c3c7f0ab9cc20701 Signed-off-by: Seung-Woo Kim --- arch/arm/configs/tizen_bcm2711_defconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/configs/tizen_bcm2711_defconfig b/arch/arm/configs/tizen_bcm2711_defconfig index 565611b..167c914 100644 --- a/arch/arm/configs/tizen_bcm2711_defconfig +++ b/arch/arm/configs/tizen_bcm2711_defconfig @@ -419,6 +419,7 @@ CONFIG_STAGING_MEDIA=y CONFIG_ANDROID_LOGGER=y CONFIG_SND_BCM2835=y CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_CODEC_BCM2835=y CONFIG_CLK_RASPBERRYPI=y CONFIG_MAILBOX=y CONFIG_BCM2835_MBOX=y -- 2.7.4 From 1f214bbbe0819ae7bb4e9ba4384ede5c974c985d Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 10 Sep 2020 13:28:11 +0900 Subject: [PATCH 07/16] ARM64: tizen_bcm2711_defconfig: Enable VIDEO_CODEC_BCM2835 To support v4l2 codec device, enable VIDEO_CODEC_BCM2835 and to meet dependency, enable MEDIA_CONTROLLER. Change-Id: Id473825163c409ceaab5d4b618cf8bddd6af0f68 Signed-off-by: Seung-Woo Kim --- arch/arm64/configs/tizen_bcm2711_defconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/configs/tizen_bcm2711_defconfig b/arch/arm64/configs/tizen_bcm2711_defconfig index 3928257..de8a7cf 100644 --- a/arch/arm64/configs/tizen_bcm2711_defconfig +++ b/arch/arm64/configs/tizen_bcm2711_defconfig @@ -322,6 +322,7 @@ CONFIG_MEDIA_SUPPORT=y CONFIG_MEDIA_CAMERA_SUPPORT=y CONFIG_MEDIA_ANALOG_TV_SUPPORT=y CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_CONTROLLER=y CONFIG_MEDIA_USB_SUPPORT=y CONFIG_USB_VIDEO_CLASS=y CONFIG_USB_GSPCA_ZC3XX=m @@ -406,6 +407,7 @@ CONFIG_STAGING_MEDIA=y CONFIG_ANDROID_LOGGER=y CONFIG_SND_BCM2835=y CONFIG_VIDEO_BCM2835=y +CONFIG_VIDEO_CODEC_BCM2835=y CONFIG_CLK_RASPBERRYPI=y CONFIG_MAILBOX=y CONFIG_BCM2835_MBOX=y -- 2.7.4 From d2ead75e526d98aa4a838f2e9b66f8114eaca3fa Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 24 Aug 2020 19:56:15 +0900 Subject: [PATCH 08/16] drm/vc4: encoder: Add finer-grained encoder callbacks In the BCM2711, the setup of the HVS, pixelvalve and HDMI controller requires very precise ordering and timing that the regular atomic callbacks don't provide. Let's add new callbacks on top of the regular ones to be able to split the configuration as needed. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/1dd78efe8f29add73c97d0148cfd4ec8e34aaf22.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: For use encoder callback, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I16a1a59ad753d7c4e211c24a3563a607faa03a5c --- drivers/gpu/drm/vc4/vc4_crtc.c | 19 +++++++++++++++++++ drivers/gpu/drm/vc4/vc4_drv.h | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 7925b7d..129cf90a 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -495,6 +495,8 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(old_state); u32 chan = vc4_crtc_state->assigned_channel; + struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); int ret; require_hvs_enabled(dev); @@ -506,6 +508,9 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, ret = wait_for(!(CRTC_READ(PV_V_CONTROL) & PV_VCONTROL_VIDEN), 1); WARN_ONCE(ret, "Timeout waiting for !PV_VCONTROL_VIDEN\n"); + if (vc4_encoder->post_crtc_disable) + vc4_encoder->post_crtc_disable(encoder); + CRTC_WRITE(PV_CONTROL, CRTC_READ(PV_CONTROL) & ~PV_CONTROL_EN); if (HVS_READ(SCALER_DISPCTRLX(chan)) & @@ -531,6 +536,9 @@ static void vc4_crtc_atomic_disable(struct drm_crtc *crtc, (SCALER_DISPSTATX_FULL | SCALER_DISPSTATX_EMPTY)) != SCALER_DISPSTATX_EMPTY); + if (vc4_encoder->post_crtc_powerdown) + vc4_encoder->post_crtc_powerdown(encoder); + /* * Make sure we issue a vblank event after disabling the CRTC if * someone was waiting it. @@ -592,6 +600,8 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, struct vc4_crtc_state *vc4_state = to_vc4_crtc_state(crtc->state); struct drm_display_mode *mode = &crtc->state->adjusted_mode; u32 dispctrl; + struct drm_encoder *encoder = vc4_get_crtc_encoder(crtc); + struct vc4_encoder *vc4_encoder = to_vc4_encoder(encoder); require_hvs_enabled(dev); @@ -627,14 +637,23 @@ static void vc4_crtc_atomic_enable(struct drm_crtc *crtc, (vc4_state->feed_txp ? SCALER5_DISPCTRLX_ONESHOT : 0); + if (vc4_encoder->pre_crtc_configure) + vc4_encoder->pre_crtc_configure(encoder); + HVS_WRITE(SCALER_DISPCTRLX(vc4_state->assigned_channel), dispctrl); + if (vc4_encoder->pre_crtc_enable) + vc4_encoder->pre_crtc_enable(encoder); + /* When feeding the transposer block the pixelvalve is unneeded and * should not be enabled. */ if (!vc4_state->feed_txp) CRTC_WRITE(PV_V_CONTROL, CRTC_READ(PV_V_CONTROL) | PV_VCONTROL_VIDEN); + + if (vc4_encoder->post_crtc_enable) + vc4_encoder->post_crtc_enable(encoder); } static enum drm_mode_status vc4_crtc_mode_valid(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index afdf477..9273595 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -440,6 +440,13 @@ struct vc4_encoder { struct drm_encoder base; enum vc4_encoder_type type; u32 clock_select; + + void (*pre_crtc_configure)(struct drm_encoder *encoder); + void (*pre_crtc_enable)(struct drm_encoder *encoder); + void (*post_crtc_enable)(struct drm_encoder *encoder); + + void (*post_crtc_disable)(struct drm_encoder *encoder); + void (*post_crtc_powerdown)(struct drm_encoder *encoder); }; static inline struct vc4_encoder * -- 2.7.4 From fb91e38e8069c7b592767a33f436f0d4ea7a9d34 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 15:53:28 +0900 Subject: [PATCH 09/16] drm/vc4: hdmi: Add reset callback The BCM2711 and BCM283x HDMI controllers use a slightly different reset sequence, so let's add a callback to reset the controller. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/a34bcb493da07eae58ed704f65e72ce0748e8952.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Apply the missing code, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: If0383cb9b5f8ba5d3f309bfeab3e3c74272d8723 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index da9fce5..77c05ae 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -97,6 +97,12 @@ static int vc4_hdmi_debugfs_regs(struct seq_file *m, void *unused) static void vc4_hdmi_reset(struct vc4_hdmi *vc4_hdmi) { + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); + udelay(1); + HDMI_WRITE(HDMI_M_CTL, 0); + + HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); + HDMI_WRITE(HDMI_SW_RESET_CONTROL, VC4_HDMI_SW_RESET_HDMI | VC4_HDMI_SW_RESET_FORMAT_DETECT); @@ -1757,14 +1763,6 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) vc4_hdmi->hpd_active_low = hpd_gpio_flags & OF_GPIO_ACTIVE_LOW; } - /* HDMI core must be enabled. */ - if (!(HDMI_READ(HDMI_M_CTL) & VC4_HD_M_ENABLE)) { - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_SW_RST); - udelay(1); - HDMI_WRITE(HDMI_M_CTL, 0); - - HDMI_WRITE(HDMI_M_CTL, VC4_HD_M_ENABLE); - } pm_runtime_enable(dev); drm_encoder_init(drm, encoder, &vc4_hdmi_encoder_funcs, -- 2.7.4 From 11b503d4d3c574fd920243a5f35d8de1974bd96b Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 17:31:56 +0900 Subject: [PATCH 10/16] drm/vc4: hdmi: Adjust HSM clock rate depending on pixel rate The HSM clock needs to be setup at around 101% of the pixel rate. This was done previously by setting the clock rate to 163.7MHz at probe time and only check in mode_valid whether the mode pixel clock was under the pixel clock +1% or not. However, with 4k we need to change that frequency to a higher frequency than 163.7MHz, and yet want to have the lowest clock as possible to have a decent power saving. Let's change that logic a bit by setting the clock rate of the HSM clock to the pixel rate at encoder_enable time. This would work for the BCM2711 that support 4k resolutions and has a clock that can provide it, but we still have to take care of a 4k panel plugged on a BCM283x SoCs that wouldn't be able to use those modes, so let's define the limit in the variant. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/7e692ddc231d33dd671e70ea04dd1dcf56c1ecb3.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Applied missing code, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I43328575d59a0bbccac8d4153ac5ed54f029550b --- drivers/gpu/drm/vc4/vc4_hdmi.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 77c05ae..1c20561 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -612,7 +612,23 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) return; } - hsm_rate = vc4_hdmi->variant->calc_hsm_clock(vc4_hdmi, pixel_rate); + /* + * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must + * be faster than pixel clock, infinitesimally faster, tested in + * simulation. Otherwise, exact value is unimportant for HDMI + * operation." This conflicts with bcm2835's vc4 documentation, which + * states HSM's clock has to be at least 108% of the pixel clock. + * + * Real life tests reveal that vc4's firmware statement holds up, and + * users are able to use pixel clocks closer to HSM's, namely for + * 1920x1200@60Hz. So it was decided to have leave a 1% margin between + * both clocks. Which, for RPi0-3 implies a maximum pixel clock of + * 162MHz. + * + * Additionally, the AXI clock needs to be at least 25% of + * pixel clock, but HSM ends up being the limiting factor. + */ + hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); @@ -757,22 +773,6 @@ static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) { - /* - * As stated in RPi's vc4 firmware "HDMI state machine (HSM) clock must - * be faster than pixel clock, infinitesimally faster, tested in - * simulation. Otherwise, exact value is unimportant for HDMI - * operation." This conflicts with bcm2835's vc4 documentation, which - * states HSM's clock has to be at least 108% of the pixel clock. - * - * Real life tests reveal that vc4's firmware statement holds up, and - * users are able to use pixel clocks closer to HSM's, namely for - * 1920x1200@60Hz. So it was decided to have leave a 1% margin between - * both clocks. Which, for RPi0-3 implies a maximum pixel clock of - * 162MHz. - * - * Additionally, the AXI clock needs to be at least 25% of - * pixel clock, but HSM ends up being the limiting factor. - */ struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) @@ -794,7 +794,7 @@ static u32 vc4_hdmi_get_hsm_clock(struct vc4_hdmi *vc4_hdmi) static u32 vc5_hdmi_get_hsm_clock(struct vc4_hdmi *vc4_hdmi) { - return 108000000; + return 120000000; } static u32 vc4_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate) @@ -815,7 +815,7 @@ static u32 vc5_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixe * Use 101% as this is what the firmware uses. */ - return max_t(unsigned long, 108000000, (pixel_rate / 100) * 101); + return max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); } static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask) -- 2.7.4 From d0a23476008384650b5d08111f456649bf425df3 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:07:16 +0900 Subject: [PATCH 11/16] drm/vc4: hdmi: Use clk_set_min_rate instead The HSM clock needs to be running at 101% the pixel clock of the HDMI controller, however it's shared between the two HDMI controllers, which means that if the resolutions are different between the two HDMI controllers, and the lowest resolution is on the second (in enable order) controller, the first HDMI controller will end up with a smaller than expected clock rate. Since we don't really need an exact frequency there, we can simply change the minimum rate we expect instead. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/821992209cc0d7a83254bf26fe2bf507ef0994d2.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I5666bf89beb6bada919b279846e5c204fabd0ffc --- drivers/gpu/drm/vc4/vc4_hdmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 1c20561..61f6279 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -629,7 +629,7 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) * pixel clock, but HSM ends up being the limiting factor. */ hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); - ret = clk_set_rate(vc4_hdmi->hsm_clock, hsm_rate); + ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); return; -- 2.7.4 From b41b24ecdc754277251c07bacd03982651a70e7a Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:18:19 +0900 Subject: [PATCH 12/16] drm/vc4: hdmi: Remove register dumps in enable The current code has some logic, disabled by default, to dump the register setup in the HDMI controller. However, since we're going to split those functions in multiple, shorter, functions that only make sense where they are called in sequence, keeping the register dump makes little sense. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/c8c8d388f2d32fc3536336be36d003a862487eb7.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Remove hdmi reg dumps, needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I8048f58783639cf790c8bb691007099943733a71 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 61f6279..7548431 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -589,7 +589,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); - bool debug_dump_regs = false; unsigned long pixel_rate, hsm_rate; int ret; @@ -665,14 +664,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) if (vc4_hdmi->variant->phy_init) vc4_hdmi->variant->phy_init(vc4_hdmi, mode); - if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); - - dev_info(&vc4_hdmi->pdev->dev, "HDMI regs before:\n"); - drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); - drm_print_regset32(&p, &vc4_hdmi->hd_regset); - } - HDMI_WRITE(HDMI_VID_CTL, 0); HDMI_WRITE(HDMI_SCHEDULER_CONTROL, @@ -698,14 +689,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); - if (debug_dump_regs) { - struct drm_printer p = drm_info_printer(&vc4_hdmi->pdev->dev); - - dev_info(&vc4_hdmi->pdev->dev, "HDMI regs after:\n"); - drm_print_regset32(&p, &vc4_hdmi->hdmi_regset); - drm_print_regset32(&p, &vc4_hdmi->hd_regset); - } - HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_ENABLE | -- 2.7.4 From e191c6f5f87b90c2044912afa9e70e5a35367fe5 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:21:50 +0900 Subject: [PATCH 13/16] drm/vc4: hdmi: Always recenter the HDMI FIFO In order to avoid a pixel getting stuck in an unflushable FIFO, we need to recenter the FIFO every time we're doing a modeset and not only if we're connected to an HDMI monitor. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/b3faaf05ac6c4d3c364d28fa441571eb85903269.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: Ife295f612fb32ef2a02e1494c3a4b532735c989e --- drivers/gpu/drm/vc4/vc4_hdmi.c | 46 ++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 7548431..f8144aa 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -584,6 +584,30 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_CLOCK_STOP, 0); } +static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) +{ + u32 drift; + int ret; + + drift = HDMI_READ(HDMI_FIFO_CTL); + drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; + + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + usleep_range(1000, 1100); + HDMI_WRITE(HDMI_FIFO_CTL, + drift & ~VC4_HDMI_FIFO_CTL_RECENTER); + HDMI_WRITE(HDMI_FIFO_CTL, + drift | VC4_HDMI_FIFO_CTL_RECENTER); + + ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & + VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); + WARN_ONCE(ret, "Timeout waiting for " + "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); +} + static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; @@ -719,8 +743,6 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } if (vc4_encoder->hdmi_monitor) { - u32 drift; - WARN_ON(!(HDMI_READ(HDMI_SCHEDULER_CONTROL) & VC4_HDMI_SCHEDULER_CONTROL_HDMI_ACTIVE)); HDMI_WRITE(HDMI_SCHEDULER_CONTROL, @@ -731,25 +753,9 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) VC4_HDMI_RAM_PACKET_ENABLE); vc4_hdmi_set_infoframes(encoder); - - drift = HDMI_READ(HDMI_FIFO_CTL); - drift &= VC4_HDMI_FIFO_VALID_WRITE_MASK; - - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - usleep_range(1000, 1100); - HDMI_WRITE(HDMI_FIFO_CTL, - drift & ~VC4_HDMI_FIFO_CTL_RECENTER); - HDMI_WRITE(HDMI_FIFO_CTL, - drift | VC4_HDMI_FIFO_CTL_RECENTER); - - ret = wait_for(HDMI_READ(HDMI_FIFO_CTL) & - VC4_HDMI_FIFO_CTL_RECENTER_DONE, 1); - WARN_ONCE(ret, "Timeout waiting for " - "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); } + + vc4_hdmi_recenter_fifo(vc4_hdmi); } static enum drm_mode_status -- 2.7.4 From 489ac6bc9de2adc1ff7a648ea18b6d8bcf081d7c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:26:58 +0900 Subject: [PATCH 14/16] drm/vc4: hdmi: Implement finer-grained hooks In order to prevent some pixels getting stuck in an unflushable FIFO on bcm2711, we need to enable the HVS, the pixelvalve (the CRTC) and the HDMI controller (the encoder) in an intertwined way, and with tight delays. However, the atomic callbacks don't really provide a way to work with either constraints, so we need to roll our own callbacks so that we can provide those guarantees. Since those callbacks have been implemented and called in the CRTC code, we can just implement them in the HDMI driver now. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/2e9226d971117065f3b97e597f04f7fe2f0c134c.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: Ice9a866f353d8e478e8f24c66b6e2e836e474817 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index f8144aa..188f2fb 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -387,12 +387,17 @@ static void vc4_hdmi_set_infoframes(struct drm_encoder *encoder) vc4_hdmi_set_audio_infoframe(encoder); } -static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) +static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - int ret; HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); +} + +static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + int ret; if (vc4_hdmi->variant->phy_disable) vc4_hdmi->variant->phy_disable(vc4_hdmi); @@ -409,6 +414,10 @@ static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) DRM_ERROR("Failed to release power domain: %d\n", ret); } +static void vc4_hdmi_encoder_disable(struct drm_encoder *encoder) +{ +} + static void vc4_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, bool enable) { u32 csc_ctl; @@ -608,11 +617,10 @@ static void vc4_hdmi_recenter_fifo(struct vc4_hdmi *vc4_hdmi) "VC4_HDMI_FIFO_CTL_RECENTER_DONE"); } -static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) { struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); unsigned long pixel_rate, hsm_rate; int ret; @@ -697,6 +705,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) if (vc4_hdmi->variant->set_timings) vc4_hdmi->variant->set_timings(vc4_hdmi, mode); +} + +static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder) +{ + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; + struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); if (vc4_encoder->hdmi_monitor && drm_default_rgb_quant_range(mode) == HDMI_QUANTIZATION_RANGE_LIMITED) { @@ -712,6 +727,13 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) } HDMI_WRITE(HDMI_FIFO_CTL, VC4_HDMI_FIFO_CTL_MASTER_SLAVE_N); +} + +static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) +{ + struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + int ret; HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | @@ -758,6 +780,10 @@ static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) vc4_hdmi_recenter_fifo(vc4_hdmi); } +static void vc4_hdmi_encoder_enable(struct drm_encoder *encoder) +{ +} + static enum drm_mode_status vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display_mode *mode) @@ -1699,6 +1725,12 @@ static int vc4_hdmi_bind(struct device *dev, struct device *master, void *data) variant = of_device_get_match_data(dev); vc4_hdmi->variant = variant; vc4_hdmi->encoder.base.type = variant->id ? VC4_ENCODER_TYPE_HDMI1 : VC4_ENCODER_TYPE_HDMI0; + vc4_hdmi->encoder.base.pre_crtc_configure = vc4_hdmi_encoder_pre_crtc_configure; + vc4_hdmi->encoder.base.pre_crtc_enable = vc4_hdmi_encoder_pre_crtc_enable; + vc4_hdmi->encoder.base.post_crtc_enable = vc4_hdmi_encoder_post_crtc_enable; + vc4_hdmi->encoder.base.post_crtc_disable = vc4_hdmi_encoder_post_crtc_disable; + vc4_hdmi->encoder.base.post_crtc_powerdown = vc4_hdmi_encoder_post_crtc_powerdown; + encoder = &vc4_hdmi->encoder.base.base; ret = variant->init_resources(vc4_hdmi); -- 2.7.4 From 521cd5ed95e44648b8ae5d1e81f3af9bc6c0f3fd Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:39:06 +0900 Subject: [PATCH 15/16] drm/vc4: hdmi: Do the VID_CTL configuration at once The VID_CTL setup is done in several places in the driver even though it's not really required. Let's simplify it a bit to do the configuration in one go. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/08e7ebb605a560fcc149b69b4af52753a7870b2f.1599120059.git-series.maxime@cerno.tech [cw00.choi: Apply it to both vc4_hdmi_set_timings and vc5_hdmi_set_timings, needed to troubleshoot page flip timed out issue.] Signed-off-by: Chanwoo Choi Signed-off-by: Hoegeun Kwon Change-Id: I3b12049c9bfb69d5d21c7186b677e8e32d756959 --- drivers/gpu/drm/vc4/vc4_hdmi.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 188f2fb..1084623 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -535,10 +535,6 @@ static void vc4_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); - - HDMI_WRITE(HDMI_VID_CTL, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); } static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, @@ -586,10 +582,6 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); - HDMI_WRITE(HDMI_VID_CTL, - (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | - (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); - HDMI_WRITE(HDMI_CLOCK_STOP, 0); } @@ -696,8 +688,6 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder) if (vc4_hdmi->variant->phy_init) vc4_hdmi->variant->phy_init(vc4_hdmi, mode); - HDMI_WRITE(HDMI_VID_CTL, 0); - HDMI_WRITE(HDMI_SCHEDULER_CONTROL, HDMI_READ(HDMI_SCHEDULER_CONTROL) | VC4_HDMI_SCHEDULER_CONTROL_MANUAL_FORMAT | @@ -731,15 +721,19 @@ static void vc4_hdmi_encoder_pre_crtc_enable(struct drm_encoder *encoder) static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) { + struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct vc4_hdmi_encoder *vc4_encoder = to_vc4_hdmi_encoder(encoder); + bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; + bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; int ret; HDMI_WRITE(HDMI_VID_CTL, - HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_ENABLE | VC4_HD_VID_CTL_UNDERFLOW_ENABLE | - VC4_HD_VID_CTL_FRAME_COUNTER_RESET); + VC4_HD_VID_CTL_FRAME_COUNTER_RESET | + (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | + (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); if (vc4_encoder->hdmi_monitor) { HDMI_WRITE(HDMI_SCHEDULER_CONTROL, -- 2.7.4 From 6a01bb354aecde44c192fed5475cac30542ae56f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 25 Aug 2020 18:44:04 +0900 Subject: [PATCH 16/16] drm/vc4: hdmi: Switch to blank pixels when disabled In order to avoid pixels getting stuck in an unflushable FIFO, we need when we disable the HDMI controller to switch away from getting our pixels from the pixelvalve and instead use blank pixels, and switch back to the pixelvalve when we enable the HDMI controller. Signed-off-by: Maxime Ripard Tested-by: Chanwoo Choi Tested-by: Hoegeun Kwon Tested-by: Stefan Wahren Reviewed-by: Dave Stevenson Link: https://patchwork.freedesktop.org/patch/msgid/fde3efb1ad79f4476a73d310cbba3ec07dc6dabe.1599120059.git-series.maxime@cerno.tech [hoegeun.kwon: Needed to troubleshoot page flip timed out issue.] Signed-off-by: Hoegeun Kwon Change-Id: I497f96e6d9b535d9d173d486fe1829c30093d88f --- drivers/gpu/drm/vc4/vc4_hdmi.c | 9 +++++++++ drivers/gpu/drm/vc4/vc4_regs.h | 3 +++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 1084623..4c10427 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -392,6 +392,12 @@ static void vc4_hdmi_encoder_post_crtc_disable(struct drm_encoder *encoder) struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); HDMI_WRITE(HDMI_RAM_PACKET_CONFIG, 0); + + HDMI_WRITE(HDMI_VID_CTL, HDMI_READ(HDMI_VID_CTL) | + VC4_HD_VID_CTL_CLRRGB | VC4_HD_VID_CTL_CLRSYNC); + + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) | VC4_HD_VID_CTL_BLANKPIX); } static void vc4_hdmi_encoder_post_crtc_powerdown(struct drm_encoder *encoder) @@ -735,6 +741,9 @@ static void vc4_hdmi_encoder_post_crtc_enable(struct drm_encoder *encoder) (vsync_pos ? 0 : VC4_HD_VID_CTL_VSYNC_LOW) | (hsync_pos ? 0 : VC4_HD_VID_CTL_HSYNC_LOW)); + HDMI_WRITE(HDMI_VID_CTL, + HDMI_READ(HDMI_VID_CTL) & ~VC4_HD_VID_CTL_BLANKPIX); + if (vc4_encoder->hdmi_monitor) { HDMI_WRITE(HDMI_SCHEDULER_CONTROL, HDMI_READ(HDMI_SCHEDULER_CONTROL) | diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 4d01757..c14ee209 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -732,6 +732,9 @@ # define VC4_HD_VID_CTL_FRAME_COUNTER_RESET BIT(29) # define VC4_HD_VID_CTL_VSYNC_LOW BIT(28) # define VC4_HD_VID_CTL_HSYNC_LOW BIT(27) +# define VC4_HD_VID_CTL_CLRSYNC BIT(24) +# define VC4_HD_VID_CTL_CLRRGB BIT(23) +# define VC4_HD_VID_CTL_BLANKPIX BIT(18) # define VC4_HD_CSC_CTL_ORDER_MASK VC4_MASK(7, 5) # define VC4_HD_CSC_CTL_ORDER_SHIFT 5 -- 2.7.4