Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/omap: fix TILER on OMAP5

On OMAP5 it is not possible to use TILER buffer with CPU when caching or
write-combining is used. Doing so leads to errors from the memory
manager.

However, on OMAP4, write-combining works fine.

This patch adds platform specific data for the TILER, and a function
tiler_get_cpu_cache_flags() which can be used to get the caching mode to
be used.

Note that without write-combining the use of the TILER buffer with CPU
is unusably slow. It's still good to have it operational for testing
purposes.

Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>

+46 -4
+6
drivers/gpu/drm/omapdrm/omap_dmm_priv.h
··· 153 153 struct list_head idle_node; 154 154 }; 155 155 156 + struct dmm_platform_data { 157 + uint32_t cpu_cache_flags; 158 + }; 159 + 156 160 struct dmm { 157 161 struct device *dev; 158 162 void __iomem *base; ··· 187 183 188 184 /* allocation list and lock */ 189 185 struct list_head alloc_head; 186 + 187 + const struct dmm_platform_data *plat_data; 190 188 }; 191 189 192 190 #endif
+37 -2
drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
··· 39 39 static struct tcm *containers[TILFMT_NFORMATS]; 40 40 static struct dmm *omap_dmm; 41 41 42 + #if defined(CONFIG_OF) 43 + static const struct of_device_id dmm_of_match[]; 44 + #endif 45 + 42 46 /* global spinlock for protecting lists */ 43 47 static DEFINE_SPINLOCK(list_lock); 44 48 ··· 533 529 return round_up(geom[fmt].cpp * w, PAGE_SIZE) * h; 534 530 } 535 531 532 + uint32_t tiler_get_cpu_cache_flags(void) 533 + { 534 + return omap_dmm->plat_data->cpu_cache_flags; 535 + } 536 + 536 537 bool dmm_is_available(void) 537 538 { 538 539 return omap_dmm ? true : false; ··· 600 591 INIT_LIST_HEAD(&omap_dmm->idle_head); 601 592 602 593 init_waitqueue_head(&omap_dmm->engine_queue); 594 + 595 + if (dev->dev.of_node) { 596 + const struct of_device_id *match; 597 + 598 + match = of_match_node(dmm_of_match, dev->dev.of_node); 599 + if (!match) { 600 + dev_err(&dev->dev, "failed to find matching device node\n"); 601 + return -ENODEV; 602 + } 603 + 604 + omap_dmm->plat_data = match->data; 605 + } 603 606 604 607 /* lookup hwmod data - base address and irq */ 605 608 mem = platform_get_resource(dev, IORESOURCE_MEM, 0); ··· 993 972 #endif 994 973 995 974 #if defined(CONFIG_OF) 975 + static const struct dmm_platform_data dmm_omap4_platform_data = { 976 + .cpu_cache_flags = OMAP_BO_WC, 977 + }; 978 + 979 + static const struct dmm_platform_data dmm_omap5_platform_data = { 980 + .cpu_cache_flags = OMAP_BO_UNCACHED, 981 + }; 982 + 996 983 static const struct of_device_id dmm_of_match[] = { 997 - { .compatible = "ti,omap4-dmm", }, 998 - { .compatible = "ti,omap5-dmm", }, 984 + { 985 + .compatible = "ti,omap4-dmm", 986 + .data = &dmm_omap4_platform_data, 987 + }, 988 + { 989 + .compatible = "ti,omap5-dmm", 990 + .data = &dmm_omap5_platform_data, 991 + }, 999 992 {}, 1000 993 }; 1001 994 #endif
+1
drivers/gpu/drm/omapdrm/omap_dmm_tiler.h
··· 106 106 size_t tiler_size(enum tiler_fmt fmt, uint16_t w, uint16_t h); 107 107 size_t tiler_vsize(enum tiler_fmt fmt, uint16_t w, uint16_t h); 108 108 void tiler_align(enum tiler_fmt fmt, uint16_t *w, uint16_t *h); 109 + uint32_t tiler_get_cpu_cache_flags(void); 109 110 bool dmm_is_available(void); 110 111 111 112 extern struct platform_driver omap_dmm_driver;
+2 -2
drivers/gpu/drm/omapdrm/omap_gem.c
··· 1359 1359 /* currently don't allow cached buffers.. there is some caching 1360 1360 * stuff that needs to be handled better 1361 1361 */ 1362 - flags &= ~(OMAP_BO_CACHED|OMAP_BO_UNCACHED); 1363 - flags |= OMAP_BO_WC; 1362 + flags &= ~(OMAP_BO_CACHED|OMAP_BO_WC|OMAP_BO_UNCACHED); 1363 + flags |= tiler_get_cpu_cache_flags(); 1364 1364 1365 1365 /* align dimensions to slot boundaries... */ 1366 1366 tiler_align(gem2fmt(flags),