Message ID | 20181017130454.44292-6-noralf@tronnes.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | drm: Add shmem GEM library | expand |
Den 17.10.2018 15.04, skrev Noralf Trønnes: > This move makes tinydrm useful for more drivers. tinydrm doesn't need > continuous memory, but at the time it was convenient to use the CMA > library. The spi core can do dma on is_vmalloc() addresses making this > possible. > > Cc: David Lechner <david@lechnology.com> > Signed-off-by: Noralf Trønnes <noralf@tronnes.org> > Acked-by: David Lechner <david@lechnology.com> > Tested-by: David Lechner <david@lechnology.com> > --- David, FYI This series is scratched. See the shmem helper patch thread for details. Noralf. > drivers/gpu/drm/tinydrm/Kconfig | 2 +- > drivers/gpu/drm/tinydrm/core/tinydrm-core.c | 92 +++++++------------------- > drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c | 5 ++ > drivers/gpu/drm/tinydrm/ili9225.c | 14 ++-- > drivers/gpu/drm/tinydrm/ili9341.c | 6 +- > drivers/gpu/drm/tinydrm/mi0283qt.c | 6 +- > drivers/gpu/drm/tinydrm/mipi-dbi.c | 38 ++++------- > drivers/gpu/drm/tinydrm/repaper.c | 24 +++---- > drivers/gpu/drm/tinydrm/st7586.c | 15 +++-- > drivers/gpu/drm/tinydrm/st7735r.c | 6 +- > include/drm/tinydrm/tinydrm.h | 36 +++------- > 11 files changed, 91 insertions(+), 153 deletions(-) > > diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig > index 16f4b5c91f1b..aa0cabba5ace 100644 > --- a/drivers/gpu/drm/tinydrm/Kconfig > +++ b/drivers/gpu/drm/tinydrm/Kconfig > @@ -2,7 +2,7 @@ menuconfig DRM_TINYDRM > tristate "Support for simple displays" > depends on DRM > select DRM_KMS_HELPER > - select DRM_KMS_CMA_HELPER > + select DRM_GEM_SHMEM_HELPER > help > Choose this option if you have a tinydrm supported display. > If M is selected the module will be called tinydrm. > diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c > index 255341ee4eb9..38ba361d1af2 100644 > --- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c > +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c > @@ -12,6 +12,7 @@ > #include <drm/drm_crtc_helper.h> > #include <drm/drm_fb_helper.h> > #include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/drm_gem_shmem_helper.h> > #include <drm/tinydrm/tinydrm.h> > #include <linux/device.h> > #include <linux/dma-buf.h> > @@ -23,7 +24,7 @@ > * > * It is based on &drm_simple_display_pipe coupled with a &drm_connector which > * has only one fixed &drm_display_mode. The framebuffers are backed by the > - * cma helper and have support for framebuffer flushing (dirty). > + * shmem buffers and have support for framebuffer flushing (dirty). > * fbdev support is also included. > * > */ > @@ -37,84 +38,41 @@ > */ > > /** > - * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from > - * another driver's scatter/gather table of pinned pages > - * @drm: DRM device to import into > - * @attach: DMA-BUF attachment > - * @sgt: Scatter/gather table of pinned pages > + * tinydrm_fb_destroy - Destroy framebuffer > + * @fb: Framebuffer > * > - * This function imports a scatter/gather table exported via DMA-BUF by > - * another driver using drm_gem_cma_prime_import_sg_table(). It sets the > - * kernel virtual address on the CMA object. Drivers should use this as their > - * &drm_driver->gem_prime_import_sg_table callback if they need the virtual > - * address. tinydrm_gem_cma_free_object() should be used in combination with > - * this function. > - * > - * Returns: > - * A pointer to a newly created GEM object or an ERR_PTR-encoded negative > - * error code on failure. > + * This function unmaps the virtual address on the backing buffer and destroys the framebuffer. > + * Drivers should use this as their &drm_framebuffer_funcs->destroy callback. > */ > -struct drm_gem_object * > -tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm, > - struct dma_buf_attachment *attach, > - struct sg_table *sgt) > +void tinydrm_fb_destroy(struct drm_framebuffer *fb) > { > - struct drm_gem_cma_object *cma_obj; > - struct drm_gem_object *obj; > - void *vaddr; > + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); > + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); > > - vaddr = dma_buf_vmap(attach->dmabuf); > - if (!vaddr) { > - DRM_ERROR("Failed to vmap PRIME buffer\n"); > - return ERR_PTR(-ENOMEM); > - } > - > - obj = drm_gem_cma_prime_import_sg_table(drm, attach, sgt); > - if (IS_ERR(obj)) { > - dma_buf_vunmap(attach->dmabuf, vaddr); > - return obj; > - } > - > - cma_obj = to_drm_gem_cma_obj(obj); > - cma_obj->vaddr = vaddr; > - > - return obj; > + drm_gem_vunmap(gem, shmem->vaddr); > + drm_gem_fb_destroy(fb); > } > -EXPORT_SYMBOL(tinydrm_gem_cma_prime_import_sg_table); > - > -/** > - * tinydrm_gem_cma_free_object - Free resources associated with a CMA GEM > - * object > - * @gem_obj: GEM object to free > - * > - * This function frees the backing memory of the CMA GEM object, cleans up the > - * GEM object state and frees the memory used to store the object itself using > - * drm_gem_cma_free_object(). It also handles PRIME buffers which has the kernel > - * virtual address set by tinydrm_gem_cma_prime_import_sg_table(). Drivers > - * can use this as their &drm_driver->gem_free_object_unlocked callback. > - */ > -void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj) > -{ > - if (gem_obj->import_attach) { > - struct drm_gem_cma_object *cma_obj; > - > - cma_obj = to_drm_gem_cma_obj(gem_obj); > - dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr); > - cma_obj->vaddr = NULL; > - } > - > - drm_gem_cma_free_object(gem_obj); > -} > -EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object); > +EXPORT_SYMBOL(tinydrm_fb_destroy); > > static struct drm_framebuffer * > tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv, > const struct drm_mode_fb_cmd2 *mode_cmd) > { > struct tinydrm_device *tdev = drm->dev_private; > + struct drm_framebuffer *fb; > + void *vaddr; > > - return drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd, > - tdev->fb_funcs); > + fb = drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd, tdev->fb_funcs); > + if (IS_ERR(fb)) > + return fb; > + > + vaddr = drm_gem_vmap(drm_gem_fb_get_obj(fb, 0)); > + if (IS_ERR(vaddr)) { > + drm_gem_fb_destroy(fb); > + return ERR_CAST(vaddr); > + } > + > + return fb; > } > > static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = { > diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c > index dcd390163a4a..f9d35acff23d 100644 > --- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c > +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c > @@ -9,12 +9,17 @@ > > #include <linux/backlight.h> > #include <linux/dma-buf.h> > +#include <linux/module.h> > #include <linux/pm.h> > #include <linux/spi/spi.h> > #include <linux/swab.h> > > +#include <drm/drm_device.h> > +#include <drm/drm_drv.h> > +#include <drm/drm_fourcc.h> > #include <drm/tinydrm/tinydrm.h> > #include <drm/tinydrm/tinydrm-helpers.h> > +#include <drm/drm_print.h> > > static unsigned int spi_max; > module_param(spi_max, uint, 0400); > diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c > index 455fefe012f5..c24d6e4c834b 100644 > --- a/drivers/gpu/drm/tinydrm/ili9225.c > +++ b/drivers/gpu/drm/tinydrm/ili9225.c > @@ -20,8 +20,11 @@ > #include <linux/spi/spi.h> > #include <video/mipi_display.h> > > +#include <drm/drm_drv.h> > #include <drm/drm_fb_helper.h> > +#include <drm/drm_fourcc.h> > #include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/drm_gem_shmem_helper.h> > #include <drm/tinydrm/mipi-dbi.h> > #include <drm/tinydrm/tinydrm-helpers.h> > > @@ -77,7 +80,8 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, > unsigned int color, struct drm_clip_rect *clips, > unsigned int num_clips) > { > - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); > + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); > + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); > struct tinydrm_device *tdev = fb->dev->dev_private; > struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); > bool swap = mipi->swap_bytes; > @@ -104,7 +108,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, > if (ret) > return ret; > } else { > - tr = cma_obj->vaddr; > + tr = shmem->vaddr; > } > > switch (mipi->rotation) { > @@ -157,7 +161,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, > } > > static const struct drm_framebuffer_funcs ili9225_fb_funcs = { > - .destroy = drm_gem_fb_destroy, > + .destroy = tinydrm_fb_destroy, > .create_handle = drm_gem_fb_create_handle, > .dirty = tinydrm_fb_dirty, > }; > @@ -361,13 +365,13 @@ static const struct drm_display_mode ili9225_mode = { > TINYDRM_MODE(176, 220, 35, 44), > }; > > -DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops); > +DEFINE_DRM_GEM_SHMEM_FOPS(ili9225_fops); > > static struct drm_driver ili9225_driver = { > .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | > DRIVER_ATOMIC, > .fops = &ili9225_fops, > - TINYDRM_GEM_DRIVER_OPS, > + DRM_GEM_SHMEM_DRIVER_OPS, > .name = "ili9225", > .desc = "Ilitek ILI9225", > .date = "20171106", > diff --git a/drivers/gpu/drm/tinydrm/ili9341.c b/drivers/gpu/drm/tinydrm/ili9341.c > index 6701037749a7..7a80f8e6d6f3 100644 > --- a/drivers/gpu/drm/tinydrm/ili9341.c > +++ b/drivers/gpu/drm/tinydrm/ili9341.c > @@ -15,8 +15,10 @@ > #include <linux/property.h> > #include <linux/spi/spi.h> > > +#include <drm/drm_drv.h> > #include <drm/drm_fb_helper.h> > #include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/drm_gem_shmem_helper.h> > #include <drm/drm_modeset_helper.h> > #include <drm/tinydrm/mipi-dbi.h> > #include <drm/tinydrm/tinydrm-helpers.h> > @@ -139,12 +141,12 @@ static const struct drm_display_mode yx240qv29_mode = { > TINYDRM_MODE(240, 320, 37, 49), > }; > > -DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops); > +DEFINE_DRM_GEM_SHMEM_FOPS(ili9341_fops); > > static struct drm_driver ili9341_driver = { > .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, > .fops = &ili9341_fops, > - TINYDRM_GEM_DRIVER_OPS, > + DRM_GEM_SHMEM_DRIVER_OPS, > .debugfs_init = mipi_dbi_debugfs_init, > .name = "ili9341", > .desc = "Ilitek ILI9341", > diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c > index d7bb4c5e6657..b5837a6b3633 100644 > --- a/drivers/gpu/drm/tinydrm/mi0283qt.c > +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c > @@ -17,9 +17,11 @@ > #include <linux/regulator/consumer.h> > #include <linux/spi/spi.h> > > +#include <drm/drm_drv.h> > #include <drm/drm_fb_helper.h> > #include <drm/drm_modeset_helper.h> > #include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/drm_gem_shmem_helper.h> > #include <drm/tinydrm/mipi-dbi.h> > #include <drm/tinydrm/tinydrm-helpers.h> > #include <video/mipi_display.h> > @@ -147,13 +149,13 @@ static const struct drm_display_mode mi0283qt_mode = { > TINYDRM_MODE(320, 240, 58, 43), > }; > > -DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops); > +DEFINE_DRM_GEM_SHMEM_FOPS(mi0283qt_fops); > > static struct drm_driver mi0283qt_driver = { > .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | > DRIVER_ATOMIC, > .fops = &mi0283qt_fops, > - TINYDRM_GEM_DRIVER_OPS, > + DRM_GEM_SHMEM_DRIVER_OPS, > .debugfs_init = mipi_dbi_debugfs_init, > .name = "mi0283qt", > .desc = "Multi-Inno MI0283QT", > diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c > index cb3441e51d5f..e0f59177c2ef 100644 > --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c > +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c > @@ -9,10 +9,15 @@ > * (at your option) any later version. > */ > > +#include <drm/drm_device.h> > +#include <drm/drm_drv.h> > +#include <drm/drm_fourcc.h> > #include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/drm_gem_shmem_helper.h> > #include <drm/tinydrm/mipi-dbi.h> > #include <drm/tinydrm/tinydrm-helpers.h> > #include <linux/debugfs.h> > +#include <linux/delay.h> > #include <linux/dma-buf.h> > #include <linux/gpio/consumer.h> > #include <linux/module.h> > @@ -167,10 +172,11 @@ EXPORT_SYMBOL(mipi_dbi_command_buf); > int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, > struct drm_clip_rect *clip, bool swap) > { > - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); > - struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; > + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); > + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); > + struct dma_buf_attachment *import_attach = gem->import_attach; > struct drm_format_name_buf format_name; > - void *src = cma_obj->vaddr; > + void *src = shmem->vaddr; > int ret = 0; > > if (import_attach) { > @@ -210,7 +216,8 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, > struct drm_clip_rect *clips, > unsigned int num_clips) > { > - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); > + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); > + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); > struct tinydrm_device *tdev = fb->dev->dev_private; > struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); > bool swap = mipi->swap_bytes; > @@ -235,7 +242,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, > if (ret) > return ret; > } else { > - tr = cma_obj->vaddr; > + tr = shmem->vaddr; > } > > mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, > @@ -252,7 +259,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, > } > > static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = { > - .destroy = drm_gem_fb_destroy, > + .destroy = tinydrm_fb_destroy, > .create_handle = drm_gem_fb_create_handle, > .dirty = tinydrm_fb_dirty, > }; > @@ -882,31 +889,12 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi, > { > size_t tx_size = tinydrm_spi_max_transfer_size(spi, 0); > struct device *dev = &spi->dev; > - int ret; > > if (tx_size < 16) { > DRM_ERROR("SPI transmit buffer too small: %zu\n", tx_size); > return -EINVAL; > } > > - /* > - * Even though it's not the SPI device that does DMA (the master does), > - * the dma mask is necessary for the dma_alloc_wc() in > - * drm_gem_cma_create(). The dma_addr returned will be a physical > - * adddress which might be different from the bus address, but this is > - * not a problem since the address will not be used. > - * The virtual address is used in the transfer and the SPI core > - * re-maps it on the SPI master device using the DMA streaming API > - * (spi_map_buf()). > - */ > - if (!dev->coherent_dma_mask) { > - ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); > - if (ret) { > - dev_warn(dev, "Failed to set dma mask %d\n", ret); > - return ret; > - } > - } > - > mipi->spi = spi; > mipi->read_commands = mipi_dbi_dcs_read_commands; > > diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c > index 50a1d4216ce7..82d8c6bf0c91 100644 > --- a/drivers/gpu/drm/tinydrm/repaper.c > +++ b/drivers/gpu/drm/tinydrm/repaper.c > @@ -26,7 +26,9 @@ > #include <linux/spi/spi.h> > #include <linux/thermal.h> > > +#include <drm/drm_drv.h> > #include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/drm_gem_shmem_helper.h> > #include <drm/tinydrm/tinydrm.h> > #include <drm/tinydrm/tinydrm-helpers.h> > > @@ -526,8 +528,9 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, > struct drm_clip_rect *clips, > unsigned int num_clips) > { > - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); > - struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; > + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); > + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); > + struct dma_buf_attachment *import_attach = gem->import_attach; > struct tinydrm_device *tdev = fb->dev->dev_private; > struct repaper_epd *epd = epd_from_tinydrm(tdev); > struct drm_clip_rect clip; > @@ -559,7 +562,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, > goto out_free; > } > > - tinydrm_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip); > + tinydrm_xrgb8888_to_gray8(buf, shmem->vaddr, fb, &clip); > > if (import_attach) { > ret = dma_buf_end_cpu_access(import_attach->dmabuf, > @@ -624,7 +627,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, > } > > static const struct drm_framebuffer_funcs repaper_fb_funcs = { > - .destroy = drm_gem_fb_destroy, > + .destroy = tinydrm_fb_destroy, > .create_handle = drm_gem_fb_create_handle, > .dirty = tinydrm_fb_dirty, > }; > @@ -876,13 +879,13 @@ static const struct drm_display_mode repaper_e2271cs021_mode = { > static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f, > 0xff, 0xfe, 0x00, 0x00 }; > > -DEFINE_DRM_GEM_CMA_FOPS(repaper_fops); > +DEFINE_DRM_GEM_SHMEM_FOPS(repaper_fops); > > static struct drm_driver repaper_driver = { > .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | > DRIVER_ATOMIC, > .fops = &repaper_fops, > - TINYDRM_GEM_DRIVER_OPS, > + DRM_GEM_SHMEM_DRIVER_OPS, > .name = "repaper", > .desc = "Pervasive Displays RePaper e-ink panels", > .date = "20170405", > @@ -929,15 +932,6 @@ static int repaper_probe(struct spi_device *spi) > model = spi_id->driver_data; > } > > - /* The SPI device is used to allocate dma memory */ > - if (!dev->coherent_dma_mask) { > - ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); > - if (ret) { > - dev_warn(dev, "Failed to set dma mask %d\n", ret); > - return ret; > - } > - } > - > epd = devm_kzalloc(dev, sizeof(*epd), GFP_KERNEL); > if (!epd) > return -ENOMEM; > diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c > index 2fcbc3067d71..340c9be2613b 100644 > --- a/drivers/gpu/drm/tinydrm/st7586.c > +++ b/drivers/gpu/drm/tinydrm/st7586.c > @@ -17,8 +17,10 @@ > #include <linux/spi/spi.h> > #include <video/mipi_display.h> > > +#include <drm/drm_drv.h> > #include <drm/drm_fb_helper.h> > #include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/drm_gem_shmem_helper.h> > #include <drm/tinydrm/mipi-dbi.h> > #include <drm/tinydrm/tinydrm-helpers.h> > > @@ -88,9 +90,10 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, > static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, > struct drm_clip_rect *clip) > { > - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); > - struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; > - void *src = cma_obj->vaddr; > + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); > + struct dma_buf_attachment *import_attach = gem->import_attach; > + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); > + void *src = shmem->vaddr; > int ret = 0; > > if (import_attach) { > @@ -156,7 +159,7 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb, > } > > static const struct drm_framebuffer_funcs st7586_fb_funcs = { > - .destroy = drm_gem_fb_destroy, > + .destroy = tinydrm_fb_destroy, > .create_handle = drm_gem_fb_create_handle, > .dirty = tinydrm_fb_dirty, > }; > @@ -297,13 +300,13 @@ static const struct drm_display_mode st7586_mode = { > TINYDRM_MODE(178, 128, 37, 27), > }; > > -DEFINE_DRM_GEM_CMA_FOPS(st7586_fops); > +DEFINE_DRM_GEM_SHMEM_FOPS(st7586_fops); > > static struct drm_driver st7586_driver = { > .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | > DRIVER_ATOMIC, > .fops = &st7586_fops, > - TINYDRM_GEM_DRIVER_OPS, > + DRM_GEM_SHMEM_DRIVER_OPS, > .debugfs_init = mipi_dbi_debugfs_init, > .name = "st7586", > .desc = "Sitronix ST7586", > diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c > index 3081bc57c116..1108088a1a03 100644 > --- a/drivers/gpu/drm/tinydrm/st7735r.c > +++ b/drivers/gpu/drm/tinydrm/st7735r.c > @@ -14,8 +14,10 @@ > #include <linux/spi/spi.h> > #include <video/mipi_display.h> > > +#include <drm/drm_drv.h> > #include <drm/drm_fb_helper.h> > #include <drm/drm_gem_framebuffer_helper.h> > +#include <drm/drm_gem_shmem_helper.h> > #include <drm/tinydrm/mipi-dbi.h> > #include <drm/tinydrm/tinydrm-helpers.h> > > @@ -113,13 +115,13 @@ static const struct drm_display_mode jd_t18003_t01_mode = { > TINYDRM_MODE(128, 160, 28, 35), > }; > > -DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops); > +DEFINE_DRM_GEM_SHMEM_FOPS(st7735r_fops); > > static struct drm_driver st7735r_driver = { > .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | > DRIVER_ATOMIC, > .fops = &st7735r_fops, > - TINYDRM_GEM_DRIVER_OPS, > + DRM_GEM_SHMEM_DRIVER_OPS, > .debugfs_init = mipi_dbi_debugfs_init, > .name = "st7735r", > .desc = "Sitronix ST7735R", > diff --git a/include/drm/tinydrm/tinydrm.h b/include/drm/tinydrm/tinydrm.h > index fe9827d0ca8a..e2cb254125c5 100644 > --- a/include/drm/tinydrm/tinydrm.h > +++ b/include/drm/tinydrm/tinydrm.h > @@ -10,10 +10,15 @@ > #ifndef __LINUX_TINYDRM_H > #define __LINUX_TINYDRM_H > > -#include <drm/drm_gem_cma_helper.h> > -#include <drm/drm_fb_cma_helper.h> > +#include <linux/mutex.h> > #include <drm/drm_simple_kms_helper.h> > > +struct drm_driver; > +struct drm_framebuffer; > +struct drm_file; > +struct drm_clip_rect; > +struct drm_framebuffer_funcs; > + > /** > * struct tinydrm_device - tinydrm device > */ > @@ -53,27 +58,6 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe) > return container_of(pipe, struct tinydrm_device, pipe); > } > > -/** > - * TINYDRM_GEM_DRIVER_OPS - default tinydrm gem operations > - * > - * This macro provides a shortcut for setting the tinydrm GEM operations in > - * the &drm_driver structure. > - */ > -#define TINYDRM_GEM_DRIVER_OPS \ > - .gem_free_object_unlocked = tinydrm_gem_cma_free_object, \ > - .gem_print_info = drm_gem_cma_print_info, \ > - .gem_vm_ops = &drm_gem_cma_vm_ops, \ > - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, \ > - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, \ > - .gem_prime_import = drm_gem_prime_import, \ > - .gem_prime_export = drm_gem_prime_export, \ > - .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, \ > - .gem_prime_import_sg_table = tinydrm_gem_cma_prime_import_sg_table, \ > - .gem_prime_vmap = drm_gem_cma_prime_vmap, \ > - .gem_prime_vunmap = drm_gem_cma_prime_vunmap, \ > - .gem_prime_mmap = drm_gem_cma_prime_mmap, \ > - .dumb_create = drm_gem_cma_dumb_create > - > /** > * TINYDRM_MODE - tinydrm display mode > * @hd: Horizontal resolution, width > @@ -97,11 +81,7 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe) > .type = DRM_MODE_TYPE_DRIVER, \ > .clock = 1 /* pass validation */ > > -void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj); > -struct drm_gem_object * > -tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm, > - struct dma_buf_attachment *attach, > - struct sg_table *sgt); > +void tinydrm_fb_destroy(struct drm_framebuffer *fb); > int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev, > const struct drm_framebuffer_funcs *fb_funcs, > struct drm_driver *driver);
On 10/26/2018 05:38 PM, Noralf Trønnes wrote: > > Den 17.10.2018 15.04, skrev Noralf Trønnes: >> This move makes tinydrm useful for more drivers. tinydrm doesn't need >> continuous memory, but at the time it was convenient to use the CMA >> library. The spi core can do dma on is_vmalloc() addresses making this >> possible. >> >> Cc: David Lechner <david@lechnology.com> >> Signed-off-by: Noralf Trønnes <noralf@tronnes.org> >> Acked-by: David Lechner <david@lechnology.com> >> Tested-by: David Lechner <david@lechnology.com> >> --- > > David, > FYI This series is scratched. > See the shmem helper patch thread for details. > Yes, I saw that. Thank you. I don't suppose there is a way to configure the DMA controller to do the byte swapping?
Den 28.10.2018 21.21, skrev David Lechner: > On 10/26/2018 05:38 PM, Noralf Trønnes wrote: >> Den 17.10.2018 15.04, skrev Noralf Trønnes: >>> This move makes tinydrm useful for more drivers. tinydrm doesn't need >>> continuous memory, but at the time it was convenient to use the CMA >>> library. The spi core can do dma on is_vmalloc() addresses making this >>> possible. >>> >>> Cc: David Lechner <david@lechnology.com> >>> Signed-off-by: Noralf Trønnes <noralf@tronnes.org> >>> Acked-by: David Lechner <david@lechnology.com> >>> Tested-by: David Lechner <david@lechnology.com> >>> --- >> David, >> FYI This series is scratched. >> See the shmem helper patch thread for details. >> > Yes, I saw that. Thank you. > > I don't suppose there is a way to configure the DMA controller to do > the byte swapping? > Not that I know of. "Proper" SPI hw can do 16-bit transfers and for them there's no problem. The DMA capable SPI block on the Pi can only do 8-bit, hence the swapping. But that wasn't the problem, the byteswapping actually papered over the problem. I'm no -mm expert so I don't know why the problem onyl showed up when using the virtual address of the buffer used by fbcon and not on mmap'ed fbdev as Daniel suggested would happen. Either way shmem not being coherent is a problem on the Pi, even though I expected the DMA streaming API called by the spi core to flush "things". The solution I'm aiming for is to make it easy for tinydrm drivers to use the buffer type they want, instead of having one type they all have to use. Noralf.
On Sun, Oct 28, 2018 at 09:46:43PM +0100, Noralf Trønnes wrote: > > Den 28.10.2018 21.21, skrev David Lechner: > > On 10/26/2018 05:38 PM, Noralf Trønnes wrote: > > > Den 17.10.2018 15.04, skrev Noralf Trønnes: > > > > This move makes tinydrm useful for more drivers. tinydrm doesn't need > > > > continuous memory, but at the time it was convenient to use the CMA > > > > library. The spi core can do dma on is_vmalloc() addresses making this > > > > possible. > > > > > > > > Cc: David Lechner <david@lechnology.com> > > > > Signed-off-by: Noralf Trønnes <noralf@tronnes.org> > > > > Acked-by: David Lechner <david@lechnology.com> > > > > Tested-by: David Lechner <david@lechnology.com> > > > > --- > > > David, > > > FYI This series is scratched. > > > See the shmem helper patch thread for details. > > > > > Yes, I saw that. Thank you. > > > > I don't suppose there is a way to configure the DMA controller to do > > the byte swapping? > > > > Not that I know of. > "Proper" SPI hw can do 16-bit transfers and for them there's no problem. > The DMA capable SPI block on the Pi can only do 8-bit, hence the swapping. > > But that wasn't the problem, the byteswapping actually papered over the > problem. I'm no -mm expert so I don't know why the problem onyl showed > up when using the virtual address of the buffer used by fbcon and not on > mmap'ed fbdev as Daniel suggested would happen. Hm, I missed that detail. This sounds like one of the mappings ended up being write-combining (which avoids all the issues with dirty cpu cache lines), while the broken one was not. Or we ended up with a flush somewhere by accident. > Either way shmem not being coherent is a problem on the Pi, even though > I expected the DMA streaming API called by the spi core to flush "things". It should do that for you. At least if it's using dma_map/unmap_sg and friends. > The solution I'm aiming for is to make it easy for tinydrm drivers to use > the > buffer type they want, instead of having one type they all have to use. General recommendation for this is "less midlayer, more helper". Which was the goal of all this ... Oh well :-/ Maybe we can progress in other areas meanwhile. -Daniel
Den 29.10.2018 10.07, skrev Daniel Vetter: > On Sun, Oct 28, 2018 at 09:46:43PM +0100, Noralf Trønnes wrote: >> Den 28.10.2018 21.21, skrev David Lechner: >>> On 10/26/2018 05:38 PM, Noralf Trønnes wrote: >>>> Den 17.10.2018 15.04, skrev Noralf Trønnes: >>>>> This move makes tinydrm useful for more drivers. tinydrm doesn't need >>>>> continuous memory, but at the time it was convenient to use the CMA >>>>> library. The spi core can do dma on is_vmalloc() addresses making this >>>>> possible. >>>>> >>>>> Cc: David Lechner <david@lechnology.com> >>>>> Signed-off-by: Noralf Trønnes <noralf@tronnes.org> >>>>> Acked-by: David Lechner <david@lechnology.com> >>>>> Tested-by: David Lechner <david@lechnology.com> >>>>> --- >>>> David, >>>> FYI This series is scratched. >>>> See the shmem helper patch thread for details. >>>> >>> Yes, I saw that. Thank you. >>> >>> I don't suppose there is a way to configure the DMA controller to do >>> the byte swapping? >>> >> Not that I know of. >> "Proper" SPI hw can do 16-bit transfers and for them there's no problem. >> The DMA capable SPI block on the Pi can only do 8-bit, hence the swapping. >> >> But that wasn't the problem, the byteswapping actually papered over the >> problem. I'm no -mm expert so I don't know why the problem onyl showed >> up when using the virtual address of the buffer used by fbcon and not on >> mmap'ed fbdev as Daniel suggested would happen. > Hm, I missed that detail. This sounds like one of the mappings ended up > being write-combining (which avoids all the issues with dirty cpu cache > lines), while the broken one was not. > > Or we ended up with a flush somewhere by accident. > >> Either way shmem not being coherent is a problem on the Pi, even though >> I expected the DMA streaming API called by the spi core to flush "things". > It should do that for you. At least if it's using dma_map/unmap_sg and > friends. I just watched a talk by the i2c maintainer about his challenges with supporting DMA buffers and DMA only host controllers: DMA Safety in Buffers for Linux Kernel Device Drivers - Wolfram Sang https://www.youtube.com/watch?v=JDwaMClvV-s In passing he mentions this from Documentation/spi/spi-summary: - I/O buffers use the usual Linux rules, and must be DMA-safe. You'd normally allocate them from the heap or free page pool. So how can the SPI core ensure DMA safety for its DMA mapping of the underlying pages of virtual addresses? This is what I relied on when doing the shmem helper. Doing further digging I came across these: Vignesh R says: https://www.spinics.net/lists/kernel/msg2687381.html SPI core does try to DMA into underlying physical pages of vmalloc'd buffer. But this has two problems: 1. Does not work well with VIVT caches[1]. 2. On ARM LPAE systems, vmalloc'd buffers can be from highmem region that are not addressable using 32 bit addresses and is backed by LPAE. So, a 32 bit DMA cannot access these buffers. Both these issues lead to random crashes and errors with UBIFS and JFFS2 flash file systems which this patch series tries to address using bounce buffer [1] https://patchwork.kernel.org/patch/9579553/ Russel King provides some more info: https://patchwork.kernel.org/patch/9579553/#20139929 SPI is rather another special case - rather than SPI following the established mechanism of passing data references via scatterlists or similar, it also passes them via virtual addresses, which means SPI can directly access the vmalloc area when performing PIO. This really makes the problem more complex, because it means that if you do have a SPI driver that does that, it's going to be reading/writing direct from vmalloc space. That's not a problem as long as the data is only accessed via vmalloc space, but it will definitely go totally wrong if the data is subsequently mapped into userspace. So even if I could make the shmem helper work on the Raspberry Pi with tinydrm and SPI, it probably wouldn't work on all systems. I also learned that using devm_kmalloc, which tinydrm does for a tx buffer, is not DMA safe because it prepends a devres struct to the buffer making the buffer itself not cache line aligned. [Question] devm_kmalloc() for DMA ? https://linux-arm-kernel.infradead.narkive.com/vyJqy0RQ/question-devm-kmalloc-for-dma I'll turn this into a plain kmalloc when I return to my work on supporting device unplug which will deal with device resource lifetime issues. Noralf.
diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tinydrm/Kconfig index 16f4b5c91f1b..aa0cabba5ace 100644 --- a/drivers/gpu/drm/tinydrm/Kconfig +++ b/drivers/gpu/drm/tinydrm/Kconfig @@ -2,7 +2,7 @@ menuconfig DRM_TINYDRM tristate "Support for simple displays" depends on DRM select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_SHMEM_HELPER help Choose this option if you have a tinydrm supported display. If M is selected the module will be called tinydrm. diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c index 255341ee4eb9..38ba361d1af2 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-core.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-core.c @@ -12,6 +12,7 @@ #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> #include <drm/tinydrm/tinydrm.h> #include <linux/device.h> #include <linux/dma-buf.h> @@ -23,7 +24,7 @@ * * It is based on &drm_simple_display_pipe coupled with a &drm_connector which * has only one fixed &drm_display_mode. The framebuffers are backed by the - * cma helper and have support for framebuffer flushing (dirty). + * shmem buffers and have support for framebuffer flushing (dirty). * fbdev support is also included. * */ @@ -37,84 +38,41 @@ */ /** - * tinydrm_gem_cma_prime_import_sg_table - Produce a CMA GEM object from - * another driver's scatter/gather table of pinned pages - * @drm: DRM device to import into - * @attach: DMA-BUF attachment - * @sgt: Scatter/gather table of pinned pages + * tinydrm_fb_destroy - Destroy framebuffer + * @fb: Framebuffer * - * This function imports a scatter/gather table exported via DMA-BUF by - * another driver using drm_gem_cma_prime_import_sg_table(). It sets the - * kernel virtual address on the CMA object. Drivers should use this as their - * &drm_driver->gem_prime_import_sg_table callback if they need the virtual - * address. tinydrm_gem_cma_free_object() should be used in combination with - * this function. - * - * Returns: - * A pointer to a newly created GEM object or an ERR_PTR-encoded negative - * error code on failure. + * This function unmaps the virtual address on the backing buffer and destroys the framebuffer. + * Drivers should use this as their &drm_framebuffer_funcs->destroy callback. */ -struct drm_gem_object * -tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm, - struct dma_buf_attachment *attach, - struct sg_table *sgt) +void tinydrm_fb_destroy(struct drm_framebuffer *fb) { - struct drm_gem_cma_object *cma_obj; - struct drm_gem_object *obj; - void *vaddr; + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); - vaddr = dma_buf_vmap(attach->dmabuf); - if (!vaddr) { - DRM_ERROR("Failed to vmap PRIME buffer\n"); - return ERR_PTR(-ENOMEM); - } - - obj = drm_gem_cma_prime_import_sg_table(drm, attach, sgt); - if (IS_ERR(obj)) { - dma_buf_vunmap(attach->dmabuf, vaddr); - return obj; - } - - cma_obj = to_drm_gem_cma_obj(obj); - cma_obj->vaddr = vaddr; - - return obj; + drm_gem_vunmap(gem, shmem->vaddr); + drm_gem_fb_destroy(fb); } -EXPORT_SYMBOL(tinydrm_gem_cma_prime_import_sg_table); - -/** - * tinydrm_gem_cma_free_object - Free resources associated with a CMA GEM - * object - * @gem_obj: GEM object to free - * - * This function frees the backing memory of the CMA GEM object, cleans up the - * GEM object state and frees the memory used to store the object itself using - * drm_gem_cma_free_object(). It also handles PRIME buffers which has the kernel - * virtual address set by tinydrm_gem_cma_prime_import_sg_table(). Drivers - * can use this as their &drm_driver->gem_free_object_unlocked callback. - */ -void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj) -{ - if (gem_obj->import_attach) { - struct drm_gem_cma_object *cma_obj; - - cma_obj = to_drm_gem_cma_obj(gem_obj); - dma_buf_vunmap(gem_obj->import_attach->dmabuf, cma_obj->vaddr); - cma_obj->vaddr = NULL; - } - - drm_gem_cma_free_object(gem_obj); -} -EXPORT_SYMBOL_GPL(tinydrm_gem_cma_free_object); +EXPORT_SYMBOL(tinydrm_fb_destroy); static struct drm_framebuffer * tinydrm_fb_create(struct drm_device *drm, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd) { struct tinydrm_device *tdev = drm->dev_private; + struct drm_framebuffer *fb; + void *vaddr; - return drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd, - tdev->fb_funcs); + fb = drm_gem_fb_create_with_funcs(drm, file_priv, mode_cmd, tdev->fb_funcs); + if (IS_ERR(fb)) + return fb; + + vaddr = drm_gem_vmap(drm_gem_fb_get_obj(fb, 0)); + if (IS_ERR(vaddr)) { + drm_gem_fb_destroy(fb); + return ERR_CAST(vaddr); + } + + return fb; } static const struct drm_mode_config_funcs tinydrm_mode_config_funcs = { diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c index dcd390163a4a..f9d35acff23d 100644 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c +++ b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c @@ -9,12 +9,17 @@ #include <linux/backlight.h> #include <linux/dma-buf.h> +#include <linux/module.h> #include <linux/pm.h> #include <linux/spi/spi.h> #include <linux/swab.h> +#include <drm/drm_device.h> +#include <drm/drm_drv.h> +#include <drm/drm_fourcc.h> #include <drm/tinydrm/tinydrm.h> #include <drm/tinydrm/tinydrm-helpers.h> +#include <drm/drm_print.h> static unsigned int spi_max; module_param(spi_max, uint, 0400); diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tinydrm/ili9225.c index 455fefe012f5..c24d6e4c834b 100644 --- a/drivers/gpu/drm/tinydrm/ili9225.c +++ b/drivers/gpu/drm/tinydrm/ili9225.c @@ -20,8 +20,11 @@ #include <linux/spi/spi.h> #include <video/mipi_display.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> #include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/tinydrm-helpers.h> @@ -77,7 +80,8 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, unsigned int color, struct drm_clip_rect *clips, unsigned int num_clips) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); struct tinydrm_device *tdev = fb->dev->dev_private; struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); bool swap = mipi->swap_bytes; @@ -104,7 +108,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, if (ret) return ret; } else { - tr = cma_obj->vaddr; + tr = shmem->vaddr; } switch (mipi->rotation) { @@ -157,7 +161,7 @@ static int ili9225_fb_dirty(struct drm_framebuffer *fb, } static const struct drm_framebuffer_funcs ili9225_fb_funcs = { - .destroy = drm_gem_fb_destroy, + .destroy = tinydrm_fb_destroy, .create_handle = drm_gem_fb_create_handle, .dirty = tinydrm_fb_dirty, }; @@ -361,13 +365,13 @@ static const struct drm_display_mode ili9225_mode = { TINYDRM_MODE(176, 220, 35, 44), }; -DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops); +DEFINE_DRM_GEM_SHMEM_FOPS(ili9225_fops); static struct drm_driver ili9225_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, .fops = &ili9225_fops, - TINYDRM_GEM_DRIVER_OPS, + DRM_GEM_SHMEM_DRIVER_OPS, .name = "ili9225", .desc = "Ilitek ILI9225", .date = "20171106", diff --git a/drivers/gpu/drm/tinydrm/ili9341.c b/drivers/gpu/drm/tinydrm/ili9341.c index 6701037749a7..7a80f8e6d6f3 100644 --- a/drivers/gpu/drm/tinydrm/ili9341.c +++ b/drivers/gpu/drm/tinydrm/ili9341.c @@ -15,8 +15,10 @@ #include <linux/property.h> #include <linux/spi/spi.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> #include <drm/drm_modeset_helper.h> #include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/tinydrm-helpers.h> @@ -139,12 +141,12 @@ static const struct drm_display_mode yx240qv29_mode = { TINYDRM_MODE(240, 320, 37, 49), }; -DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops); +DEFINE_DRM_GEM_SHMEM_FOPS(ili9341_fops); static struct drm_driver ili9341_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, .fops = &ili9341_fops, - TINYDRM_GEM_DRIVER_OPS, + DRM_GEM_SHMEM_DRIVER_OPS, .debugfs_init = mipi_dbi_debugfs_init, .name = "ili9341", .desc = "Ilitek ILI9341", diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tinydrm/mi0283qt.c index d7bb4c5e6657..b5837a6b3633 100644 --- a/drivers/gpu/drm/tinydrm/mi0283qt.c +++ b/drivers/gpu/drm/tinydrm/mi0283qt.c @@ -17,9 +17,11 @@ #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> #include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/tinydrm-helpers.h> #include <video/mipi_display.h> @@ -147,13 +149,13 @@ static const struct drm_display_mode mi0283qt_mode = { TINYDRM_MODE(320, 240, 58, 43), }; -DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops); +DEFINE_DRM_GEM_SHMEM_FOPS(mi0283qt_fops); static struct drm_driver mi0283qt_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, .fops = &mi0283qt_fops, - TINYDRM_GEM_DRIVER_OPS, + DRM_GEM_SHMEM_DRIVER_OPS, .debugfs_init = mipi_dbi_debugfs_init, .name = "mi0283qt", .desc = "Multi-Inno MI0283QT", diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/tinydrm/mipi-dbi.c index cb3441e51d5f..e0f59177c2ef 100644 --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c +++ b/drivers/gpu/drm/tinydrm/mipi-dbi.c @@ -9,10 +9,15 @@ * (at your option) any later version. */ +#include <drm/drm_device.h> +#include <drm/drm_drv.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> #include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/tinydrm-helpers.h> #include <linux/debugfs.h> +#include <linux/delay.h> #include <linux/dma-buf.h> #include <linux/gpio/consumer.h> #include <linux/module.h> @@ -167,10 +172,11 @@ EXPORT_SYMBOL(mipi_dbi_command_buf); int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, struct drm_clip_rect *clip, bool swap) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); + struct dma_buf_attachment *import_attach = gem->import_attach; struct drm_format_name_buf format_name; - void *src = cma_obj->vaddr; + void *src = shmem->vaddr; int ret = 0; if (import_attach) { @@ -210,7 +216,8 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_clip_rect *clips, unsigned int num_clips) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); struct tinydrm_device *tdev = fb->dev->dev_private; struct mipi_dbi *mipi = mipi_dbi_from_tinydrm(tdev); bool swap = mipi->swap_bytes; @@ -235,7 +242,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, if (ret) return ret; } else { - tr = cma_obj->vaddr; + tr = shmem->vaddr; } mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, @@ -252,7 +259,7 @@ static int mipi_dbi_fb_dirty(struct drm_framebuffer *fb, } static const struct drm_framebuffer_funcs mipi_dbi_fb_funcs = { - .destroy = drm_gem_fb_destroy, + .destroy = tinydrm_fb_destroy, .create_handle = drm_gem_fb_create_handle, .dirty = tinydrm_fb_dirty, }; @@ -882,31 +889,12 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi, { size_t tx_size = tinydrm_spi_max_transfer_size(spi, 0); struct device *dev = &spi->dev; - int ret; if (tx_size < 16) { DRM_ERROR("SPI transmit buffer too small: %zu\n", tx_size); return -EINVAL; } - /* - * Even though it's not the SPI device that does DMA (the master does), - * the dma mask is necessary for the dma_alloc_wc() in - * drm_gem_cma_create(). The dma_addr returned will be a physical - * adddress which might be different from the bus address, but this is - * not a problem since the address will not be used. - * The virtual address is used in the transfer and the SPI core - * re-maps it on the SPI master device using the DMA streaming API - * (spi_map_buf()). - */ - if (!dev->coherent_dma_mask) { - ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); - if (ret) { - dev_warn(dev, "Failed to set dma mask %d\n", ret); - return ret; - } - } - mipi->spi = spi; mipi->read_commands = mipi_dbi_dcs_read_commands; diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tinydrm/repaper.c index 50a1d4216ce7..82d8c6bf0c91 100644 --- a/drivers/gpu/drm/tinydrm/repaper.c +++ b/drivers/gpu/drm/tinydrm/repaper.c @@ -26,7 +26,9 @@ #include <linux/spi/spi.h> #include <linux/thermal.h> +#include <drm/drm_drv.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> #include <drm/tinydrm/tinydrm.h> #include <drm/tinydrm/tinydrm-helpers.h> @@ -526,8 +528,9 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, struct drm_clip_rect *clips, unsigned int num_clips) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); + struct dma_buf_attachment *import_attach = gem->import_attach; struct tinydrm_device *tdev = fb->dev->dev_private; struct repaper_epd *epd = epd_from_tinydrm(tdev); struct drm_clip_rect clip; @@ -559,7 +562,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, goto out_free; } - tinydrm_xrgb8888_to_gray8(buf, cma_obj->vaddr, fb, &clip); + tinydrm_xrgb8888_to_gray8(buf, shmem->vaddr, fb, &clip); if (import_attach) { ret = dma_buf_end_cpu_access(import_attach->dmabuf, @@ -624,7 +627,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb, } static const struct drm_framebuffer_funcs repaper_fb_funcs = { - .destroy = drm_gem_fb_destroy, + .destroy = tinydrm_fb_destroy, .create_handle = drm_gem_fb_create_handle, .dirty = tinydrm_fb_dirty, }; @@ -876,13 +879,13 @@ static const struct drm_display_mode repaper_e2271cs021_mode = { static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x00 }; -DEFINE_DRM_GEM_CMA_FOPS(repaper_fops); +DEFINE_DRM_GEM_SHMEM_FOPS(repaper_fops); static struct drm_driver repaper_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, .fops = &repaper_fops, - TINYDRM_GEM_DRIVER_OPS, + DRM_GEM_SHMEM_DRIVER_OPS, .name = "repaper", .desc = "Pervasive Displays RePaper e-ink panels", .date = "20170405", @@ -929,15 +932,6 @@ static int repaper_probe(struct spi_device *spi) model = spi_id->driver_data; } - /* The SPI device is used to allocate dma memory */ - if (!dev->coherent_dma_mask) { - ret = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32)); - if (ret) { - dev_warn(dev, "Failed to set dma mask %d\n", ret); - return ret; - } - } - epd = devm_kzalloc(dev, sizeof(*epd), GFP_KERNEL); if (!epd) return -ENOMEM; diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tinydrm/st7586.c index 2fcbc3067d71..340c9be2613b 100644 --- a/drivers/gpu/drm/tinydrm/st7586.c +++ b/drivers/gpu/drm/tinydrm/st7586.c @@ -17,8 +17,10 @@ #include <linux/spi/spi.h> #include <video/mipi_display.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> #include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/tinydrm-helpers.h> @@ -88,9 +90,10 @@ static void st7586_xrgb8888_to_gray332(u8 *dst, void *vaddr, static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, struct drm_clip_rect *clip) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; - void *src = cma_obj->vaddr; + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct dma_buf_attachment *import_attach = gem->import_attach; + struct drm_gem_shmem_object *shmem = to_drm_gem_shmem_obj(gem); + void *src = shmem->vaddr; int ret = 0; if (import_attach) { @@ -156,7 +159,7 @@ static int st7586_fb_dirty(struct drm_framebuffer *fb, } static const struct drm_framebuffer_funcs st7586_fb_funcs = { - .destroy = drm_gem_fb_destroy, + .destroy = tinydrm_fb_destroy, .create_handle = drm_gem_fb_create_handle, .dirty = tinydrm_fb_dirty, }; @@ -297,13 +300,13 @@ static const struct drm_display_mode st7586_mode = { TINYDRM_MODE(178, 128, 37, 27), }; -DEFINE_DRM_GEM_CMA_FOPS(st7586_fops); +DEFINE_DRM_GEM_SHMEM_FOPS(st7586_fops); static struct drm_driver st7586_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, .fops = &st7586_fops, - TINYDRM_GEM_DRIVER_OPS, + DRM_GEM_SHMEM_DRIVER_OPS, .debugfs_init = mipi_dbi_debugfs_init, .name = "st7586", .desc = "Sitronix ST7586", diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tinydrm/st7735r.c index 3081bc57c116..1108088a1a03 100644 --- a/drivers/gpu/drm/tinydrm/st7735r.c +++ b/drivers/gpu/drm/tinydrm/st7735r.c @@ -14,8 +14,10 @@ #include <linux/spi/spi.h> #include <video/mipi_display.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_shmem_helper.h> #include <drm/tinydrm/mipi-dbi.h> #include <drm/tinydrm/tinydrm-helpers.h> @@ -113,13 +115,13 @@ static const struct drm_display_mode jd_t18003_t01_mode = { TINYDRM_MODE(128, 160, 28, 35), }; -DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops); +DEFINE_DRM_GEM_SHMEM_FOPS(st7735r_fops); static struct drm_driver st7735r_driver = { .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, .fops = &st7735r_fops, - TINYDRM_GEM_DRIVER_OPS, + DRM_GEM_SHMEM_DRIVER_OPS, .debugfs_init = mipi_dbi_debugfs_init, .name = "st7735r", .desc = "Sitronix ST7735R", diff --git a/include/drm/tinydrm/tinydrm.h b/include/drm/tinydrm/tinydrm.h index fe9827d0ca8a..e2cb254125c5 100644 --- a/include/drm/tinydrm/tinydrm.h +++ b/include/drm/tinydrm/tinydrm.h @@ -10,10 +10,15 @@ #ifndef __LINUX_TINYDRM_H #define __LINUX_TINYDRM_H -#include <drm/drm_gem_cma_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <linux/mutex.h> #include <drm/drm_simple_kms_helper.h> +struct drm_driver; +struct drm_framebuffer; +struct drm_file; +struct drm_clip_rect; +struct drm_framebuffer_funcs; + /** * struct tinydrm_device - tinydrm device */ @@ -53,27 +58,6 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe) return container_of(pipe, struct tinydrm_device, pipe); } -/** - * TINYDRM_GEM_DRIVER_OPS - default tinydrm gem operations - * - * This macro provides a shortcut for setting the tinydrm GEM operations in - * the &drm_driver structure. - */ -#define TINYDRM_GEM_DRIVER_OPS \ - .gem_free_object_unlocked = tinydrm_gem_cma_free_object, \ - .gem_print_info = drm_gem_cma_print_info, \ - .gem_vm_ops = &drm_gem_cma_vm_ops, \ - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, \ - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, \ - .gem_prime_import = drm_gem_prime_import, \ - .gem_prime_export = drm_gem_prime_export, \ - .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, \ - .gem_prime_import_sg_table = tinydrm_gem_cma_prime_import_sg_table, \ - .gem_prime_vmap = drm_gem_cma_prime_vmap, \ - .gem_prime_vunmap = drm_gem_cma_prime_vunmap, \ - .gem_prime_mmap = drm_gem_cma_prime_mmap, \ - .dumb_create = drm_gem_cma_dumb_create - /** * TINYDRM_MODE - tinydrm display mode * @hd: Horizontal resolution, width @@ -97,11 +81,7 @@ pipe_to_tinydrm(struct drm_simple_display_pipe *pipe) .type = DRM_MODE_TYPE_DRIVER, \ .clock = 1 /* pass validation */ -void tinydrm_gem_cma_free_object(struct drm_gem_object *gem_obj); -struct drm_gem_object * -tinydrm_gem_cma_prime_import_sg_table(struct drm_device *drm, - struct dma_buf_attachment *attach, - struct sg_table *sgt); +void tinydrm_fb_destroy(struct drm_framebuffer *fb); int devm_tinydrm_init(struct device *parent, struct tinydrm_device *tdev, const struct drm_framebuffer_funcs *fb_funcs, struct drm_driver *driver);